Skip to content

Commit

Permalink
RequestAdaptor support all fields template (#910)
Browse files Browse the repository at this point in the history
* RequestAdaptor support template

* ResponseAdaptor support template

* fix race conditions

* 1. kick out some fields  and won't be supported by template
2. move the requestadaptor and responseadaptor out from their own folder

* template support for RequestAdaptor.Path
merge setRequest and setRequest in builder unittest

* update doc

* Update doc/reference/filters.md

Co-authored-by: samanhappy <[email protected]>

* Update doc/reference/filters.md

Co-authored-by: samanhappy <[email protected]>

* fix for json:",inline"

---------

Co-authored-by: lawrence_he <[email protected]>
Co-authored-by: samanhappy <[email protected]>
  • Loading branch information
3 people committed Feb 15, 2023
1 parent d08528a commit 58d671a
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 158 deletions.
55 changes: 40 additions & 15 deletions doc/reference/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,16 +418,20 @@ path:

### Configuration

| Name | Type | Description | Required |
| -----------| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| method | string | If provided, the method of the original request is replaced by the value of this option | No |
| path | [pathadaptor.Spec](#pathadaptorSpec) | Rules to revise request path | No |
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| host | string | If provided the host of the original request is replaced by the value of this option. | No |
| decompress | string | If provided, the request body is replaced by the value of decompressed body. Now support "gzip" decompress | No |
| compress | string | If provided, the request body is replaced by the value of compressed body. Now support "gzip" compress | No |
| Name | Type | Description | Required |
| -----------| -------------------------------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- |
| method | string | If provided, the method of the original request is replaced by the value of this option | No |
| path | [pathadaptor.Spec](#pathadaptorSpec) | Rules to revise request path | No |
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| host | string | If provided the host of the original request is replaced by the value of this option. | No |
| decompress | string | If provided, the request body is replaced by the value of decompressed body. Now support "gzip" decompress | No |
| compress | string | If provided, the request body is replaced by the value of compressed body. Now support "gzip" compress | No |
| sign | [requestadaptor.SignerSpec](#requestadaptorsignerspec) | If provided, sign the request using the [Amazon Signature V4](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html) signing process with the configuration | No |
| template | string | template to create request adaptor, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
NOTE: template field takes higher priority than the static field with the same name.

### Results

Expand Down Expand Up @@ -547,12 +551,16 @@ header:

### Configuration

| Name | Type | Description | Required |
| ------ | -------- |-------------- | -------- |
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| compress | string | compress body, currently only support gzip | No |
| decompress | string | decompress body, currently only support gzip | No |
| Name | Type | Description | Required |
| ------ | -------- |---------------------------------------------------------------------------------------------------------------------| -------- |
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| compress | string | compress body, currently only support gzip | No |
| decompress | string | decompress body, currently only support gzip | No |
| template | string | template to create response adaptor, please refer the [template](#template-of-builder-filters) for more information | No |
| leftDelim | string | left action delimiter of the template, default is `{{` | No |
| rightDelim | string | right action delimiter of the template, default is `}}` | No |
NOTE: template field takes higher priority than the static field with the same name.

### Results

Expand Down Expand Up @@ -1688,3 +1696,20 @@ result YAML varies from filters and protocols.
| statusCode | int | HTTP status code, default is 200. | No |
| headers | map[string][]string | Headers of the result request. | No |
| body | string | Body of the result request. | No |

* **Schema of RequestAdaptor**

| Name | Type | Description | Required |
|------|------|-------------|----------|
| method | string | If provided, the method of the original request is replaced by the value of this option | No |
| path | [pathadaptor.Spec](#pathadaptorSpec) | Rules to revise request path | No |
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
| host | string | If provided the host of the original request is replaced by the value of this option. | No |

* **Schema of ResponseAdaptor**

| Name | Type | Description | Required |
|------|------|-------------|----------|
| header | [httpheader.AdaptSpec](#httpheaderAdaptSpec) | Rules to revise request header | No |
| body | string | If provided the body of the original request is replaced by the value of this option. | No |
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
* limitations under the License.
*/

package requestadaptor
package builder

import (
"fmt"
"io"
"net/http"
"strconv"
"time"

Expand All @@ -35,8 +36,8 @@ import (
)

const (
// Kind is the kind of RequestAdaptor.
Kind = "RequestAdaptor"
// RequestAdaptorKind is the kind of RequestAdaptor.
RequestAdaptorKind = "RequestAdaptor"

resultDecompressFailed = "decompressFailed"
resultCompressFailed = "compressFailed"
Expand All @@ -46,18 +47,18 @@ const (
keyContentEncoding = "Content-Encoding"
)

var kind = &filters.Kind{
Name: Kind,
var requestAdaptorKind = &filters.Kind{
Name: RequestAdaptorKind,
Description: "RequestAdaptor adapts request.",
Results: []string{
resultDecompressFailed,
resultCompressFailed,
},
DefaultSpec: func() filters.Spec {
return &Spec{}
return &RequestAdaptorSpec{}
},
CreateInstance: func(spec filters.Spec) filters.Filter {
return &RequestAdaptor{spec: spec.(*Spec)}
return &RequestAdaptor{spec: spec.(*RequestAdaptorSpec)}
},
}

Expand Down Expand Up @@ -125,30 +126,36 @@ var signerConfigs = map[string]signerConfig{
}

func init() {
filters.Register(kind)
filters.Register(requestAdaptorKind)
}

type (
// RequestAdaptor is filter RequestAdaptor.
RequestAdaptor struct {
spec *Spec
spec *RequestAdaptorSpec
Builder

pa *pathadaptor.PathAdaptor
signer *signer.Signer
}

// Spec is HTTPAdaptor Spec.
Spec struct {
// RequestAdaptorSpec is HTTPAdaptor RequestAdaptorSpec.
RequestAdaptorSpec struct {
filters.BaseSpec `json:",inline"`
Spec `json:",inline"`

Host string `json:"host" jsonschema:"omitempty"`
Method string `json:"method" jsonschema:"omitempty,format=httpmethod"`
Path *pathadaptor.Spec `json:"path,omitempty" jsonschema:"omitempty"`
Header *httpheader.AdaptSpec `json:"header,omitempty" jsonschema:"omitempty"`
Body string `json:"body" jsonschema:"omitempty"`
Compress string `json:"compress" jsonschema:"omitempty"`
Decompress string `json:"decompress" jsonschema:"omitempty"`
Sign *SignerSpec `json:"sign,omitempty" jsonschema:"omitempty"`
RequestAdaptorTemplate `json:",inline"`
Compress string `json:"compress" jsonschema:"omitempty"`
Decompress string `json:"decompress" jsonschema:"omitempty"`
Sign *SignerSpec `json:"sign,omitempty" jsonschema:"omitempty"`
}

RequestAdaptorTemplate struct {
Host string `json:"host" jsonschema:"omitempty"`
Method string `json:"method" jsonschema:"omitempty,format=httpmethod"`
Path *pathadaptor.Spec `json:"path,omitempty" jsonschema:"omitempty"`
Header *httpheader.AdaptSpec `json:"header,omitempty" jsonschema:"omitempty"`
Body string `json:"body" jsonschema:"omitempty"`
}

// SignerSpec is the spec of the request signer.
Expand All @@ -165,7 +172,7 @@ type (
)

// Validate verifies that at least one of the validations is defined.
func (spec *Spec) Validate() error {
func (spec *RequestAdaptorSpec) Validate() error {
if spec.Decompress != "" && spec.Decompress != "gzip" {
return fmt.Errorf("RequestAdaptor only support decompress type of gzip")
}
Expand Down Expand Up @@ -198,7 +205,7 @@ func (ra *RequestAdaptor) Name() string {

// Kind returns the kind of RequestAdaptor.
func (ra *RequestAdaptor) Kind() *filters.Kind {
return kind
return requestAdaptorKind
}

// Spec returns the spec used by the RequestAdaptor
Expand Down Expand Up @@ -228,10 +235,12 @@ func (ra *RequestAdaptor) reload() {
}
ra.signer = signer.CreateFromSpec(&s.Spec)
}
if ra.spec.Template != "" {
ra.Builder.reload(&ra.spec.Spec)
}
}

func adaptHeader(req *httpprot.Request, as *httpheader.AdaptSpec) {
h := req.Std().Header
func adaptHeader(h http.Header, as *httpheader.AdaptSpec) {
for _, key := range as.Del {
h.Del(key)
}
Expand All @@ -248,30 +257,65 @@ func (ra *RequestAdaptor) Handle(ctx *context.Context) string {
req := ctx.GetInputRequest().(*httpprot.Request)
method, path := req.Method(), req.Path()

if ra.spec.Method != "" && ra.spec.Method != method {
ctx.AddTag(stringtool.Cat("requestAdaptor: method ", method, " adapted to ", ra.spec.Method))
req.SetMethod(ra.spec.Method)
templateSpec := &RequestAdaptorTemplate{}
if ra.spec.Template != "" {
data, err := prepareBuilderData(ctx)
if err != nil {
logger.Warnf("prepareBuilderData failed: %v", err)
return resultBuildErr
}
if err = ra.Builder.build(data, templateSpec); err != nil {
msgFmt := "RequestAdaptor(%s): failed to build adaptor info: %v"
logger.Warnf(msgFmt, ra.Name(), err)
return resultBuildErr
}
}
newMethod := templateSpec.Method
if newMethod == "" {
newMethod = ra.spec.Method
}
if newMethod != "" && newMethod != method {
ctx.AddTag(stringtool.Cat("requestAdaptor: method ", method, " adapted to ", newMethod))
req.SetMethod(newMethod)
}

if ra.pa != nil {
adaptedPath := ra.pa.Adapt(path)
var newPa *pathadaptor.PathAdaptor
if templateSpec.Path == nil {
newPa = ra.pa
} else {
newPa = pathadaptor.New(templateSpec.Path)
}
if newPa != nil {
adaptedPath := newPa.Adapt(path)
if adaptedPath != path {
ctx.AddTag(stringtool.Cat("requestAdaptor: path ", path, " adapted to ", adaptedPath))
}
req.SetPath(adaptedPath)
}

if ra.spec.Header != nil {
adaptHeader(req, ra.spec.Header)
newHeader := templateSpec.Header
if newHeader == nil {
newHeader = ra.spec.Header
}
if newHeader != nil {
adaptHeader(req.Std().Header, newHeader)
}

if len(ra.spec.Body) != 0 {
req.SetPayload([]byte(ra.spec.Body))
newBody := templateSpec.Body
if newBody == "" {
newBody = ra.spec.Body
}
if len(newBody) != 0 {
req.SetPayload([]byte(newBody))
req.Std().Header.Del("Content-Encoding")
}

if len(ra.spec.Host) != 0 {
req.SetHost(ra.spec.Host)
newHost := templateSpec.Host
if newHost == "" {
newHost = ra.spec.Host
}
if len(newHost) != 0 {
req.SetHost(newHost)
}

if ra.spec.Compress != "" {
Expand Down
Loading

0 comments on commit 58d671a

Please sign in to comment.