1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// 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 }
|