Skip to content

Commit

Permalink
Add JQ tests, and make compilation conditional
Browse files Browse the repository at this point in the history
  • Loading branch information
buger committed Mar 27, 2018
1 parent 0744345 commit 16b2ffa
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 39 deletions.
42 changes: 6 additions & 36 deletions api_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ import (
"path/filepath"
"regexp"
"strings"
"sync"
"sync/atomic"
"text/template"
"time"

"github.com/rubyist/circuitbreaker"

"sync"

"github.com/TykTechnologies/gojsonschema"
"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/config"
"github.com/TykTechnologies/tyk/storage"
"sync"
)

const (
Expand Down Expand Up @@ -119,12 +119,6 @@ type TransformSpec struct {
Template *template.Template
}

type TransformJQSpec struct {
apidef.TransformJQMeta
sync.Mutex
JQFilter *JQ
}

type ExtendedCircuitBreakerMeta struct {
apidef.CircuitBreakerMeta
CB *circuit.Breaker
Expand Down Expand Up @@ -536,34 +530,6 @@ func (a APIDefinitionLoader) compileTransformPathSpec(paths []apidef.TemplateMet
return urlSpec
}

func (a *APIDefinitionLoader) compileTransformJQPathSpec(paths []apidef.TransformJQMeta, stat URLStatus) []URLSpec {
urlSpec := []URLSpec{}

log.Debug("Checking for JQ tranform paths ...")
for _, stringSpec := range paths {
newSpec := URLSpec{}
a.generateRegex(stringSpec.Path, &newSpec, stat)
newTransformSpec := TransformJQSpec{TransformJQMeta: stringSpec}

var err error
newTransformSpec.JQFilter, err = NewJQ(stringSpec.Filter)

if stat == TransformedJQ {
newSpec.TransformJQAction = newTransformSpec
} else {
newSpec.TransformJQResponseAction = newTransformSpec
}

if err == nil {
urlSpec = append(urlSpec, newSpec)
} else {
log.Error("JQ Filter load failure! Skipping transformation: ", err)
}
}

return urlSpec
}

func (a APIDefinitionLoader) compileInjectedHeaderSpec(paths []apidef.HeaderInjectionMeta, stat URLStatus) []URLSpec {
// transform an extended configuration URL into an array of URLSpecs
// This way we can iterate the whole array once, on match we break with status
Expand Down Expand Up @@ -975,6 +941,10 @@ func (a *APISpec) CheckSpecMatchesStatus(r *http.Request, rxPaths []URLSpec, mod
if v.InjectHeadersResponse.Path != ctxGetUrlRewritePath(r) {
continue
}
} else if mode == TransformedJQResponse {
if v.TransformJQResponseAction.Path != ctxGetUrlRewritePath(r) {
continue
}
} else {
continue
}
Expand Down
4 changes: 4 additions & 0 deletions helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func bundleHandleFunc(w http.ResponseWriter, r *http.Request) {
type testHttpResponse struct {
Method string
Url string
Body string
Headers map[string]string
Form map[string]string
}
Expand Down Expand Up @@ -128,11 +129,14 @@ func testHttpHandler() *mux.Router {
}
r.URL.Opaque = r.URL.RawPath
w.Header().Set("X-Tyk-Mock", "1")
body, _ := ioutil.ReadAll(r.Body)

err := json.NewEncoder(w).Encode(testHttpResponse{
Method: r.Method,
Url: r.URL.String(),
Headers: firstVals(r.Header),
Form: firstVals(r.Form),
Body: string(body),
})
if err != nil {
httpError(w, http.StatusInternalServerError)
Expand Down
4 changes: 3 additions & 1 deletion jq.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// +build jq

package main

// #cgo LDFLAGS: -l:libjq.a -l:libonig.a -lm
// #cgo LDFLAGS: -ljq
// #include <jq.h>
// #include <jv.h>
import "C"
Expand Down
42 changes: 41 additions & 1 deletion mw_transform_jq.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
// +build jq

package main

import (
"bytes"
"encoding/json"
"errors"
"github.com/Sirupsen/logrus"
"io"
"io/ioutil"
"net/http"
"sync"

"github.com/Sirupsen/logrus"

"github.com/TykTechnologies/tyk/apidef"
)

type TransformJQMiddleware struct {
Expand Down Expand Up @@ -141,3 +147,37 @@ func lockedJQTransform(t *TransformJQSpec, jqObj map[string]interface{}) (JQResu

return jqResult, nil
}

type TransformJQSpec struct {
apidef.TransformJQMeta
sync.Mutex
JQFilter *JQ
}

func (a *APIDefinitionLoader) compileTransformJQPathSpec(paths []apidef.TransformJQMeta, stat URLStatus) []URLSpec {
urlSpec := []URLSpec{}

log.Debug("Checking for JQ tranform paths ...")
for _, stringSpec := range paths {
newSpec := URLSpec{}
a.generateRegex(stringSpec.Path, &newSpec, stat)
newTransformSpec := TransformJQSpec{TransformJQMeta: stringSpec}

var err error
newTransformSpec.JQFilter, err = NewJQ(stringSpec.Filter)

if stat == TransformedJQ {
newSpec.TransformJQAction = newTransformSpec
} else {
newSpec.TransformJQResponseAction = newTransformSpec
}

if err == nil {
urlSpec = append(urlSpec, newSpec)
} else {
log.Error("JQ Filter load failure! Skipping transformation: ", err)
}
}

return urlSpec
}
41 changes: 41 additions & 0 deletions mw_transform_jq_dummy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// +build !jq

package main

import (
"net/http"

"github.com/TykTechnologies/tyk/apidef"
)

type TransformJQMiddleware struct {
BaseMiddleware
}

func (t *TransformJQMiddleware) Name() string {
return "TransformJQMiddleware"
}

func (t *TransformJQMiddleware) EnabledForSpec() bool {
for _, version := range t.Spec.VersionData.Versions {
if len(version.ExtendedPaths.TransformJQ) > 0 {
log.Warning("JQ transform not supported.")
return false
}
}

return false
}

// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail
func (t *TransformJQMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
return nil, 200
}

type TransformJQSpec struct {
apidef.TransformJQMeta
}

func (a *APIDefinitionLoader) compileTransformJQPathSpec(paths []apidef.TransformJQMeta, stat URLStatus) []URLSpec {
return []URLSpec{}
}
37 changes: 37 additions & 0 deletions mw_transform_jq_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// +build jq

package main

import (
"testing"

"github.com/TykTechnologies/tyk/apidef"
"github.com/TykTechnologies/tyk/test"
)

func TestJQMiddleware(t *testing.T) {
ts := newTykTestServer()
defer ts.Close()

buildAndLoadAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/"
spec.EnableContextVars = true
updateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
v.UseExtendedPaths = true
v.ExtendedPaths.TransformJQ = []apidef.TransformJQMeta{{
Path: "/jq",
Method: "POST",
Filter: `{"body": (.body + {"TRANSFORMED-REQUEST-BY-JQ": true, path: ._tyk_context.path, user_agent: ._tyk_context.headers_User_Agent}), "rewrite_headers": {"X-added-rewrite-headers": .body.foo}, "tyk_context": { "foo-val": .body.foo}}`,
}}
})
})

bodyContextVar := `\"path\":\"/jq\"`
headersBodyVar := `"X-Added-Rewrite-Headers":"bar"`

ts.Run(t, []test.TestCase{
{Path: "/jq", Method: "POST", Data: `{"foo": "bar"}`, Code: 200, BodyMatch: bodyContextVar},
{Path: "/jq", Method: "POST", Data: `{"foo": "bar"}`, Code: 200, BodyMatch: headersBodyVar},
{Path: "/jq", Method: "POST", Data: `wrong json`, Code: 415},
}...)
}
5 changes: 4 additions & 1 deletion res_handler_jq_transform.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
//+build jq

package main

import (
"bytes"
"encoding/json"
"github.com/TykTechnologies/tyk/user"
"io/ioutil"
"net/http"
"strconv"

"github.com/TykTechnologies/tyk/user"
)

type ResponseTransformJQMiddleware struct {
Expand Down
24 changes: 24 additions & 0 deletions res_handler_jq_transform_dummy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//+build !jq

package main

import (
"net/http"

"github.com/TykTechnologies/tyk/user"
)

type ResponseTransformJQMiddleware struct {
Spec *APISpec
}

func (h *ResponseTransformJQMiddleware) Init(c interface{}, spec *APISpec) error {
h.Spec = spec

return nil
}

func (h *ResponseTransformJQMiddleware) HandleResponse(rw http.ResponseWriter, res *http.Response, req *http.Request, ses *user.SessionState) error {
log.Warning("JQ transforms not supported")
return nil
}

0 comments on commit 16b2ffa

Please sign in to comment.