github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/mw_url_rewrite_test.go (about)

     1  package gateway
     2  
     3  import (
     4  	"net/http/httptest"
     5  	"sync"
     6  	"testing"
     7  
     8  	"github.com/TykTechnologies/tyk/test"
     9  
    10  	"bytes"
    11  	"net/http"
    12  
    13  	"github.com/TykTechnologies/tyk/apidef"
    14  	"github.com/TykTechnologies/tyk/user"
    15  )
    16  
    17  var testRewriterData = []struct {
    18  	name        string
    19  	pattern, to string
    20  	in, want    string
    21  }{
    22  	{
    23  		"Straight",
    24  		"/test/straight/rewrite", "/change/to/me",
    25  		"/test/straight/rewrite", "/change/to/me",
    26  	},
    27  	{
    28  		"OneVal",
    29  		"test/val/(.*)", "change/to/$1",
    30  		"/test/val/VALUE", "change/to/VALUE",
    31  	},
    32  	{
    33  		"ThreeVals",
    34  		"/test/val/(.*)/space/(.*)/and/then/(.*)", "/change/to/$1/$2/$3",
    35  		"/test/val/ONE/space/TWO/and/then/THREE", "/change/to/ONE/TWO/THREE",
    36  	},
    37  	{
    38  		"Reverse",
    39  		"/test/val/(.*)/space/(.*)/and/then/(.*)", "/change/to/$3/$2/$1",
    40  		"/test/val/ONE/space/TWO/and/then/THREE", "/change/to/THREE/TWO/ONE",
    41  	},
    42  	{
    43  		"Missing",
    44  		"/test/val/(.*)/space/(.*)/and/then/(.*)", "/change/to/$1/$2",
    45  		"/test/val/ONE/space/TWO/and/then/THREE", "/change/to/ONE/TWO",
    46  	},
    47  	{
    48  		"MissingAgain",
    49  		"/test/val/(.*)/space/(.*)/and/then/(.*)", "/change/to/$3/$1",
    50  		"/test/val/ONE/space/TWO/and/then/THREE", "/change/to/THREE/ONE",
    51  	},
    52  	{
    53  		"QS",
    54  		"(.*)", "$1&newParam=that",
    55  		"/foo/bar?param1=this", "/foo/bar?param1=this&newParam=that",
    56  	},
    57  	{
    58  		"QS2",
    59  		"/test/val/(.*)/space/(.*)/and/then(.*)", "/change/to/$2/$1$3",
    60  		"/test/val/ONE/space/TWO/and/then?param1=this", "/change/to/TWO/ONE?param1=this",
    61  	},
    62  }
    63  
    64  type testRewriterCase struct {
    65  	name     string
    66  	meta     *apidef.URLRewriteMeta
    67  	reqMaker func() *http.Request
    68  	want     string
    69  }
    70  
    71  func prepareRewriterCases() []testRewriterCase {
    72  	tcs := make([]testRewriterCase, len(testRewriterData))
    73  	for i, td := range testRewriterData {
    74  		reqTarget := td.in
    75  		tcs[i] = testRewriterCase{
    76  			name: td.name,
    77  			meta: &apidef.URLRewriteMeta{
    78  				MatchPattern: td.pattern,
    79  				RewriteTo:    td.to,
    80  			},
    81  			reqMaker: func() *http.Request {
    82  				return httptest.NewRequest("GET", reqTarget, nil)
    83  			},
    84  			want: td.want,
    85  		}
    86  	}
    87  	return tcs
    88  }
    89  
    90  func TestRewriter(t *testing.T) {
    91  	cases := prepareRewriterCases()
    92  	for _, tc := range cases {
    93  		t.Run(tc.name, func(t *testing.T) {
    94  			r := tc.reqMaker()
    95  			got, err := urlRewrite(tc.meta, r)
    96  			if err != nil {
    97  				t.Error("compile failed:", err)
    98  			}
    99  			if got != tc.want {
   100  				t.Errorf("rewrite failed, want %q, got %q", tc.want, got)
   101  			}
   102  		})
   103  	}
   104  }
   105  func BenchmarkRewriter(b *testing.B) {
   106  	cases := prepareRewriterCases()
   107  	//warm-up regexp caches
   108  	for _, tc := range cases {
   109  		r := tc.reqMaker()
   110  		urlRewrite(tc.meta, r)
   111  	}
   112  
   113  	b.ReportAllocs()
   114  	b.ResetTimer()
   115  	for _, tc := range cases {
   116  		for i := 0; i < b.N; i++ {
   117  			b.StopTimer()
   118  			r := tc.reqMaker()
   119  			b.StartTimer()
   120  			urlRewrite(tc.meta, r)
   121  		}
   122  	}
   123  }
   124  
   125  func TestRewriterTriggers(t *testing.T) {
   126  	type TestDef struct {
   127  		name        string
   128  		pattern, to string
   129  		in, want    string
   130  		triggerConf []apidef.RoutingTrigger
   131  		req         *http.Request
   132  	}
   133  	tests := []func() TestDef{
   134  		func() TestDef {
   135  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   136  
   137  			patt := "hello"
   138  			r.Header.Set("x-test", patt)
   139  
   140  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   141  			hOpt.Init()
   142  
   143  			return TestDef{
   144  				"Header Single",
   145  				"/test/straight/rewrite", "/change/to/me/ignore",
   146  				"/test/straight/rewrite", "/change/to/me/hello",
   147  				[]apidef.RoutingTrigger{
   148  					{
   149  						On: apidef.Any,
   150  						Options: apidef.RoutingTriggerOptions{
   151  							HeaderMatches: map[string]apidef.StringRegexMap{
   152  								"x-test": hOpt,
   153  							},
   154  						},
   155  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0",
   156  					},
   157  				},
   158  				r,
   159  			}
   160  		},
   161  		func() TestDef {
   162  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   163  
   164  			r.Header.Set("x-test", "hello-world")
   165  
   166  			hOpt := apidef.StringRegexMap{MatchPattern: "hello-(\\w+)"}
   167  			hOpt.Init()
   168  
   169  			return TestDef{
   170  				"Header Single Group",
   171  				"/test/straight/rewrite", "/change/to/me/ignore",
   172  				"/test/straight/rewrite", "/change/to/me/world",
   173  				[]apidef.RoutingTrigger{
   174  					{
   175  						On: apidef.Any,
   176  						Options: apidef.RoutingTriggerOptions{
   177  							HeaderMatches: map[string]apidef.StringRegexMap{
   178  								"x-test": hOpt,
   179  							},
   180  						},
   181  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0-0",
   182  					},
   183  				},
   184  				r,
   185  			}
   186  		},
   187  		func() TestDef {
   188  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   189  
   190  			patt := "bar"
   191  			r.Header.Set("x-test-Two", patt)
   192  
   193  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   194  			hOpt.Init()
   195  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   196  			hOpt2.Init()
   197  
   198  			return TestDef{
   199  				"Header Multi Any",
   200  				"/test/straight/rewrite", "/change/to/me/ignore",
   201  				"/test/straight/rewrite", "/change/to/me/bar",
   202  				[]apidef.RoutingTrigger{
   203  					{
   204  						On: apidef.Any,
   205  						Options: apidef.RoutingTriggerOptions{
   206  							HeaderMatches: map[string]apidef.StringRegexMap{
   207  								"x-test":     hOpt,
   208  								"x-test-Two": hOpt2,
   209  							},
   210  						},
   211  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-Two-0",
   212  					},
   213  				},
   214  				r,
   215  			}
   216  		},
   217  		func() TestDef {
   218  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   219  
   220  			patt := "bar"
   221  			r.Header.Set("x-test-Two", patt)
   222  
   223  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   224  			hOpt.Init()
   225  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   226  			hOpt2.Init()
   227  
   228  			return TestDef{
   229  				"Header Multi All Fail",
   230  				"/test/straight/rewrite", "/change/to/me/ignore",
   231  				"/test/straight/rewrite", "/change/to/me/ignore",
   232  				[]apidef.RoutingTrigger{
   233  					{
   234  						On: apidef.All,
   235  						Options: apidef.RoutingTriggerOptions{
   236  							HeaderMatches: map[string]apidef.StringRegexMap{
   237  								"x-test":     hOpt,
   238  								"x-test-Two": hOpt2,
   239  							},
   240  						},
   241  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-Two-0",
   242  					},
   243  				},
   244  				r,
   245  			}
   246  		},
   247  		func() TestDef {
   248  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   249  
   250  			r.Header.Set("x-test-Two", "bar")
   251  			r.Header.Set("x-test", "hello")
   252  
   253  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   254  			hOpt.Init()
   255  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   256  			hOpt2.Init()
   257  
   258  			return TestDef{
   259  				"Header Multi All Pass",
   260  				"/test/straight/rewrite", "/change/to/me/ignore",
   261  				"/test/straight/rewrite", "/change/to/me/hello",
   262  				[]apidef.RoutingTrigger{
   263  					{
   264  						On: apidef.All,
   265  						Options: apidef.RoutingTriggerOptions{
   266  							HeaderMatches: map[string]apidef.StringRegexMap{
   267  								"x-test":     hOpt,
   268  								"x-test-Two": hOpt2,
   269  							},
   270  						},
   271  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0",
   272  					},
   273  				},
   274  				r,
   275  			}
   276  		},
   277  		func() TestDef {
   278  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   279  
   280  			r.Header.Set("y-test", "baz")
   281  			r.Header.Set("y-test-Two", "qux")
   282  
   283  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   284  			hOpt.Init()
   285  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   286  			hOpt2.Init()
   287  
   288  			hOpt3 := apidef.StringRegexMap{MatchPattern: "baz"}
   289  			hOpt3.Init()
   290  			hOpt4 := apidef.StringRegexMap{MatchPattern: "fnee"}
   291  			hOpt4.Init()
   292  
   293  			return TestDef{
   294  				"Header Many Multi Any Pass",
   295  				"/test/straight/rewrite", "/change/to/me/ignore",
   296  				"/test/straight/rewrite", "/change/to/me/baz",
   297  				[]apidef.RoutingTrigger{
   298  					{
   299  						On: apidef.Any,
   300  						Options: apidef.RoutingTriggerOptions{
   301  							HeaderMatches: map[string]apidef.StringRegexMap{
   302  								"x-test":     hOpt,
   303  								"x-test-Two": hOpt2,
   304  							},
   305  						},
   306  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0",
   307  					},
   308  					{
   309  						On: apidef.Any,
   310  						Options: apidef.RoutingTriggerOptions{
   311  							HeaderMatches: map[string]apidef.StringRegexMap{
   312  								"y-test":     hOpt3,
   313  								"y-test-Two": hOpt4,
   314  							},
   315  						},
   316  						RewriteTo: "/change/to/me/$tyk_context.trigger-1-Y-Test-0",
   317  					},
   318  				},
   319  				r,
   320  			}
   321  		},
   322  		func() TestDef {
   323  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   324  
   325  			r.Header.Set("x-test", "hello")
   326  			r.Header.Set("x-test-Two", "world")
   327  
   328  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   329  			hOpt.Init()
   330  			hOpt2 := apidef.StringRegexMap{MatchPattern: "w.*", Reverse: true}
   331  			hOpt2.Init()
   332  
   333  			return TestDef{
   334  				"Header Reverse Logic Any Pass",
   335  				"/test/straight/rewrite", "/change/to/me/ignore",
   336  				"/test/straight/rewrite", "/change/to/me/hello",
   337  				[]apidef.RoutingTrigger{
   338  					{
   339  						On: apidef.Any,
   340  						Options: apidef.RoutingTriggerOptions{
   341  							HeaderMatches: map[string]apidef.StringRegexMap{
   342  								"x-test":     hOpt,
   343  								"x-test-Two": hOpt2,
   344  							},
   345  						},
   346  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0",
   347  					},
   348  				},
   349  				r,
   350  			}
   351  		},
   352  		func() TestDef {
   353  			r, _ := http.NewRequest("GET", "/test/straight/rewrite", nil)
   354  
   355  			r.Header.Set("x-test", "hello")
   356  			r.Header.Set("x-test-Two", "world")
   357  
   358  			hOpt := apidef.StringRegexMap{MatchPattern: "hello"}
   359  			hOpt.Init()
   360  			hOpt2 := apidef.StringRegexMap{MatchPattern: "w.*", Reverse: true}
   361  			hOpt2.Init()
   362  
   363  			return TestDef{
   364  				"Header Reverse Logic All Fail",
   365  				"/test/straight/rewrite", "/change/to/me/ignore",
   366  				"/test/straight/rewrite", "/change/to/me/ignore",
   367  				[]apidef.RoutingTrigger{
   368  					{
   369  						On: apidef.All,
   370  						Options: apidef.RoutingTriggerOptions{
   371  							HeaderMatches: map[string]apidef.StringRegexMap{
   372  								"x-test":     hOpt,
   373  								"x-test-Two": hOpt2,
   374  							},
   375  						},
   376  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-X-Test-0",
   377  					},
   378  				},
   379  				r,
   380  			}
   381  		},
   382  		func() TestDef {
   383  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   384  
   385  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   386  			hOpt.Init()
   387  
   388  			return TestDef{
   389  				"Query Single",
   390  				"/test/query/rewrite", "/change/to/me/ignore",
   391  				"/test/query/rewrite", "/change/to/me/foo",
   392  				[]apidef.RoutingTrigger{
   393  					{
   394  						On: apidef.Any,
   395  						Options: apidef.RoutingTriggerOptions{
   396  							QueryValMatches: map[string]apidef.StringRegexMap{
   397  								"x_test": hOpt,
   398  							},
   399  						},
   400  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-x_test-0",
   401  					},
   402  				},
   403  				r,
   404  			}
   405  		},
   406  		func() TestDef {
   407  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo-bar", nil)
   408  
   409  			hOpt := apidef.StringRegexMap{MatchPattern: "foo-(\\w+)"}
   410  			hOpt.Init()
   411  
   412  			return TestDef{
   413  				"Query Single Group",
   414  				"/test/query/rewrite", "/change/to/me/ignore",
   415  				"/test/query/rewrite", "/change/to/me/bar",
   416  				[]apidef.RoutingTrigger{
   417  					{
   418  						On: apidef.Any,
   419  						Options: apidef.RoutingTriggerOptions{
   420  							QueryValMatches: map[string]apidef.StringRegexMap{
   421  								"x_test": hOpt,
   422  							},
   423  						},
   424  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-x_test-0-0",
   425  					},
   426  				},
   427  				r,
   428  			}
   429  		},
   430  		func() TestDef {
   431  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo&y_test=bar", nil)
   432  
   433  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   434  			hOpt.Init()
   435  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   436  			hOpt2.Init()
   437  
   438  			return TestDef{
   439  				"Query Multi All",
   440  				"/test/query/rewrite", "/change/to/me/ignore",
   441  				"/test/query/rewrite", "/change/to/me/bar",
   442  				[]apidef.RoutingTrigger{
   443  					{
   444  						On: apidef.All,
   445  						Options: apidef.RoutingTriggerOptions{
   446  							QueryValMatches: map[string]apidef.StringRegexMap{
   447  								"x_test": hOpt,
   448  								"y_test": hOpt2,
   449  							},
   450  						},
   451  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-y_test-0",
   452  					},
   453  				},
   454  				r,
   455  			}
   456  		},
   457  		func() TestDef {
   458  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   459  			r.Header.Set("y-test", "qux")
   460  
   461  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   462  			hOpt.Init()
   463  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   464  			hOpt2.Init()
   465  
   466  			return TestDef{
   467  				"Multi Multi Type Any",
   468  				"/test/query/rewrite", "/change/to/me/ignore",
   469  				"/test/query/rewrite", "/change/to/me/foo",
   470  				[]apidef.RoutingTrigger{
   471  					{
   472  						On: apidef.Any,
   473  						Options: apidef.RoutingTriggerOptions{
   474  							QueryValMatches: map[string]apidef.StringRegexMap{
   475  								"x_test": hOpt,
   476  							},
   477  							HeaderMatches: map[string]apidef.StringRegexMap{
   478  								"y-test": hOpt2,
   479  							},
   480  						},
   481  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-x_test-0",
   482  					},
   483  				},
   484  				r,
   485  			}
   486  		},
   487  		func() TestDef {
   488  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   489  			r.Header.Set("y-test", "bar")
   490  
   491  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   492  			hOpt.Init()
   493  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   494  			hOpt2.Init()
   495  
   496  			return TestDef{
   497  				"Multi Multi Type All",
   498  				"/test/query/rewrite", "/change/to/me/ignore",
   499  				"/test/query/rewrite", "/change/to/me/bar",
   500  				[]apidef.RoutingTrigger{
   501  					{
   502  						On: apidef.All,
   503  						Options: apidef.RoutingTriggerOptions{
   504  							QueryValMatches: map[string]apidef.StringRegexMap{
   505  								"x_test": hOpt,
   506  							},
   507  							HeaderMatches: map[string]apidef.StringRegexMap{
   508  								"y-test": hOpt2,
   509  							},
   510  						},
   511  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-Y-Test-0",
   512  					},
   513  				},
   514  				r,
   515  			}
   516  		},
   517  		func() TestDef {
   518  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   519  			r.Header.Set("y-test", "bar")
   520  			r.Header.Set("z-test", "fnee")
   521  
   522  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   523  			hOpt.Init()
   524  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   525  			hOpt2.Init()
   526  			hOpt3 := apidef.StringRegexMap{MatchPattern: "baz"}
   527  			hOpt3.Init()
   528  
   529  			return TestDef{
   530  				"Multi Multi Type All Fail",
   531  				"/test/query/rewrite", "/change/to/me/ignore",
   532  				"/test/query/rewrite", "/change/to/me/ignore",
   533  				[]apidef.RoutingTrigger{
   534  					{
   535  						On: apidef.All,
   536  						Options: apidef.RoutingTriggerOptions{
   537  							QueryValMatches: map[string]apidef.StringRegexMap{
   538  								"x_test": hOpt,
   539  							},
   540  							HeaderMatches: map[string]apidef.StringRegexMap{
   541  								"y-test": hOpt2,
   542  								"z-test": hOpt3,
   543  							},
   544  						},
   545  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-Y-Test-0",
   546  					},
   547  				},
   548  				r,
   549  			}
   550  		},
   551  		func() TestDef {
   552  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   553  			r.Header.Set("y-test", "bar")
   554  			r.Header.Set("z-test", "baz")
   555  
   556  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   557  			hOpt.Init()
   558  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   559  			hOpt2.Init()
   560  			hOpt3 := apidef.StringRegexMap{MatchPattern: "baz", Reverse: true}
   561  			hOpt3.Init()
   562  
   563  			return TestDef{
   564  				"Multi Multi Type Reverse Logic All Fail",
   565  				"/test/query/rewrite", "/change/to/me/ignore",
   566  				"/test/query/rewrite", "/change/to/me/ignore",
   567  				[]apidef.RoutingTrigger{
   568  					{
   569  						On: apidef.All,
   570  						Options: apidef.RoutingTriggerOptions{
   571  							QueryValMatches: map[string]apidef.StringRegexMap{
   572  								"x_test": hOpt,
   573  							},
   574  							HeaderMatches: map[string]apidef.StringRegexMap{
   575  								"y-test": hOpt2,
   576  								"z-test": hOpt3,
   577  							},
   578  						},
   579  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-Y-Test-0",
   580  					},
   581  				},
   582  				r,
   583  			}
   584  		},
   585  		func() TestDef {
   586  			r, _ := http.NewRequest("GET", "/test/query/rewrite?x_test=foo", nil)
   587  			r.Header.Set("y-test", "bar")
   588  			r.Header.Set("z-test", "baz")
   589  
   590  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   591  			hOpt.Init()
   592  			hOpt2 := apidef.StringRegexMap{MatchPattern: "bar"}
   593  			hOpt2.Init()
   594  			hOpt3 := apidef.StringRegexMap{MatchPattern: "baz", Reverse: true}
   595  			hOpt3.Init()
   596  
   597  			return TestDef{
   598  				"Multi Multi Type Reverse Logic All Fail",
   599  				"/test/query/rewrite", "/change/to/me/ignore",
   600  				"/test/query/rewrite", "/change/to/me/bar",
   601  				[]apidef.RoutingTrigger{
   602  					{
   603  						On: apidef.Any,
   604  						Options: apidef.RoutingTriggerOptions{
   605  							QueryValMatches: map[string]apidef.StringRegexMap{
   606  								"x_test": hOpt,
   607  							},
   608  							HeaderMatches: map[string]apidef.StringRegexMap{
   609  								"y-test": hOpt2,
   610  								"z-test": hOpt3,
   611  							},
   612  						},
   613  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-Y-Test-0",
   614  					},
   615  				},
   616  				r,
   617  			}
   618  		},
   619  		func() TestDef {
   620  			var jsonStr = []byte(`{"foo":"bar"}`)
   621  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   622  
   623  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   624  			hOpt.Init()
   625  
   626  			return TestDef{
   627  				"Payload Single",
   628  				"/test/pl/rewrite", "/change/to/me/ignore",
   629  				"/test/pl/rewrite", "/change/to/me/bar",
   630  				[]apidef.RoutingTrigger{
   631  					{
   632  						On: apidef.Any,
   633  						Options: apidef.RoutingTriggerOptions{
   634  							PayloadMatches: hOpt,
   635  						},
   636  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload",
   637  					},
   638  				},
   639  				r,
   640  			}
   641  		},
   642  		func() TestDef {
   643  			var jsonStr = []byte(`{"foo":"barxxx", "fooble":"baryyy"}`)
   644  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   645  
   646  			hOpt := apidef.StringRegexMap{MatchPattern: "bar\\w*"}
   647  			hOpt.Init()
   648  
   649  			return TestDef{
   650  				"Payload Multiple Match",
   651  				"/test/pl/rewrite", "/change/to/me/ignore",
   652  				"/test/pl/rewrite", "/change/to/me/barxxx/baryyy",
   653  				[]apidef.RoutingTrigger{
   654  					{
   655  						On: apidef.Any,
   656  						Options: apidef.RoutingTriggerOptions{
   657  							PayloadMatches: hOpt,
   658  						},
   659  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-payload-1",
   660  					},
   661  				},
   662  				r,
   663  			}
   664  		},
   665  		func() TestDef {
   666  			var jsonStr = []byte(`{"foo":"barxxx", "fooble":"baryyy"}`)
   667  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   668  
   669  			hOpt := apidef.StringRegexMap{MatchPattern: "bar(\\w*)"}
   670  			hOpt.Init()
   671  
   672  			return TestDef{
   673  				"Payload Multiple Match Groups",
   674  				"/test/pl/rewrite", "/change/to/me/ignore",
   675  				"/test/pl/rewrite", "/change/to/me/xxx/yyy",
   676  				[]apidef.RoutingTrigger{
   677  					{
   678  						On: apidef.Any,
   679  						Options: apidef.RoutingTriggerOptions{
   680  							PayloadMatches: hOpt,
   681  						},
   682  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0-0/$tyk_context.trigger-0-payload-1-0",
   683  					},
   684  				},
   685  				r,
   686  			}
   687  		},
   688  		func() TestDef {
   689  			var jsonStr = []byte(`{"foo":"barxxx", "fooble":"baryyy"}`)
   690  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   691  
   692  			hOpt := apidef.StringRegexMap{MatchPattern: "bar(\\w*)"}
   693  			hOpt.Init()
   694  
   695  			return TestDef{
   696  				"Payload Multiple Match Groups",
   697  				"/test/pl/rewrite", "/change/to/me/ignore",
   698  				"/test/pl/rewrite", "/change/to/me/xxx/yyy",
   699  				[]apidef.RoutingTrigger{
   700  					{
   701  						On: apidef.Any,
   702  						Options: apidef.RoutingTriggerOptions{
   703  							PayloadMatches: hOpt,
   704  						},
   705  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0-0/$tyk_context.trigger-0-payload-1-0",
   706  					},
   707  				},
   708  				r,
   709  			}
   710  		},
   711  		func() TestDef {
   712  			var jsonStr = []byte(`{"foo":"bar"}`)
   713  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   714  			r.Header.Set("x-test", "apple")
   715  
   716  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   717  			hOpt.Init()
   718  			hOpt2 := apidef.StringRegexMap{MatchPattern: "apple"}
   719  			hOpt2.Init()
   720  
   721  			return TestDef{
   722  				"Multi Type All",
   723  				"/test/pl/rewrite", "/change/to/me/ignore",
   724  				"/test/pl/rewrite", "/change/to/me/bar/apple",
   725  				[]apidef.RoutingTrigger{
   726  					{
   727  						On: apidef.All,
   728  						Options: apidef.RoutingTriggerOptions{
   729  							PayloadMatches: hOpt,
   730  							HeaderMatches: map[string]apidef.StringRegexMap{
   731  								"x-test": hOpt2,
   732  							},
   733  						},
   734  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-X-Test-0",
   735  					},
   736  				},
   737  				r,
   738  			}
   739  		},
   740  		func() TestDef {
   741  			var jsonStr = []byte(`{"foo":"bar"}`)
   742  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   743  			r.Header.Set("x-test", "apple")
   744  
   745  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   746  			hOpt.Init()
   747  			hOpt2 := apidef.StringRegexMap{MatchPattern: "apple", Reverse: true}
   748  			hOpt2.Init()
   749  
   750  			return TestDef{
   751  				"Multi Multi Type Reverse Logic Any 1",
   752  				"/test/pl/rewrite", "/change/to/me/ignore",
   753  				"/test/pl/rewrite", "/change/to/me/bar/",
   754  				[]apidef.RoutingTrigger{
   755  					{
   756  						On: apidef.Any,
   757  						Options: apidef.RoutingTriggerOptions{
   758  							PayloadMatches: hOpt,
   759  							HeaderMatches: map[string]apidef.StringRegexMap{
   760  								"x-test": hOpt2,
   761  							},
   762  						},
   763  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-X-Test-0",
   764  					},
   765  				},
   766  				r,
   767  			}
   768  		},
   769  		func() TestDef {
   770  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
   771  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   772  			hOpt.Init()
   773  
   774  			return TestDef{
   775  				"PathPart Single",
   776  				"/test/foo/rewrite", "/change/to/me/ignore",
   777  				"/test/foo/rewrite", "/change/to/me/foo",
   778  				[]apidef.RoutingTrigger{
   779  					{
   780  						On: apidef.Any,
   781  						Options: apidef.RoutingTriggerOptions{
   782  							PathPartMatches: map[string]apidef.StringRegexMap{
   783  								"pathpart": hOpt,
   784  							},
   785  						},
   786  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0",
   787  					},
   788  				},
   789  				r,
   790  			}
   791  		},
   792  		func() TestDef {
   793  			var jsonStr = []byte(`{"foo":"bar"}`)
   794  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   795  			r.Header.Set("x-test", "apple")
   796  
   797  			hOpt := apidef.StringRegexMap{MatchPattern: "bar", Reverse: true}
   798  			hOpt.Init()
   799  			hOpt2 := apidef.StringRegexMap{MatchPattern: "apple"}
   800  			hOpt2.Init()
   801  
   802  			return TestDef{
   803  				"Multi Multi Type Reverse Logic Any 2",
   804  				"/test/pl/rewrite", "/change/to/me/ignore",
   805  				"/test/pl/rewrite", "/change/to/me//apple",
   806  				[]apidef.RoutingTrigger{
   807  					{
   808  						On: apidef.Any,
   809  						Options: apidef.RoutingTriggerOptions{
   810  							PayloadMatches: hOpt,
   811  							HeaderMatches: map[string]apidef.StringRegexMap{
   812  								"x-test": hOpt2,
   813  							},
   814  						},
   815  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-X-Test-0",
   816  					},
   817  				},
   818  				r,
   819  			}
   820  		},
   821  		func() TestDef {
   822  			var jsonStr = []byte(`{"foo":"bar"}`)
   823  			r, _ := http.NewRequest("POST", "/test/pl/rewrite", bytes.NewBuffer(jsonStr))
   824  			r.Header.Set("x-test", "apple")
   825  
   826  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   827  			hOpt.Init()
   828  			hOpt2 := apidef.StringRegexMap{MatchPattern: "apple", Reverse: true}
   829  			hOpt2.Init()
   830  
   831  			return TestDef{
   832  				"Multi Multi Type Reverse Logic Any 3",
   833  				"/test/pl/rewrite", "/change/to/me/ignore",
   834  				"/test/pl/rewrite", "/change/to/me/bar/",
   835  				[]apidef.RoutingTrigger{
   836  					{
   837  						On: apidef.Any,
   838  						Options: apidef.RoutingTriggerOptions{
   839  							PayloadMatches: hOpt,
   840  							HeaderMatches: map[string]apidef.StringRegexMap{
   841  								"x-test": hOpt2,
   842  							},
   843  						},
   844  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-payload-0/$tyk_context.trigger-0-X-Test-0",
   845  					},
   846  				},
   847  				r,
   848  			}
   849  		},
   850  		func() TestDef {
   851  			r, _ := http.NewRequest("GET", "/test/foobar/rewrite", nil)
   852  			hOpt := apidef.StringRegexMap{MatchPattern: "foo(\\w+)"}
   853  			hOpt.Init()
   854  
   855  			return TestDef{
   856  				"PathPart Single Group",
   857  				"/test/foobar/rewrite", "/change/to/me/ignore",
   858  				"/test/foobar/rewrite", "/change/to/me/bar",
   859  				[]apidef.RoutingTrigger{
   860  					{
   861  						On: apidef.Any,
   862  						Options: apidef.RoutingTriggerOptions{
   863  							PathPartMatches: map[string]apidef.StringRegexMap{
   864  								"pathpart": hOpt,
   865  							},
   866  						},
   867  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0-0",
   868  					},
   869  				},
   870  				r,
   871  			}
   872  		},
   873  		func() TestDef {
   874  			r, _ := http.NewRequest("GET", "/test/foo/rewrite/foo", nil)
   875  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
   876  			hOpt.Init()
   877  
   878  			return TestDef{
   879  				"PathPart MoreParts",
   880  				"/test/foo/rewrite/foo", "/change/to/me/ignore",
   881  				"/test/foo/rewrite/foo", "/change/to/me/foo/biz/foo",
   882  				[]apidef.RoutingTrigger{
   883  					{
   884  						On: apidef.Any,
   885  						Options: apidef.RoutingTriggerOptions{
   886  							PathPartMatches: map[string]apidef.StringRegexMap{
   887  								"pathpart": hOpt,
   888  							},
   889  						},
   890  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0/biz/$tyk_context.trigger-0-pathpart-1",
   891  					},
   892  				},
   893  				r,
   894  			}
   895  		},
   896  		func() TestDef {
   897  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
   898  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   899  			hOpt.Init()
   900  
   901  			ctxSetSession(r, &user.SessionState{
   902  				MetaData: map[string]interface{}{
   903  					"rewrite": "bar-baz",
   904  				},
   905  				Mutex: &sync.RWMutex{},
   906  			}, "", false)
   907  
   908  			return TestDef{
   909  				"Meta Simple",
   910  				"/test/foo/rewrite", "/change/to/me/ignore",
   911  				"/test/foo/rewrite", "/change/to/me/bar",
   912  				[]apidef.RoutingTrigger{
   913  					{
   914  						On: apidef.Any,
   915  						Options: apidef.RoutingTriggerOptions{
   916  							SessionMetaMatches: map[string]apidef.StringRegexMap{
   917  								"rewrite": hOpt,
   918  							},
   919  						},
   920  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-rewrite",
   921  					},
   922  				},
   923  				r,
   924  			}
   925  		},
   926  		func() TestDef {
   927  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
   928  			hOpt := apidef.StringRegexMap{MatchPattern: "bar-(\\w+)"}
   929  			hOpt.Init()
   930  
   931  			ctxSetSession(r, &user.SessionState{
   932  				MetaData: map[string]interface{}{
   933  					"rewrite": "bar-baz",
   934  				},
   935  				Mutex: &sync.RWMutex{},
   936  			}, "", false)
   937  
   938  			return TestDef{
   939  				"Meta Simple Group",
   940  				"/test/foo/rewrite", "/change/to/me/ignore",
   941  				"/test/foo/rewrite", "/change/to/me/baz",
   942  				[]apidef.RoutingTrigger{
   943  					{
   944  						On: apidef.Any,
   945  						Options: apidef.RoutingTriggerOptions{
   946  							SessionMetaMatches: map[string]apidef.StringRegexMap{
   947  								"rewrite": hOpt,
   948  							},
   949  						},
   950  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-rewrite-0",
   951  					},
   952  				},
   953  				r,
   954  			}
   955  		},
   956  		func() TestDef {
   957  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
   958  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   959  			hOpt.Init()
   960  
   961  			ctxSetSession(r, &user.SessionState{
   962  				MetaData: map[string]interface{}{
   963  					"rewrite": "bar-baz",
   964  					"somevar": "someval",
   965  				},
   966  				Mutex: &sync.RWMutex{},
   967  			}, "", false)
   968  
   969  			return TestDef{
   970  				"Meta Value from Session",
   971  				"/test/foo/rewrite", "/change/to/me/ignore",
   972  				"/test/foo/rewrite", "/change/to/me/bar/someval",
   973  				[]apidef.RoutingTrigger{
   974  					{
   975  						On: apidef.Any,
   976  						Options: apidef.RoutingTriggerOptions{
   977  							SessionMetaMatches: map[string]apidef.StringRegexMap{
   978  								"rewrite": hOpt,
   979  							},
   980  						},
   981  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-rewrite/$tyk_meta.somevar",
   982  					},
   983  				},
   984  				r,
   985  			}
   986  		},
   987  		func() TestDef {
   988  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
   989  			hOpt := apidef.StringRegexMap{MatchPattern: "bar"}
   990  			hOpt.Init()
   991  
   992  			ctxSetData(r, map[string]interface{}{
   993  				"rewrite": "bar-baz",
   994  			})
   995  
   996  			return TestDef{
   997  				"Request context",
   998  				"/test/foo/rewrite", "/change/to/me/ignore",
   999  				"/test/foo/rewrite", "/change/to/me/bar",
  1000  				[]apidef.RoutingTrigger{
  1001  					{
  1002  						On: apidef.Any,
  1003  						Options: apidef.RoutingTriggerOptions{
  1004  							RequestContextMatches: map[string]apidef.StringRegexMap{
  1005  								"rewrite": hOpt,
  1006  							},
  1007  						},
  1008  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-rewrite",
  1009  					},
  1010  				},
  1011  				r,
  1012  			}
  1013  		},
  1014  		func() TestDef {
  1015  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
  1016  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
  1017  			hOpt.Init()
  1018  
  1019  			ctxSetSession(r, &user.SessionState{
  1020  				MetaData: map[string]interface{}{
  1021  					"rewrite": "bar-baz",
  1022  				},
  1023  				Mutex: &sync.RWMutex{},
  1024  			}, "", false)
  1025  
  1026  			return TestDef{
  1027  				"Variable not found",
  1028  				"/test/foo/rewrite", "/change/to/me/ignore",
  1029  				"/test/foo/rewrite", "/change/to/me/foo//",
  1030  				[]apidef.RoutingTrigger{
  1031  					{
  1032  						On: apidef.Any,
  1033  						Options: apidef.RoutingTriggerOptions{
  1034  							PathPartMatches: map[string]apidef.StringRegexMap{
  1035  								"pathpart": hOpt,
  1036  							},
  1037  						},
  1038  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0/$tyk_context.nonexistent/$tyk_meta.nonexistent",
  1039  					},
  1040  				},
  1041  				r,
  1042  			}
  1043  		},
  1044  		func() TestDef {
  1045  			r, _ := http.NewRequest("GET", "/test/foo/rewrite", nil)
  1046  			hOpt := apidef.StringRegexMap{MatchPattern: "foo"}
  1047  			hOpt.Init()
  1048  
  1049  			return TestDef{
  1050  				"Session not found",
  1051  				"/test/foo/rewrite", "/change/to/me/ignore",
  1052  				"/test/foo/rewrite", "/change/to/me/foo/",
  1053  				[]apidef.RoutingTrigger{
  1054  					{
  1055  						On: apidef.Any,
  1056  						Options: apidef.RoutingTriggerOptions{
  1057  							PathPartMatches: map[string]apidef.StringRegexMap{
  1058  								"pathpart": hOpt,
  1059  							},
  1060  						},
  1061  						RewriteTo: "/change/to/me/$tyk_context.trigger-0-pathpart-0/$tyk_meta.nonexistent",
  1062  					},
  1063  				},
  1064  				r,
  1065  			}
  1066  		},
  1067  	}
  1068  	for _, tf := range tests {
  1069  		tc := tf()
  1070  		t.Run(tc.name, func(t *testing.T) {
  1071  			testConf := apidef.URLRewriteMeta{
  1072  				MatchPattern: tc.pattern,
  1073  				RewriteTo:    tc.to,
  1074  				Triggers:     tc.triggerConf,
  1075  			}
  1076  
  1077  			got, err := urlRewrite(&testConf, tc.req)
  1078  			if err != nil {
  1079  				t.Error("compile failed:", err)
  1080  			}
  1081  			if got != tc.want {
  1082  				t.Errorf("rewrite failed, want %q, got %q", tc.want, got)
  1083  			}
  1084  		})
  1085  	}
  1086  }
  1087  
  1088  func TestInitTriggerRx(t *testing.T) {
  1089  	// prepare test data
  1090  	testRewriteMW := &URLRewriteMiddleware{
  1091  		BaseMiddleware: BaseMiddleware{
  1092  			Spec: &APISpec{
  1093  				APIDefinition: &apidef.APIDefinition{},
  1094  			},
  1095  		},
  1096  	}
  1097  	testRewriteMW.Spec.APIDefinition.VersionData = struct {
  1098  		NotVersioned   bool                          `bson:"not_versioned" json:"not_versioned"`
  1099  		DefaultVersion string                        `bson:"default_version" json:"default_version"`
  1100  		Versions       map[string]apidef.VersionInfo `bson:"versions" json:"versions"`
  1101  	}{}
  1102  
  1103  	routingTriggerOptions := apidef.RoutingTriggerOptions{
  1104  		HeaderMatches: map[string]apidef.StringRegexMap{
  1105  			"abc": {
  1106  				MatchPattern: "^abc.*",
  1107  			},
  1108  		},
  1109  		QueryValMatches: map[string]apidef.StringRegexMap{
  1110  			"def": {
  1111  				MatchPattern: "^def.*",
  1112  			},
  1113  		},
  1114  		PayloadMatches: apidef.StringRegexMap{
  1115  			MatchPattern: "^ghi.*",
  1116  		},
  1117  	}
  1118  
  1119  	extendedPathsSet := apidef.ExtendedPathsSet{
  1120  		URLRewrite: []apidef.URLRewriteMeta{
  1121  			{
  1122  				Triggers: []apidef.RoutingTrigger{
  1123  					{
  1124  						Options: routingTriggerOptions,
  1125  					},
  1126  				},
  1127  			},
  1128  		},
  1129  	}
  1130  	testRewriteMW.Spec.APIDefinition.VersionData.Versions = map[string]apidef.VersionInfo{
  1131  		"Default": {
  1132  			ExtendedPaths: extendedPathsSet,
  1133  		},
  1134  	}
  1135  
  1136  	// run method under test
  1137  	testRewriteMW.InitTriggerRx()
  1138  
  1139  	// assert HeaderMatches
  1140  	headerMatch := testRewriteMW.
  1141  		Spec.
  1142  		APIDefinition.
  1143  		VersionData.
  1144  		Versions["Default"].
  1145  		ExtendedPaths.
  1146  		URLRewrite[0].
  1147  		Triggers[0].
  1148  		Options.
  1149  		HeaderMatches["abc"]
  1150  	if headerMatch.Check("abc") == "" {
  1151  		t.Errorf("Expected HeaderMatches initalized and matched, received no match")
  1152  	}
  1153  
  1154  	// assert QueryValMatches
  1155  	queryValMatch := testRewriteMW.
  1156  		Spec.
  1157  		APIDefinition.
  1158  		VersionData.
  1159  		Versions["Default"].
  1160  		ExtendedPaths.
  1161  		URLRewrite[0].
  1162  		Triggers[0].
  1163  		Options.
  1164  		QueryValMatches["def"]
  1165  	if queryValMatch.Check("def") == "" {
  1166  		t.Errorf("Expected QueryValMatches initalized and matched, received no match")
  1167  	}
  1168  
  1169  	// assert PayloadMatches
  1170  	payloadMatch := testRewriteMW.
  1171  		Spec.
  1172  		APIDefinition.
  1173  		VersionData.
  1174  		Versions["Default"].
  1175  		ExtendedPaths.
  1176  		URLRewrite[0].
  1177  		Triggers[0].
  1178  		Options.
  1179  		PayloadMatches
  1180  	if payloadMatch.Check("ghi") == "" {
  1181  		t.Errorf("Expected PayloadMatches initalized and matched, received no match")
  1182  	}
  1183  }
  1184  
  1185  func TestURLRewriteCaseSensitivity(t *testing.T) {
  1186  	ts := StartTest()
  1187  	defer ts.Close()
  1188  
  1189  	assert := func(relativePath string, requestedPath string, bodyMatch string) {
  1190  		BuildAndLoadAPI(func(spec *APISpec) {
  1191  			spec.Proxy.ListenPath = "/"
  1192  			UpdateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
  1193  				v.ExtendedPaths.URLRewrite = []apidef.URLRewriteMeta{{
  1194  					Path:         relativePath,
  1195  					Method:       "GET",
  1196  					MatchPattern: requestedPath,
  1197  					RewriteTo:    "/xyz",
  1198  				}}
  1199  			})
  1200  		})
  1201  
  1202  		ts.Run(t, test.TestCase{
  1203  			Path: requestedPath, Code: 200, BodyMatch: bodyMatch,
  1204  		})
  1205  	}
  1206  
  1207  	// Matches and rewrites
  1208  	t.Run("Relative path lower, requested path lower", func(t *testing.T) {
  1209  		assert("/get", "/get", `"Url":"/xyz"`)
  1210  	})
  1211  
  1212  	// Doesn't match and doesn't rewrite
  1213  	t.Run("Relative path lower, requested path upper", func(t *testing.T) {
  1214  		assert("/get", "/Get", `"Url":"/Get"`)
  1215  	})
  1216  
  1217  	// Doesn't match and doesn't rewrite
  1218  	t.Run("Relative path upper, requested path lower", func(t *testing.T) {
  1219  		assert("/Get", "/get", `"Url":"/get"`)
  1220  	})
  1221  
  1222  	// Matches and rewrites
  1223  	t.Run("Relative path upper, requested path upper", func(t *testing.T) {
  1224  		assert("/Get", "/Get", `"Url":"/xyz"`)
  1225  	})
  1226  }
  1227  
  1228  func TestValToStr(t *testing.T) {
  1229  
  1230  	example := []interface{}{
  1231  		"abc",      // string
  1232  		int64(456), // int64
  1233  		12.22,      // float
  1234  		"abc,def",  // string url encode
  1235  	}
  1236  
  1237  	str := valToStr(example)
  1238  	expected := "abc,456,12.22,abc%2Cdef"
  1239  
  1240  	if str != expected {
  1241  		t.Errorf("expected (%s) got (%s)", expected, str)
  1242  	}
  1243  }