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  }