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  }