github.com/dbernstein1/tyk@v2.9.0-beta9-dl-apic+incompatible/gateway/mw_context_vars_test.go (about) 1 package gateway 2 3 import ( 4 "io" 5 "net/http" 6 "net/http/httptest" 7 "net/url" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/TykTechnologies/tyk/apidef" 13 "github.com/TykTechnologies/tyk/test" 14 ) 15 16 func testPrepareContextVarsMiddleware() { 17 BuildAndLoadAPI(func(spec *APISpec) { 18 spec.Proxy.ListenPath = "/" 19 spec.EnableContextVars = true 20 spec.VersionData.Versions = map[string]apidef.VersionInfo{ 21 "v1": { 22 UseExtendedPaths: true, 23 GlobalHeaders: map[string]string{ 24 "X-Static": "foo", 25 "X-Request-ID": "$tyk_context.request_id", 26 "X-Path": "$tyk_context.path", 27 "X-Remote-Addr": "$tyk_context.remote_addr", 28 }, 29 }, 30 } 31 }) 32 } 33 34 func TestContextVarsMiddleware(t *testing.T) { 35 ts := StartTest() 36 defer ts.Close() 37 38 testPrepareContextVarsMiddleware() 39 40 ts.Run(t, []test.TestCase{ 41 {Path: "/test/path", Code: 200, BodyMatch: `"X-Remote-Addr":"127.0.0.1"`}, 42 {Path: "/test/path", Code: 200, BodyMatch: `"X-Path":"/test/path"`}, 43 {Path: "/test/path", Code: 200, BodyMatch: `"X-Static":"foo"`}, 44 {Path: "/test/path", Code: 200, BodyMatch: `"X-Request-Id":"`}, 45 }...) 46 } 47 48 func BenchmarkContextVarsMiddleware(b *testing.B) { 49 b.ReportAllocs() 50 51 ts := StartTest() 52 defer ts.Close() 53 54 testPrepareContextVarsMiddleware() 55 56 for i := 0; i < b.N; i++ { 57 ts.Run(b, []test.TestCase{ 58 {Path: "/test/path", Code: 200, BodyMatch: `"X-Remote-Addr":"127.0.0.1"`}, 59 {Path: "/test/path", Code: 200, BodyMatch: `"X-Path":"/test/path"`}, 60 {Path: "/test/path", Code: 200, BodyMatch: `"X-Static":"foo"`}, 61 {Path: "/test/path", Code: 200, BodyMatch: `"X-Request-Id":"`}, 62 }...) 63 } 64 } 65 66 type testContextVarsData struct { 67 Method string 68 URL string 69 Data string 70 ExpectedCtxDataObject map[string]interface{} 71 Header http.Header 72 } 73 74 func testPrepareTestContextVarsMiddleware() map[string]testContextVarsData { 75 return map[string]testContextVarsData{ 76 "GET with query string": { 77 Method: http.MethodGet, 78 URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", 79 Header: http.Header{ 80 "x-header-a": {"A"}, 81 "x-header-b": {"B"}, 82 "x-header-c": {"C"}, 83 }, 84 ExpectedCtxDataObject: map[string]interface{}{ 85 "remote_addr": "192.0.2.1", 86 "request_data": url.Values{ 87 "x": {"123"}, 88 "y": {"test"}, 89 }, 90 "headers": map[string][]string{ 91 "x-header-a": {"A"}, 92 "x-header-b": {"B"}, 93 "x-header-c": {"C"}, 94 }, 95 "headers_x_header_a": "A", 96 "headers_x_header_b": "B", 97 "headers_x_header_c": "C", 98 "headers_Host": "abc.com", 99 "path_parts": []string{"", "aaa", "bbb", "111", "222"}, 100 "path": "/aaa/bbb/111/222", 101 }, 102 }, 103 "POST with query string and encoded form data": { 104 Method: http.MethodPost, 105 URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", 106 Data: "i=1&j=2&str=abc", 107 Header: http.Header{ 108 "Content-Type": {"application/x-www-form-urlencoded"}, 109 "x-header-a": {"A"}, 110 "x-header-b": {"B"}, 111 "x-header-c": {"C"}, 112 }, 113 ExpectedCtxDataObject: map[string]interface{}{ 114 "remote_addr": "192.0.2.1", 115 "request_data": url.Values{ 116 "x": {"123"}, 117 "y": {"test"}, 118 "i": {"1"}, 119 "j": {"2"}, 120 "str": {"abc"}, 121 }, 122 "headers": map[string][]string{ 123 "x-header-a": {"A"}, 124 "x-header-b": {"B"}, 125 "x-header-c": {"C"}, 126 "Content-Type": {"application/x-www-form-urlencoded"}, 127 }, 128 "headers_x_header_a": "A", 129 "headers_x_header_b": "B", 130 "headers_x_header_c": "C", 131 "headers_Content_Type": "application/x-www-form-urlencoded", 132 "headers_Host": "abc.com", 133 "path_parts": []string{"", "aaa", "bbb", "111", "222"}, 134 "path": "/aaa/bbb/111/222", 135 }, 136 }, 137 "POST with query string and encoded form data and cookies": { 138 Method: http.MethodPost, 139 URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", 140 Data: "i=1&j=2&str=abc", 141 Header: http.Header{ 142 "Content-Type": {"application/x-www-form-urlencoded"}, 143 "Cookie": {"c-1=cookie1;c-2=cookie2"}, 144 "x-header-a": {"A"}, 145 "x-header-b": {"B"}, 146 "x-header-c": {"C"}, 147 }, 148 ExpectedCtxDataObject: map[string]interface{}{ 149 "remote_addr": "192.0.2.1", 150 "request_data": url.Values{ 151 "x": {"123"}, 152 "y": {"test"}, 153 "i": {"1"}, 154 "j": {"2"}, 155 "str": {"abc"}, 156 }, 157 "headers": map[string][]string{ 158 "x-header-a": {"A"}, 159 "x-header-b": {"B"}, 160 "x-header-c": {"C"}, 161 "Content-Type": {"application/x-www-form-urlencoded"}, 162 "Cookie": {"c-1=cookie1;c-2=cookie2"}, 163 }, 164 "headers_x_header_a": "A", 165 "headers_x_header_b": "B", 166 "headers_x_header_c": "C", 167 "headers_Content_Type": "application/x-www-form-urlencoded", 168 "headers_Cookie": "c-1=cookie1;c-2=cookie2", 169 "headers_Host": "abc.com", 170 "cookies_c_1": "cookie1", 171 "cookies_c_2": "cookie2", 172 "path_parts": []string{"", "aaa", "bbb", "111", "222"}, 173 "path": "/aaa/bbb/111/222", 174 }, 175 }, 176 } 177 } 178 179 func TestContextVarsMiddlewareProcessRequest(t *testing.T) { 180 mw := &MiddlewareContextVars{} 181 182 tests := testPrepareTestContextVarsMiddleware() 183 184 for name, test := range tests { 185 t.Run(name, func(t *testing.T) { 186 var bodyReader io.Reader 187 if test.Data != "" { 188 bodyReader = strings.NewReader(test.Data) 189 } 190 req := httptest.NewRequest(test.Method, test.URL, bodyReader) 191 req.Header = test.Header 192 err, code := mw.ProcessRequest(nil, req, nil) 193 if err != nil { 194 t.Error(err) 195 } 196 if code != http.StatusOK { 197 t.Errorf("Wrong response code: %d Eexpected 200.", code) 198 } 199 200 ctxDataObject := ctxGetData(req) 201 202 // check request_id 203 if _, ok := ctxDataObject["request_id"].(string); !ok { 204 t.Error("Missing 'request_id' field") 205 } 206 207 // delete request_if to do DeepEqual 208 delete(ctxDataObject, "request_id") 209 210 if !reflect.DeepEqual(ctxDataObject, test.ExpectedCtxDataObject) { 211 t.Errorf("Expected: %v\n Got: %v\n", test.ExpectedCtxDataObject, ctxDataObject) 212 } 213 }) 214 } 215 } 216 217 func BenchmarkContextVarsMiddlewareProcessRequest(b *testing.B) { 218 mw := &MiddlewareContextVars{} 219 tests := testPrepareTestContextVarsMiddleware() 220 var err error 221 var code int 222 for name, test := range tests { 223 b.Run(name, func(b *testing.B) { 224 b.ReportAllocs() 225 for i := 0; i < b.N; i++ { 226 var bodyReader io.Reader 227 if test.Data != "" { 228 bodyReader = strings.NewReader(test.Data) 229 } 230 req := httptest.NewRequest(test.Method, test.URL, bodyReader) 231 req.Header = test.Header 232 err, code = mw.ProcessRequest(nil, req, nil) 233 if err != nil { 234 b.Error(err) 235 } 236 if code != http.StatusOK { 237 b.Errorf("Wrong response code: %d Eexpected 200.", code) 238 } 239 } 240 }) 241 } 242 }