1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
23 func TestQuery(t *testing.T) {
24 req := &Request{Method: "GET"}
25 req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
26 if q := req.FormValue("q"); q != "foo" {
27 t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
31 func TestPostQuery(t *testing.T) {
32 req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
33 strings.NewReader("z=post&both=y"))
34 req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
36 if q := req.FormValue("q"); q != "foo" {
37 t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
39 if z := req.FormValue("z"); z != "post" {
40 t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
42 if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
43 t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
47 type stringMap map[string][]string
48 type parseContentTypeTest struct {
52 var parseContentTypeTests = []parseContentTypeTest{
53 {contentType: stringMap{"Content-Type": {"text/plain"}}},
54 {contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
55 {contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
57 contentType: stringMap{"Content-Type": {"application/unknown"}},
61 func TestParseFormBadContentType(t *testing.T) {
62 for i, test := range parseContentTypeTests {
65 Header: Header(test.contentType),
66 Body: ioutil.NopCloser(bytes.NewBufferString("body")),
68 err := req.ParseForm()
70 t.Errorf("test %d should have returned error", i)
75 func TestMultipartReader(t *testing.T) {
78 Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
79 Body: ioutil.NopCloser(new(bytes.Buffer)),
81 multipart, err := req.MultipartReader()
83 t.Errorf("expected multipart; error: %v", err)
86 req.Header = Header{"Content-Type": {"text/plain"}}
87 multipart, err = req.MultipartReader()
89 t.Errorf("unexpected multipart for text/plain")
93 func TestRedirect(t *testing.T) {
94 ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
97 w.Header().Set("Location", "/foo/")
98 w.WriteHeader(StatusSeeOther)
100 fmt.Fprintf(w, "foo")
102 w.WriteHeader(StatusBadRequest)
107 var end = regexp.MustCompile("/foo/$")
108 r, err := Get(ts.URL)
113 url := r.Request.URL.String()
114 if r.StatusCode != 200 || !end.MatchString(url) {
115 t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
119 func TestSetBasicAuth(t *testing.T) {
120 r, _ := NewRequest("GET", "http://example.com/", nil)
121 r.SetBasicAuth("Aladdin", "open sesame")
122 if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
123 t.Errorf("got header %q, want %q", g, e)
127 func TestMultipartRequest(t *testing.T) {
128 // Test that we can read the values and files of a
129 // multipart request with FormValue and FormFile,
130 // and that ParseMultipartForm can be called multiple times.
131 req := newTestMultipartRequest(t)
132 if err := req.ParseMultipartForm(25); err != nil {
133 t.Fatal("ParseMultipartForm first call:", err)
135 defer req.MultipartForm.RemoveAll()
136 validateTestMultipartContents(t, req, false)
137 if err := req.ParseMultipartForm(25); err != nil {
138 t.Fatal("ParseMultipartForm second call:", err)
140 validateTestMultipartContents(t, req, false)
143 func TestMultipartRequestAuto(t *testing.T) {
144 // Test that FormValue and FormFile automatically invoke
145 // ParseMultipartForm and return the right values.
146 req := newTestMultipartRequest(t)
148 if req.MultipartForm != nil {
149 req.MultipartForm.RemoveAll()
152 validateTestMultipartContents(t, req, true)
155 func TestEmptyMultipartRequest(t *testing.T) {
156 // Test that FormValue and FormFile automatically invoke
157 // ParseMultipartForm and return the right values.
158 req, err := NewRequest("GET", "/", nil)
160 t.Errorf("NewRequest err = %q", err)
162 testMissingFile(t, req)
165 func TestRequestMultipartCallOrder(t *testing.T) {
166 req := newTestMultipartRequest(t)
167 _, err := req.MultipartReader()
169 t.Fatalf("MultipartReader: %v", err)
171 err = req.ParseMultipartForm(1024)
173 t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader")
177 func testMissingFile(t *testing.T, req *Request) {
178 f, fh, err := req.FormFile("missing")
180 t.Errorf("FormFile file = %q, want nil", f)
183 t.Errorf("FormFile file header = %q, want nil", fh)
185 if err != ErrMissingFile {
186 t.Errorf("FormFile err = %q, want ErrMissingFile", err)
190 func newTestMultipartRequest(t *testing.T) *Request {
191 b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
192 req, err := NewRequest("POST", "/", b)
194 t.Fatal("NewRequest:", err)
196 ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
197 req.Header.Set("Content-type", ctype)
201 func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
202 if g, e := req.FormValue("texta"), textaValue; g != e {
203 t.Errorf("texta value = %q, want %q", g, e)
205 if g, e := req.FormValue("texta"), textaValue; g != e {
206 t.Errorf("texta value = %q, want %q", g, e)
208 if g := req.FormValue("missing"); g != "" {
209 t.Errorf("missing value = %q, want empty string", g)
212 assertMem := func(n string, fd multipart.File) {
213 if _, ok := fd.(*os.File); ok {
214 t.Error(n, " is *os.File, should not be")
217 fd := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
218 assertMem("filea", fd)
219 fd = testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
221 assertMem("fileb", fd)
223 if _, ok := fd.(*os.File); !ok {
224 t.Errorf("fileb has unexpected underlying type %T", fd)
228 testMissingFile(t, req)
231 func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
232 f, fh, err := req.FormFile(key)
234 t.Fatalf("FormFile(%q): %q", key, err)
236 if fh.Filename != expectFilename {
237 t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
240 _, err = io.Copy(&b, f)
242 t.Fatal("copying contents:", err)
244 if g := b.String(); g != expectContent {
245 t.Errorf("contents = %q, want %q", g, expectContent)
251 fileaContents = "This is a test file."
252 filebContents = "Another test file."
255 boundary = `MyBoundary`
260 Content-Disposition: form-data; name="filea"; filename="filea.txt"
261 Content-Type: text/plain
263 ` + fileaContents + `
265 Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
266 Content-Type: text/plain
268 ` + filebContents + `
270 Content-Disposition: form-data; name="texta"
274 Content-Disposition: form-data; name="textb"