Skip to content

Commit

Permalink
Merge 990474b into 23e56e7
Browse files Browse the repository at this point in the history
  • Loading branch information
dskoval committed Nov 9, 2018
2 parents 23e56e7 + 990474b commit 338197e
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 27 deletions.
8 changes: 8 additions & 0 deletions apidef/api_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,14 @@ func (s *StringRegexMap) Check(value string) string {
return s.matchRegex.FindString(value)
}

func (s *StringRegexMap) FindStringSubmatch(value string) []string {
return s.matchRegex.FindStringSubmatch(value)
}

func (s *StringRegexMap) FindAllStringSubmatch(value string, n int) [][]string {
return s.matchRegex.FindAllStringSubmatch(value, n)
}

func (s *StringRegexMap) Init() error {
var err error
if s.matchRegex, err = regexp.Compile(s.MatchPattern); err != nil {
Expand Down
85 changes: 61 additions & 24 deletions mw_url_rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import (
)

const (
metaLabel = "$tyk_meta."
contextLabel = "$tyk_context."
metaLabel = "$tyk_meta."
contextLabel = "$tyk_context."
triggerKeyPrefix = "trigger"
triggerKeySep = "-"
)

var dollarMatch = regexp.MustCompile(`\$\d+`)
Expand Down Expand Up @@ -178,7 +180,7 @@ func replaceTykVariables(r *http.Request, in string, escape bool) string {

replaceGroups := contextMatch.FindAllStringSubmatch(in, -1)
for _, v := range replaceGroups {
contextKey := strings.Replace(v[0], "$tyk_context.", "", 1)
contextKey := strings.Replace(v[0], contextLabel, "", 1)

if val, ok := contextData[contextKey]; ok {
valStr := valToStr(val)
Expand All @@ -202,7 +204,7 @@ func replaceTykVariables(r *http.Request, in string, escape bool) string {

replaceGroups := metaMatch.FindAllStringSubmatch(in, -1)
for _, v := range replaceGroups {
contextKey := strings.Replace(v[0], "$tyk_meta.", "", 1)
contextKey := strings.Replace(v[0], metaLabel, "", 1)

val, ok := session.MetaData[contextKey]
if ok {
Expand Down Expand Up @@ -362,10 +364,13 @@ func checkHeaderTrigger(r *http.Request, options map[string]apidef.StringRegexMa
vals, ok := r.Header[mhCN]
if ok {
for i, v := range vals {
b := mr.Check(v)
if len(b) > 0 {
kn := "trigger-" + strconv.Itoa(triggernum) + "-" + mhCN + "-" + strconv.Itoa(i)
contextData[kn] = b
match := mr.FindStringSubmatch(v)
if len(match) > 0 {
kn := buildTriggerKey(triggernum, mhCN, i)
contextData[kn] = match[0]

addGroupsToContextData(&contextData, kn, match[1:])

fCount++
}
}
Expand All @@ -392,11 +397,13 @@ func checkQueryString(r *http.Request, options map[string]apidef.StringRegexMap,
vals, ok := qvals[mv]
if ok {
for i, v := range vals {
b := mr.Check(v)
if len(b) > 0 {
kn := "trigger-" + strconv.Itoa(triggernum) + "-" + mv + "-" + strconv.Itoa(i)
match := mr.FindStringSubmatch(v)
if len(match) > 0 {
kn := buildTriggerKey(triggernum, mv, i)
contextData[kn] = match[0]

addGroupsToContextData(&contextData, kn, match[1:])

contextData[kn] = b
fCount++
}
}
Expand All @@ -422,11 +429,13 @@ func checkPathParts(r *http.Request, options map[string]apidef.StringRegexMap, a
pathParts := strings.Split(r.URL.Path, "/")

for _, part := range pathParts {
b := mr.Check(part)
if len(b) > 0 {
kn := "trigger-" + strconv.Itoa(triggernum) + "-" + mv + "-" + strconv.Itoa(fCount)
match := mr.FindStringSubmatch(part)
if len(match) > 0 {
kn := buildTriggerKey(triggernum, mv, fCount)
contextData[kn] = match[0]

addGroupsToContextData(&contextData, kn, match[1:])

contextData[kn] = b
fCount++
}
}
Expand All @@ -452,11 +461,13 @@ func checkSessionTrigger(r *http.Request, sess *user.SessionState, options map[s
if ok {
val, valOk := rawVal.(string)
if valOk {
b := mr.Check(val)
if len(b) > 0 {
kn := "trigger-" + strconv.Itoa(triggernum) + "-" + mh
matches := mr.FindStringSubmatch(val)
if len(matches) > 0 {
kn := buildTriggerKey(triggernum, mh)
contextData[kn] = matches[0]

addGroupsToContextData(&contextData, kn, matches[1:])

contextData[kn] = b
fCount++
}
}
Expand All @@ -479,13 +490,39 @@ func checkPayload(r *http.Request, options apidef.StringRegexMap, triggernum int
contextData := ctxGetData(r)
bodyBytes, _ := ioutil.ReadAll(r.Body)

b := options.Check(string(bodyBytes))
if len(b) > 0 {
kn := "trigger-" + strconv.Itoa(triggernum) + "-payload"
matches := options.FindAllStringSubmatch(string(bodyBytes), -1)

contextData[kn] = string(b)
if len(matches) > 0 {
kn := buildTriggerKey(triggernum, "payload")
contextData[kn] = matches[0][0]

for i, match := range matches {
kn = buildTriggerKey(triggernum, "payload", i)
contextData[kn] = match[0]

addGroupsToContextData(&contextData, kn, match[1:])
}
return true
}

return false
}

func buildTriggerKey(num int, name string, indices ...int) string {
parts := []string{triggerKeyPrefix, strconv.Itoa(num), name}

if len(indices) > 0 {
for _, index := range indices {
parts = append(parts, strconv.Itoa(index))
}
}

return strings.Join(parts, triggerKeySep)
}

func addGroupsToContextData(cd *map[string]interface{}, keyPrefix string, groups []string) {
for i, g := range groups {
k := strings.Join([]string{keyPrefix, strconv.Itoa(i)}, triggerKeySep)
(*cd)[k] = g
}
}
144 changes: 143 additions & 1 deletion mw_url_rewrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,32 @@ func TestRewriterTriggers(t *testing.T) {
func() TestDef {
r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)

r.Header.Set("x-test", "hello-world")

hOpt := apidef.StringRegexMap{MatchPattern: "hello-(\\w+)"}
hOpt.Init()

return TestDef{
"Header Single Group",
"/test/straight/rewrite", "/change/to/me/ignore",
"/test/straight/rewrite", "/change/to/me/world",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
HeaderMatches: map[string]apidef.StringRegexMap{
"x-test": hOpt,
},
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0-0",
},
},
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)

patt := "bar"
r.Header.Set("x-test-Two", patt)

Expand Down Expand Up @@ -285,6 +311,30 @@ func TestRewriterTriggers(t *testing.T) {
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo-bar", nil)

hOpt := apidef.StringRegexMap{MatchPattern: "foo-(\\w+)"}
hOpt.Init()

return TestDef{
"Query Single Group",
"/test/query/rewrite", "/change/to/me/ignore",
"/test/query/rewrite", "/change/to/me/bar",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
QueryValMatches: map[string]apidef.StringRegexMap{
"x_test": hOpt,
},
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-x_test-0-0",
},
},
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo&y_test=bar", nil)

Expand Down Expand Up @@ -429,6 +479,52 @@ func TestRewriterTriggers(t *testing.T) {
r,
}
},
func() TestDef {
var jsonStr = []byte(`{"foo":"barxxx", "fooble":"baryyy"}`)
r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))

hOpt := apidef.StringRegexMap{MatchPattern: "bar\\w*"}
hOpt.Init()

return TestDef{
"Payload Multiple Match",
"/test/pl/rewrite", "/change/to/me/ignore",
"/test/pl/rewrite", "/change/to/me/barxxx/baryyy",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
PayloadMatches: hOpt,
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-payload-1",
},
},
r,
}
},
func() TestDef {
var jsonStr = []byte(`{"foo":"barxxx", "fooble":"baryyy"}`)
r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))

hOpt := apidef.StringRegexMap{MatchPattern: "bar(\\w*)"}
hOpt.Init()

return TestDef{
"Payload Multiple Match Groups",
"/test/pl/rewrite", "/change/to/me/ignore",
"/test/pl/rewrite", "/change/to/me/xxx/yyy",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
PayloadMatches: hOpt,
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0-0/$tyk_context.trigger-0-payload-1-0",
},
},
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
Expand All @@ -452,6 +548,29 @@ func TestRewriterTriggers(t *testing.T) {
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/foobar/rewrite", nil)
hOpt := apidef.StringRegexMap{MatchPattern: "foo(\\w+)"}
hOpt.Init()

return TestDef{
"PathPart Single Group",
"/test/foobar/rewrite", "/change/to/me/ignore",
"/test/foobar/rewrite", "/change/to/me/bar",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
PathPartMatches: map[string]apidef.StringRegexMap{
"pathpart": hOpt,
},
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0-0",
},
},
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/foo/rewrite/foo", nil)
hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
Expand Down Expand Up @@ -498,6 +617,29 @@ func TestRewriterTriggers(t *testing.T) {
r,
}
},
func() TestDef {
r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
hOpt := apidef.StringRegexMap{MatchPattern: "bar-(\\w+)"}
hOpt.Init()

return TestDef{
"Meta Simple Group",
"/test/foo/rewrite", "/change/to/me/ignore",
"/test/foo/rewrite", "/change/to/me/baz",
[]apidef.RoutingTrigger{
{
On: apidef.Any,
Options: apidef.RoutingTriggerOptions{
SessionMetaMatches: map[string]apidef.StringRegexMap{
"rewrite": hOpt,
},
},
RewriteTo: "/change/to/me/$tyk_context.trigger-0-rewrite-0",
},
},
r,
}
},
}
for _, tf := range tests {
tc := tf()
Expand All @@ -510,7 +652,7 @@ func TestRewriterTriggers(t *testing.T) {

ctxSetSession(tc.req, &user.SessionState{
MetaData: map[string]interface{}{
"rewrite": "bar",
"rewrite": "bar-baz",
},
}, "", false)

Expand Down
45 changes: 45 additions & 0 deletions regexp/cache_regexp_str_ret_slice_str.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package regexp

import (
"regexp"
"time"
)

type regexpStrRetSliceStrCache struct {
*cache
}

func newRegexpStrRetSliceStrCache(ttl time.Duration, isEnabled bool) *regexpStrRetSliceStrCache {
return &regexpStrRetSliceStrCache{
cache: newCache(
ttl,
isEnabled,
),
}
}

func (c *regexpStrRetSliceStrCache) do(r *regexp.Regexp, s string, noCacheFn func(s string) []string) []string {
// return if cache is not enabled
if !c.enabled() {
return noCacheFn(s)
}

// generate key, check key size
key := r.String() + s
if len(key) > maxKeySize {
return noCacheFn(s)
}

// cache hit
if res, found := c.getStrSlice(key); found {
return res
}

// cache miss, add to cache if value is not too big
res := noCacheFn(s)
if len(res) <= maxValueSize {
c.add(key, res)
}

return res
}
Loading

0 comments on commit 338197e

Please sign in to comment.