func TestNoMatch(t *testing.T) { t.Parallel() var rt router rt.add(boolPattern(false), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Fatal("did not expect handler to be called") })) _, r := wr() ctx := context.Background() ctx = context.WithValue(ctx, internal.Pattern, boolPattern(true)) ctx = context.WithValue(ctx, internal.Pattern, boolPattern(true)) ctx = context.WithValue(ctx, pattern.Variable("answer"), 42) ctx = context.WithValue(ctx, internal.Path, "/") r = r.WithContext(ctx) r = rt.route(r) ctx = r.Context() if p := ctx.Value(internal.Pattern); p != nil { t.Errorf("unexpected pattern %v", p) } if h := ctx.Value(internal.Handler); h != nil { t.Errorf("unexpected handler %v", h) } if h := ctx.Value(pattern.Variable("answer")); h != 42 { t.Errorf("context didn't work: got %v, wanted %v", h, 42) } }
func TestExistingContext(t *testing.T) { t.Parallel() pat := New("/hi/:c/:a/:r/:l") req, err := http.NewRequest("GET", "/hi/foo/bar/baz/quux", nil) if err != nil { panic(err) } ctx := context.Background() ctx = pattern.SetPath(ctx, req.URL.EscapedPath()) ctx = context.WithValue(ctx, pattern.AllVariables, map[pattern.Variable]interface{}{ "hello": "world", "c": "nope", }) ctx = context.WithValue(ctx, pattern.Variable("user"), "carl") req = req.WithContext(ctx) req = pat.Match(req) if req == nil { t.Fatalf("expected pattern to match") } ctx = req.Context() expected := map[pattern.Variable]interface{}{ "c": "foo", "a": "bar", "r": "baz", "l": "quux", } for k, v := range expected { if p := Param(req, string(k)); p != v { t.Errorf("expected %s=%q, got %q", k, v, p) } } expected["hello"] = "world" all := ctx.Value(pattern.AllVariables).(map[pattern.Variable]interface{}) if !reflect.DeepEqual(all, expected) { t.Errorf("expected %v, got %v", expected, all) } if path := pattern.Path(ctx); path != "" { t.Errorf("expected path=%q, got %q", "", path) } if user := ctx.Value(pattern.Variable("user")); user != "carl" { t.Errorf("expected user=%q, got %q", "carl", user) } }
/* New returns a new Pattern from the given Pat route. See the package documentation for more information about what syntax is accepted by this function. */ func New(pat string) *Pattern { p := &Pattern{raw: pat} if strings.HasSuffix(pat, "/*") { pat = pat[:len(pat)-1] p.wildcard = true } matches := patternRe.FindAllStringSubmatchIndex(pat, -1) numMatches := len(matches) p.pats = make(patNames, numMatches) p.breaks = make([]byte, numMatches) p.literals = make([]string, numMatches+1) n := 0 for i, match := range matches { a, b := match[2], match[3] p.literals[i] = pat[n : a-1] // Need to leave off the colon p.pats[i].name = pattern.Variable(pat[a:b]) p.pats[i].idx = i if b == len(pat) { p.breaks[i] = '/' } else { p.breaks[i] = pat[b] } n = b } p.literals[numMatches] = pat[n:] sort.Sort(p.pats) return p }
func TestRouterContextPropagation(t *testing.T) { t.Parallel() var rt router rt.add(contextPattern{}, intHandler(0)) _, r := wr() r = r.WithContext(context.WithValue(r.Context(), internal.Path, "/")) r2 := rt.route(r) ctx := r2.Context() if hello := ctx.Value(pattern.Variable("hello")).(string); hello != "world" { t.Fatalf("routed request didn't include correct key from pattern: %q", hello) } }
/* Param returns the bound parameter with the given name. For instance, given the route: /user/:name and the URL Path: /user/carl a call to Param(ctx, "name") would return the string "carl". It is the caller's responsibility to ensure that the variable has been bound. Attempts to access variables that have not been set (or which have been invalidly set) are considered programmer errors and will trigger a panic. */ func Param(ctx context.Context, name string) string { return ctx.Value(pattern.Variable(name)).(string) }
func (contextPattern) Match(r *http.Request) *http.Request { return r.WithContext(context.WithValue(r.Context(), pattern.Variable("hello"), "world")) }
/* Param returns the bound parameter with the given name. For instance, given the route: /user/:name and the URL Path: /user/carl a call to Param(r, "name") would return the string "carl". It is the caller's responsibility to ensure that the variable has been bound. Attempts to access variables that have not been set (or which have been invalidly set) are considered programmer errors and will trigger a panic. */ func Param(r *http.Request, name string) string { return r.Context().Value(pattern.Variable(name)).(string) }