| // Copyright 2012 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package http | |
| import ( | |
| "net/url" | |
| "testing" | |
| ) | |
| var serveMuxRegister = []struct { | |
| pattern string | |
| h Handler | |
| }{ | |
| {"/dir/", serve(200)}, | |
| {"/search", serve(201)}, | |
| {"codesearch.google.com/search", serve(202)}, | |
| {"codesearch.google.com/", serve(203)}, | |
| } | |
| // serve returns a handler that sends a response with the given code. | |
| func serve(code int) HandlerFunc { | |
| return func(w ResponseWriter, r *Request) { | |
| w.WriteHeader(code) | |
| } | |
| } | |
| var serveMuxTests = []struct { | |
| method string | |
| host string | |
| path string | |
| code int | |
| pattern string | |
| }{ | |
| {"GET", "google.com", "/", 404, ""}, | |
| {"GET", "google.com", "/dir", 301, "/dir/"}, | |
| {"GET", "google.com", "/dir/", 200, "/dir/"}, | |
| {"GET", "google.com", "/dir/file", 200, "/dir/"}, | |
| {"GET", "google.com", "/search", 201, "/search"}, | |
| {"GET", "google.com", "/search/", 404, ""}, | |
| {"GET", "google.com", "/search/foo", 404, ""}, | |
| {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"}, | |
| {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"}, | |
| {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"}, | |
| {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"}, | |
| {"GET", "images.google.com", "/search", 201, "/search"}, | |
| {"GET", "images.google.com", "/search/", 404, ""}, | |
| {"GET", "images.google.com", "/search/foo", 404, ""}, | |
| {"GET", "google.com", "/../search", 301, "/search"}, | |
| {"GET", "google.com", "/dir/..", 301, ""}, | |
| {"GET", "google.com", "/dir/..", 301, ""}, | |
| {"GET", "google.com", "/dir/./file", 301, "/dir/"}, | |
| // The /foo -> /foo/ redirect applies to CONNECT requests | |
| // but the path canonicalization does not. | |
| {"CONNECT", "google.com", "/dir", 301, "/dir/"}, | |
| {"CONNECT", "google.com", "/../search", 404, ""}, | |
| {"CONNECT", "google.com", "/dir/..", 200, "/dir/"}, | |
| {"CONNECT", "google.com", "/dir/..", 200, "/dir/"}, | |
| {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"}, | |
| } | |
| func TestServeMuxHandler(t *testing.T) { | |
| mux := NewServeMux() | |
| for _, e := range serveMuxRegister { | |
| mux.Handle(e.pattern, e.h) | |
| } | |
| for _, tt := range serveMuxTests { | |
| r := &Request{ | |
| Method: tt.method, | |
| Host: tt.host, | |
| URL: &url.URL{ | |
| Path: tt.path, | |
| }, | |
| } | |
| h, pattern := mux.Handler(r) | |
| cs := &codeSaver{h: Header{}} | |
| h.ServeHTTP(cs, r) | |
| if pattern != tt.pattern || cs.code != tt.code { | |
| t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, cs.code, pattern, tt.code, tt.pattern) | |
| } | |
| } | |
| } | |
| // A codeSaver is a ResponseWriter that saves the code passed to WriteHeader. | |
| type codeSaver struct { | |
| h Header | |
| code int | |
| } | |
| func (cs *codeSaver) Header() Header { return cs.h } | |
| func (cs *codeSaver) Write(p []byte) (int, error) { return len(p), nil } | |
| func (cs *codeSaver) WriteHeader(code int) { cs.code = code } |