Skip to content

Commit

Permalink
Add RequestTransformer
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyaw Myint Thein committed Nov 3, 2021
1 parent 38cd38d commit 91363c3
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/kyawmyintthein/rz-lura-martian
go 1.13

require (
github.com/clbanning/mxj v1.8.4
github.com/google/martian v2.1.0+incompatible
github.com/luraproject/lura v1.4.1
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/devopsfaith/flatmap v0.0.0-20200601181759-8521186182fc h1:WM1VdC8LW8GIZUJuvXgQWm6LcZ8niL0D0WVuC3lKkQU=
github.com/devopsfaith/flatmap v0.0.0-20200601181759-8521186182fc/go.mod h1:J9Y/58s7wx7HbHT3i4UKNwLGuBB9qCf0/JUdEFGDPmA=
Expand All @@ -21,9 +23,11 @@ github.com/urfave/negroni v0.3.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn
github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI=
github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72 h1:PdU68SuVQNpTFEyGl0zoQOMysY+E0innv/QbAqV853w=
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
Expand Down
1 change: 1 addition & 0 deletions martian.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func NewConfiguredBackendFactory(logger logging.Logger, ref func(*config.Backend
parse.Register("static.Modifier", staticModifierFromJSON)
parse.Register("body.FromQueryString", queryModifierFromJSON)
parse.Register("body.FromHeader", headerModifierFromJSON)
parse.Register("request.Transform", requestTransformerFromJSON)
return func(remote *config.Backend) proxy.Proxy {
re := ref(remote)
result, ok := ConfigGetter(remote.ExtraConfig).(Result)
Expand Down
114 changes: 114 additions & 0 deletions request_modifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package rzluramartian

import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"

"github.com/clbanning/mxj"
"github.com/google/martian/parse"
"golang.org/x/net/html/charset"
)

const (
_contentType_JSON = "json"
_contentType_XML = "xml"
)

type (
RequestBodyModifierConfig struct {
OriginalContentType string `json:"original_content_type"`
ExpectedContentType string `json:"expected_content_type"`
}

RequestBodyModifier struct {
originalContentType string
expectedContentType string
}
)

func (m *RequestBodyModifier) ModifyRequest(req *http.Request) error {
if req.Body == nil {
return nil
}

var v map[string]interface{}
switch m.expectedContentType {
case _contentType_XML:
mxj.XmlCharsetReader = charset.NewReaderLabel
mv, err := mxj.NewMapXmlReader(xmlReader{r: req.Body})
if err != nil {
return err
}
v = mv
default:
// Default is JSON
payloadBytes, err := ioutil.ReadAll(req.Body)
if err != nil {
return err
}
req.Body.Close()
err = json.Unmarshal(payloadBytes, &v)
if err != nil {
return err
}
}

switch m.originalContentType {
case _contentType_XML:
transformedDataBytes, err := mxj.AnyXml(v)
if err != nil {
return err
}

req.Header.Del("Content-Type")
req.Header.Set("Content-Type", "application/xml")
req.ContentLength = int64(len(transformedDataBytes))
req.Body = ioutil.NopCloser(bytes.NewReader(transformedDataBytes))
default:
transformedDataBytes, err := json.Marshal(v)
if err != nil {
return err
}
req.Header.Del("Content-Type")
req.Header.Set("Content-Type", "application/json")
req.ContentLength = int64(len(transformedDataBytes))
req.Body = ioutil.NopCloser(bytes.NewReader(transformedDataBytes))
}

return nil
}

type xmlReader struct {
r io.Reader
}

func (x xmlReader) Read(p []byte) (n int, err error) {
n, err = x.r.Read(p)

if err != io.EOF {
return n, err
}

if len(p) == n {
return n, nil
}

p[n] = ([]byte("\n"))[0]
return n + 1, err
}

func requestTransformerFromJSON(b []byte) (*parse.Result, error) {
cfg := &RequestBodyModifierConfig{}
if err := json.Unmarshal(b, cfg); err != nil {
return nil, err
}

mod := &RequestBodyModifier{
expectedContentType: cfg.ExpectedContentType,
originalContentType: cfg.OriginalContentType,
}
return parse.NewResult(mod, []parse.ModifierType{parse.Request})
}

0 comments on commit 91363c3

Please sign in to comment.