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

     1  package gateway
     2  
     3  import (
     4  	"crypto/md5"
     5  	"encoding/hex"
     6  	"hash"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/TykTechnologies/tyk/apidef"
    12  	"github.com/TykTechnologies/tyk/config"
    13  	"github.com/TykTechnologies/tyk/test"
    14  )
    15  
    16  func TestRedisCacheMiddleware_WithCompressedResponse(t *testing.T) {
    17  	const path = "/compressed"
    18  
    19  	globalConf := config.Global()
    20  	globalConf.AnalyticsConfig.EnableDetailedRecording = true
    21  	config.SetGlobal(globalConf)
    22  
    23  	ts := StartTest()
    24  	defer ts.Close()
    25  
    26  	createAPI := func(withCache bool) {
    27  		BuildAndLoadAPI(func(spec *APISpec) {
    28  			spec.Proxy.ListenPath = "/"
    29  			spec.CacheOptions.CacheTimeout = 60
    30  			spec.CacheOptions.EnableCache = withCache
    31  			UpdateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) {
    32  				v.ExtendedPaths.Cached = []string{path}
    33  			})
    34  		})
    35  	}
    36  
    37  	t.Run("without cache", func(t *testing.T) {
    38  		createAPI(false)
    39  
    40  		ts.Run(t, []test.TestCase{
    41  			{Path: path, Code: 200, BodyMatch: "This is a compressed response"},
    42  			{Path: path, Code: 200, BodyMatch: "This is a compressed response"},
    43  		}...)
    44  	})
    45  
    46  	t.Run("with cache", func(t *testing.T) {
    47  		createAPI(true)
    48  
    49  		ts.Run(t, []test.TestCase{
    50  			{Path: path, Code: 200, BodyMatch: "This is a compressed response"},
    51  			{Path: path, Code: 200, BodyMatch: "This is a compressed response"},
    52  		}...)
    53  	})
    54  
    55  }
    56  
    57  func Test_isSafeMethod(t *testing.T) {
    58  	tests := []struct {
    59  		name     string
    60  		method   string
    61  		expected bool
    62  	}{
    63  		{"Test if Get is a safe method", http.MethodGet, true},
    64  		{"Test if Head is a safe method", http.MethodHead, true},
    65  		{"Test if Options is a safe method", http.MethodOptions, true},
    66  		{"Test if Post is a safe method", http.MethodPost, false},
    67  		{"Test if Put is a safe method", http.MethodPut, false},
    68  		{"Test if Patch is a safe method", http.MethodPatch, false},
    69  		{"Test if Delete is a safe method", http.MethodDelete, false},
    70  		{"Test if Connect is a safe method", http.MethodConnect, false},
    71  		{"Test if Trace is a safe method", http.MethodTrace, false},
    72  	}
    73  	for _, tt := range tests {
    74  		t.Run(tt.name, func(t *testing.T) {
    75  			if got := isSafeMethod(tt.method); got != tt.expected {
    76  				t.Errorf("isSafeMethod() = %v, want %v", got, tt.expected)
    77  			}
    78  		})
    79  	}
    80  }
    81  
    82  func Test_isBodyHashRequired(t *testing.T) {
    83  	requestPutNoBody, _ := http.NewRequest(http.MethodPut, "http://test.com", nil)
    84  	requestGetNoBody, _ := http.NewRequest(http.MethodGet, "http://test.com", nil)
    85  	requestPutWithBody, _ := http.NewRequest(http.MethodPut, "http://test.com", strings.NewReader("some-body"))
    86  	requestPostWithBody, _ := http.NewRequest(http.MethodPost, "http://test.com", strings.NewReader("some-body"))
    87  	requestPatchWithBody, _ := http.NewRequest(http.MethodPatch, "http://test.com", strings.NewReader("some-body"))
    88  	requestGetWithBody, _ := http.NewRequest(http.MethodGet, "http://test.com", strings.NewReader("some-body"))
    89  	type args struct {
    90  		request *http.Request
    91  	}
    92  	tests := []struct {
    93  		name     string
    94  		args     args
    95  		expected bool
    96  	}{
    97  		{"Put no body", args{requestPutNoBody}, false},
    98  		{"Get no body", args{requestGetNoBody}, false},
    99  		{"Get with body", args{requestGetWithBody}, false},
   100  		{"Put with body", args{requestPutWithBody}, true},
   101  		{"Post with body", args{requestPostWithBody}, true},
   102  		{"Patch with body", args{requestPatchWithBody}, true},
   103  	}
   104  	for _, tt := range tests {
   105  		t.Run(tt.name, func(t *testing.T) {
   106  			if got := isBodyHashRequired(tt.args.request); got != tt.expected {
   107  				t.Errorf("isBodyHashRequired() = %v, expected %v", got, tt.expected)
   108  			}
   109  		})
   110  	}
   111  }
   112  
   113  func Test_addBodyHash(t *testing.T) {
   114  	requestPutNoBody, _ := http.NewRequest(http.MethodPut, "http://test.com", nil)
   115  	requestPostWithBody, _ := http.NewRequest(http.MethodPost, "http://test.com", strings.NewReader("some-body"))
   116  	requestPatchWithBody, _ := http.NewRequest(http.MethodPatch, "http://test.com", strings.NewReader("{\"id\":\"1\",\"name\":\"test\"}"))
   117  	type args struct {
   118  		req   *http.Request
   119  		regex string
   120  		h     hash.Hash
   121  	}
   122  	tests := []struct {
   123  		name     string
   124  		args     args
   125  		expected string
   126  	}{
   127  		{"No body", args{requestPutNoBody, ".*", md5.New()}, "d41d8cd98f00b204e9800998ecf8427e"},
   128  		{"Hash the entire body by regexp", args{requestPostWithBody, ".*", md5.New()}, "2838333d94b3b7114a3cabdf4e4fadf4"},
   129  		{"Hash the entire body no regexp", args{requestPostWithBody, "", md5.New()}, "2838333d94b3b7114a3cabdf4e4fadf4"},
   130  		{"Hash by id regexp", args{requestPatchWithBody, "\"id\":[^,]*", md5.New()}, "abe7ef0275f752342a4bf370afb0be2b"},
   131  	}
   132  	for _, tt := range tests {
   133  		t.Run(tt.name, func(t *testing.T) {
   134  			if addBodyHash(tt.args.req, tt.args.regex, tt.args.h); hex.EncodeToString(tt.args.h.Sum(nil)) != tt.expected {
   135  				t.Errorf("addBodyHash() recieved = %v, expected %v", hex.EncodeToString(tt.args.h.Sum(nil)), tt.expected)
   136  			}
   137  		})
   138  	}
   139  }