github.com/avenga/couper@v1.12.2/server/mux_test.go (about) 1 package server_test 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "reflect" 7 "testing" 8 9 "github.com/avenga/couper/config/request" 10 "github.com/avenga/couper/config/runtime" 11 rs "github.com/avenga/couper/config/runtime/server" 12 "github.com/avenga/couper/errors" 13 "github.com/avenga/couper/server" 14 ) 15 16 func TestSortPathPatterns(t *testing.T) { 17 pathPatterns := []string{ 18 "/a/b/c", 19 "/a/b/{c}", 20 "/**", 21 "/{a}/b/{c}", 22 "/a/b/**", 23 "/a/{b}/c", 24 "/", 25 "/{a}/{b}/**", 26 "/a/{b}", 27 "/a/**", 28 "/a/{b}/{c}", 29 "/{a}", 30 "/{a}/b/c", 31 "/{a}/b/**", 32 "/{a}/{b}/c", 33 "/{a}/**", 34 "/{a}/{b}/{c}", 35 "/a/b", 36 "/{a}/b", 37 "/{a}/{b}", 38 "/a", 39 } 40 server.SortPathPatterns(pathPatterns) 41 expectedSortedPathPatterns := []string{ 42 "/a/b/c", 43 "/a/b/{c}", 44 "/a/{b}/c", 45 "/a/{b}/{c}", 46 "/{a}/b/c", 47 "/{a}/b/{c}", 48 "/{a}/{b}/c", 49 "/{a}/{b}/{c}", 50 "/a/b", 51 "/a/{b}", 52 "/{a}/b", 53 "/{a}/{b}", 54 "/", 55 "/a", 56 "/{a}", 57 "/a/b/**", 58 "/{a}/b/**", 59 "/{a}/{b}/**", 60 "/a/**", 61 "/{a}/**", 62 "/**", 63 } 64 if !reflect.DeepEqual(expectedSortedPathPatterns, pathPatterns) { 65 t.Errorf("exp: %v\ngot:%v", expectedSortedPathPatterns, pathPatterns) 66 } 67 } 68 69 func TestMux_FindHandler_PathParamContext(t *testing.T) { 70 type noContentHandler http.Handler 71 var noContent noContentHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 72 rw.WriteHeader(http.StatusNoContent) 73 }) 74 75 serverOptions, _ := rs.NewServerOptions(nil, nil) 76 serverOptions.FilesBasePaths = []string{"/"} 77 78 testOptions := &runtime.MuxOptions{ 79 EndpointRoutes: map[string]http.Handler{ 80 "/without": http.NotFoundHandler(), 81 "/with/{my}/parameter": noContent, 82 "/{section}/cms": noContent, 83 "/a/{b}": noContent, 84 "/{b}/a": noContent, 85 "/{section}/{project}": noContent, 86 "/project/{project}/**": noContent, 87 "/w/c/{param}/**": noContent, 88 "/prefix/**": noContent, 89 }, 90 FileRoutes: map[string]http.Handler{ 91 "/htdocs/test.html": noContent, 92 }, 93 ServerOptions: serverOptions, 94 } 95 96 newReq := func(path string) *http.Request { 97 return httptest.NewRequest(http.MethodGet, path, nil) 98 } 99 100 tests := []struct { 101 name string 102 req *http.Request 103 want http.Handler 104 expParams request.PathParameter 105 expWildcard string 106 }{ 107 {" /wo path params", newReq("/without"), http.NotFoundHandler(), request.PathParameter{}, ""}, 108 {" /w path params", newReq("/with/my123/parameter"), noContent, request.PathParameter{ 109 "my": "my123", 110 }, ""}, 111 {" /w 1st path param #1", newReq("/with/cms"), noContent, request.PathParameter{ 112 "section": "with", 113 }, ""}, 114 {" /w 1st path param #2", newReq("/c/a"), noContent, request.PathParameter{ 115 "b": "c", 116 }, ""}, 117 {" w/o 1nd path param", newReq("//a"), http.NotFoundHandler(), nil, ""}, 118 {" /w 2nd path param", newReq("/a/c"), noContent, request.PathParameter{ 119 "b": "c", 120 }, ""}, 121 {" w/o 2nd path param", newReq("/a"), http.NotFoundHandler(), nil, ""}, 122 {" w/o 2nd path param", newReq("/a/"), http.NotFoundHandler(), nil, ""}, 123 {" w/o 2nd path param", newReq("/a//"), http.NotFoundHandler(), nil, ""}, 124 {" /w two path param", newReq("/foo/bar"), noContent, request.PathParameter{ 125 "section": "foo", 126 "project": "bar", 127 }, ""}, 128 {" w/o two path params", newReq("//"), http.NotFoundHandler(), nil, ""}, 129 {" /w path param and expWildcard", newReq("/project/foo/bar/ha"), noContent, request.PathParameter{ 130 "project": "foo", 131 }, "bar/ha"}, 132 {" /w non existing path", newReq("/foo/{bar}/123"), errors.DefaultJSON.WithError(errors.RouteNotFound), nil, ""}, 133 {" files", newReq("/htdocs/test.html"), http.NotFoundHandler(), request.PathParameter{ 134 "section": "htdocs", 135 "project": "test.html", 136 }, ""}, 137 {" w/ path param and wildcard", newReq("/w/c/my-param/wild/ca/rd"), noContent, request.PathParameter{ 138 "param": "my-param", 139 }, "wild/ca/rd"}, 140 {" w/ path param, w/o wildcard", newReq("/w/c/my-param"), noContent, request.PathParameter{ 141 "param": "my-param", 142 }, ""}, 143 {" w/ path param, trailing /, w/o wildcard", newReq("/w/c/my-param/"), noContent, request.PathParameter{ 144 "param": "my-param", 145 }, ""}, 146 {" w/o path param, w/ wildcard", newReq("/w/c//wild/card"), http.NotFoundHandler(), nil, ""}, 147 {" w/o path param, w/o wildcard", newReq("/w/c"), noContent, request.PathParameter{ 148 "section": "w", 149 "project": "c", 150 }, ""}, 151 {" w/o path param, w/o wildcard, single /", newReq("/w/c/"), noContent, request.PathParameter{ 152 "section": "w", 153 "project": "c", 154 }, ""}, 155 {" w/o path param, w/o wildcard, double /", newReq("/w/c//"), http.NotFoundHandler(), nil, ""}, 156 {" w/o path param, w/o wildcard, triple /", newReq("/w/c///"), http.NotFoundHandler(), nil, ""}, 157 {"** not just concatenating", newReq("/prefixandsomethingelse"), http.NotFoundHandler(), nil, ""}, 158 } 159 for _, tt := range tests { 160 t.Run(tt.name, func(subT *testing.T) { 161 mux := server.NewMux(testOptions) 162 mux.RegisterConfigured() 163 164 if got := mux.FindHandler(tt.req); reflect.DeepEqual(got, tt.want) { 165 subT.Errorf("FindHandler() = %v, want %v", got, tt.want) 166 } 167 168 paramCtx, ok := tt.req.Context().Value(request.PathParams).(request.PathParameter) 169 if !ok { 170 if tt.expParams == nil { 171 return 172 } 173 subT.Fatalf("Expected path parameters") 174 } 175 176 if !reflect.DeepEqual(paramCtx, tt.expParams) { 177 subT.Errorf("Path parameter context: %#v, want: %#v", paramCtx, tt.expParams) 178 } 179 180 wildcardCtx, ok := tt.req.Context().Value(request.Wildcard).(string) 181 if !ok { 182 if tt.expWildcard == "" { 183 return 184 } 185 subT.Fatal("Expected expWildcard value") 186 } 187 188 if wildcardCtx != tt.expWildcard { 189 subT.Errorf("Wildcard context: %q, want: %q", wildcardCtx, tt.expWildcard) 190 } 191 }) 192 } 193 }