request_test.go 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  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.
  4. package http_test
  5. import (
  6. "bufio"
  7. "bytes"
  8. "context"
  9. "crypto/rand"
  10. "encoding/base64"
  11. "fmt"
  12. "io"
  13. "math"
  14. "mime/multipart"
  15. . "net/http"
  16. "net/http/httptest"
  17. "net/url"
  18. "os"
  19. "reflect"
  20. "regexp"
  21. "strings"
  22. "testing"
  23. )
  24. func TestQuery(t *testing.T) {
  25. req := &Request{Method: "GET"}
  26. req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
  27. if q := req.FormValue("q"); q != "foo" {
  28. t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
  29. }
  30. }
  31. // Issue #25192: Test that ParseForm fails but still parses the form when an URL
  32. // containing a semicolon is provided.
  33. func TestParseFormSemicolonSeparator(t *testing.T) {
  34. for _, method := range []string{"POST", "PATCH", "PUT", "GET"} {
  35. req, _ := NewRequest(method, "http://www.google.com/search?q=foo;q=bar&a=1",
  36. strings.NewReader("q"))
  37. err := req.ParseForm()
  38. if err == nil {
  39. t.Fatalf(`for method %s, ParseForm expected an error, got success`, method)
  40. }
  41. wantForm := url.Values{"a": []string{"1"}}
  42. if !reflect.DeepEqual(req.Form, wantForm) {
  43. t.Fatalf("for method %s, ParseForm expected req.Form = %v, want %v", method, req.Form, wantForm)
  44. }
  45. }
  46. }
  47. func TestParseFormQuery(t *testing.T) {
  48. req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&orphan=nope&empty=not",
  49. strings.NewReader("z=post&both=y&prio=2&=nokey&orphan&empty=&"))
  50. req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
  51. if q := req.FormValue("q"); q != "foo" {
  52. t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
  53. }
  54. if z := req.FormValue("z"); z != "post" {
  55. t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
  56. }
  57. if bq, found := req.PostForm["q"]; found {
  58. t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
  59. }
  60. if bz := req.PostFormValue("z"); bz != "post" {
  61. t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
  62. }
  63. if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
  64. t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
  65. }
  66. if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
  67. t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
  68. }
  69. if prio := req.FormValue("prio"); prio != "2" {
  70. t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
  71. }
  72. if orphan := req.Form["orphan"]; !reflect.DeepEqual(orphan, []string{"", "nope"}) {
  73. t.Errorf(`req.FormValue("orphan") = %q, want "" (from body)`, orphan)
  74. }
  75. if empty := req.Form["empty"]; !reflect.DeepEqual(empty, []string{"", "not"}) {
  76. t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
  77. }
  78. if nokey := req.Form[""]; !reflect.DeepEqual(nokey, []string{"nokey"}) {
  79. t.Errorf(`req.FormValue("nokey") = %q, want "nokey" (from body)`, nokey)
  80. }
  81. }
  82. // Tests that we only parse the form automatically for certain methods.
  83. func TestParseFormQueryMethods(t *testing.T) {
  84. for _, method := range []string{"POST", "PATCH", "PUT", "FOO"} {
  85. req, _ := NewRequest(method, "http://www.google.com/search",
  86. strings.NewReader("foo=bar"))
  87. req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
  88. want := "bar"
  89. if method == "FOO" {
  90. want = ""
  91. }
  92. if got := req.FormValue("foo"); got != want {
  93. t.Errorf(`for method %s, FormValue("foo") = %q; want %q`, method, got, want)
  94. }
  95. }
  96. }
  97. func TestParseFormUnknownContentType(t *testing.T) {
  98. for _, test := range []struct {
  99. name string
  100. wantErr string
  101. contentType Header
  102. }{
  103. {"text", "", Header{"Content-Type": {"text/plain"}}},
  104. // Empty content type is legal - may be treated as
  105. // application/octet-stream (RFC 7231, section 3.1.1.5)
  106. {"empty", "", Header{}},
  107. {"boundary", "mime: invalid media parameter", Header{"Content-Type": {"text/plain; boundary="}}},
  108. {"unknown", "", Header{"Content-Type": {"application/unknown"}}},
  109. } {
  110. t.Run(test.name,
  111. func(t *testing.T) {
  112. req := &Request{
  113. Method: "POST",
  114. Header: test.contentType,
  115. Body: io.NopCloser(strings.NewReader("body")),
  116. }
  117. err := req.ParseForm()
  118. switch {
  119. case err == nil && test.wantErr != "":
  120. t.Errorf("unexpected success; want error %q", test.wantErr)
  121. case err != nil && test.wantErr == "":
  122. t.Errorf("want success, got error: %v", err)
  123. case test.wantErr != "" && test.wantErr != fmt.Sprint(err):
  124. t.Errorf("got error %q; want %q", err, test.wantErr)
  125. }
  126. },
  127. )
  128. }
  129. }
  130. func TestParseFormInitializeOnError(t *testing.T) {
  131. nilBody, _ := NewRequest("POST", "http://www.google.com/search?q=foo", nil)
  132. tests := []*Request{
  133. nilBody,
  134. {Method: "GET", URL: nil},
  135. }
  136. for i, req := range tests {
  137. err := req.ParseForm()
  138. if req.Form == nil {
  139. t.Errorf("%d. Form not initialized, error %v", i, err)
  140. }
  141. if req.PostForm == nil {
  142. t.Errorf("%d. PostForm not initialized, error %v", i, err)
  143. }
  144. }
  145. }
  146. func TestMultipartReader(t *testing.T) {
  147. tests := []struct {
  148. shouldError bool
  149. contentType string
  150. }{
  151. {false, `multipart/form-data; boundary="foo123"`},
  152. {false, `multipart/mixed; boundary="foo123"`},
  153. {true, `text/plain`},
  154. }
  155. for i, test := range tests {
  156. req := &Request{
  157. Method: "POST",
  158. Header: Header{"Content-Type": {test.contentType}},
  159. Body: io.NopCloser(new(bytes.Buffer)),
  160. }
  161. multipart, err := req.MultipartReader()
  162. if test.shouldError {
  163. if err == nil || multipart != nil {
  164. t.Errorf("test %d: unexpectedly got nil-error (%v) or non-nil-multipart (%v)", i, err, multipart)
  165. }
  166. continue
  167. }
  168. if err != nil || multipart == nil {
  169. t.Errorf("test %d: unexpectedly got error (%v) or nil-multipart (%v)", i, err, multipart)
  170. }
  171. }
  172. }
  173. // Issue 9305: ParseMultipartForm should populate PostForm too
  174. func TestParseMultipartFormPopulatesPostForm(t *testing.T) {
  175. postData :=
  176. `--xxx
  177. Content-Disposition: form-data; name="field1"
  178. value1
  179. --xxx
  180. Content-Disposition: form-data; name="field2"
  181. value2
  182. --xxx
  183. Content-Disposition: form-data; name="file"; filename="file"
  184. Content-Type: application/octet-stream
  185. Content-Transfer-Encoding: binary
  186. binary data
  187. --xxx--
  188. `
  189. req := &Request{
  190. Method: "POST",
  191. Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
  192. Body: io.NopCloser(strings.NewReader(postData)),
  193. }
  194. initialFormItems := map[string]string{
  195. "language": "Go",
  196. "name": "gopher",
  197. "skill": "go-ing",
  198. "field2": "initial-value2",
  199. }
  200. req.Form = make(url.Values)
  201. for k, v := range initialFormItems {
  202. req.Form.Add(k, v)
  203. }
  204. err := req.ParseMultipartForm(10000)
  205. if err != nil {
  206. t.Fatalf("unexpected multipart error %v", err)
  207. }
  208. wantForm := url.Values{
  209. "language": []string{"Go"},
  210. "name": []string{"gopher"},
  211. "skill": []string{"go-ing"},
  212. "field1": []string{"value1"},
  213. "field2": []string{"initial-value2", "value2"},
  214. }
  215. if !reflect.DeepEqual(req.Form, wantForm) {
  216. t.Fatalf("req.Form = %v, want %v", req.Form, wantForm)
  217. }
  218. wantPostForm := url.Values{
  219. "field1": []string{"value1"},
  220. "field2": []string{"value2"},
  221. }
  222. if !reflect.DeepEqual(req.PostForm, wantPostForm) {
  223. t.Fatalf("req.PostForm = %v, want %v", req.PostForm, wantPostForm)
  224. }
  225. }
  226. func TestParseMultipartForm(t *testing.T) {
  227. req := &Request{
  228. Method: "POST",
  229. Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
  230. Body: io.NopCloser(new(bytes.Buffer)),
  231. }
  232. err := req.ParseMultipartForm(25)
  233. if err == nil {
  234. t.Error("expected multipart EOF, got nil")
  235. }
  236. req.Header = Header{"Content-Type": {"text/plain"}}
  237. err = req.ParseMultipartForm(25)
  238. if err != ErrNotMultipart {
  239. t.Error("expected ErrNotMultipart for text/plain")
  240. }
  241. }
  242. // Issue 45789: multipart form should not include directory path in filename
  243. func TestParseMultipartFormFilename(t *testing.T) {
  244. postData :=
  245. `--xxx
  246. Content-Disposition: form-data; name="file"; filename="../usr/foobar.txt/"
  247. Content-Type: text/plain
  248. --xxx--
  249. `
  250. req := &Request{
  251. Method: "POST",
  252. Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
  253. Body: io.NopCloser(strings.NewReader(postData)),
  254. }
  255. _, hdr, err := req.FormFile("file")
  256. if err != nil {
  257. t.Fatal(err)
  258. }
  259. if hdr.Filename != "foobar.txt" {
  260. t.Errorf("expected only the last element of the path, got %q", hdr.Filename)
  261. }
  262. }
  263. // Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with
  264. // the payload size and the internal leeway buffer size of 10MiB overflows, that we
  265. // correctly return an error.
  266. func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
  267. defer afterTest(t)
  268. payloadSize := 1 << 10
  269. cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
  270. // The combination of:
  271. // MaxInt64 + payloadSize + (internal spare of 10MiB)
  272. // triggers the overflow. See issue https://golang.org/issue/40430/
  273. if err := req.ParseMultipartForm(math.MaxInt64); err != nil {
  274. Error(rw, err.Error(), StatusBadRequest)
  275. return
  276. }
  277. }))
  278. defer cst.Close()
  279. fBuf := new(bytes.Buffer)
  280. mw := multipart.NewWriter(fBuf)
  281. mf, err := mw.CreateFormFile("file", "myfile.txt")
  282. if err != nil {
  283. t.Fatal(err)
  284. }
  285. if _, err := mf.Write(bytes.Repeat([]byte("abc"), payloadSize)); err != nil {
  286. t.Fatal(err)
  287. }
  288. if err := mw.Close(); err != nil {
  289. t.Fatal(err)
  290. }
  291. req, err := NewRequest("POST", cst.URL, fBuf)
  292. if err != nil {
  293. t.Fatal(err)
  294. }
  295. req.Header.Set("Content-Type", mw.FormDataContentType())
  296. res, err := cst.Client().Do(req)
  297. if err != nil {
  298. t.Fatal(err)
  299. }
  300. res.Body.Close()
  301. if g, w := res.StatusCode, StatusOK; g != w {
  302. t.Fatalf("Status code mismatch: got %d, want %d", g, w)
  303. }
  304. }
  305. func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
  306. func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
  307. func testRedirect(t *testing.T, h2 bool) {
  308. defer afterTest(t)
  309. cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
  310. switch r.URL.Path {
  311. case "/":
  312. w.Header().Set("Location", "/foo/")
  313. w.WriteHeader(StatusSeeOther)
  314. case "/foo/":
  315. fmt.Fprintf(w, "foo")
  316. default:
  317. w.WriteHeader(StatusBadRequest)
  318. }
  319. }))
  320. defer cst.close()
  321. var end = regexp.MustCompile("/foo/$")
  322. r, err := cst.c.Get(cst.ts.URL)
  323. if err != nil {
  324. t.Fatal(err)
  325. }
  326. r.Body.Close()
  327. url := r.Request.URL.String()
  328. if r.StatusCode != 200 || !end.MatchString(url) {
  329. t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
  330. }
  331. }
  332. func TestSetBasicAuth(t *testing.T) {
  333. r, _ := NewRequest("GET", "http://example.com/", nil)
  334. r.SetBasicAuth("Aladdin", "open sesame")
  335. if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
  336. t.Errorf("got header %q, want %q", g, e)
  337. }
  338. }
  339. func TestMultipartRequest(t *testing.T) {
  340. // Test that we can read the values and files of a
  341. // multipart request with FormValue and FormFile,
  342. // and that ParseMultipartForm can be called multiple times.
  343. req := newTestMultipartRequest(t)
  344. if err := req.ParseMultipartForm(25); err != nil {
  345. t.Fatal("ParseMultipartForm first call:", err)
  346. }
  347. defer req.MultipartForm.RemoveAll()
  348. validateTestMultipartContents(t, req, false)
  349. if err := req.ParseMultipartForm(25); err != nil {
  350. t.Fatal("ParseMultipartForm second call:", err)
  351. }
  352. validateTestMultipartContents(t, req, false)
  353. }
  354. // Issue #25192: Test that ParseMultipartForm fails but still parses the
  355. // multi-part form when an URL containing a semicolon is provided.
  356. func TestParseMultipartFormSemicolonSeparator(t *testing.T) {
  357. req := newTestMultipartRequest(t)
  358. req.URL = &url.URL{RawQuery: "q=foo;q=bar"}
  359. if err := req.ParseMultipartForm(25); err == nil {
  360. t.Fatal("ParseMultipartForm expected error due to invalid semicolon, got nil")
  361. }
  362. defer req.MultipartForm.RemoveAll()
  363. validateTestMultipartContents(t, req, false)
  364. }
  365. func TestMultipartRequestAuto(t *testing.T) {
  366. // Test that FormValue and FormFile automatically invoke
  367. // ParseMultipartForm and return the right values.
  368. req := newTestMultipartRequest(t)
  369. defer func() {
  370. if req.MultipartForm != nil {
  371. req.MultipartForm.RemoveAll()
  372. }
  373. }()
  374. validateTestMultipartContents(t, req, true)
  375. }
  376. func TestMissingFileMultipartRequest(t *testing.T) {
  377. // Test that FormFile returns an error if
  378. // the named file is missing.
  379. req := newTestMultipartRequest(t)
  380. testMissingFile(t, req)
  381. }
  382. // Test that FormValue invokes ParseMultipartForm.
  383. func TestFormValueCallsParseMultipartForm(t *testing.T) {
  384. req, _ := NewRequest("POST", "http://www.google.com/", strings.NewReader("z=post"))
  385. req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
  386. if req.Form != nil {
  387. t.Fatal("Unexpected request Form, want nil")
  388. }
  389. req.FormValue("z")
  390. if req.Form == nil {
  391. t.Fatal("ParseMultipartForm not called by FormValue")
  392. }
  393. }
  394. // Test that FormFile invokes ParseMultipartForm.
  395. func TestFormFileCallsParseMultipartForm(t *testing.T) {
  396. req := newTestMultipartRequest(t)
  397. if req.Form != nil {
  398. t.Fatal("Unexpected request Form, want nil")
  399. }
  400. req.FormFile("")
  401. if req.Form == nil {
  402. t.Fatal("ParseMultipartForm not called by FormFile")
  403. }
  404. }
  405. // Test that ParseMultipartForm errors if called
  406. // after MultipartReader on the same request.
  407. func TestParseMultipartFormOrder(t *testing.T) {
  408. req := newTestMultipartRequest(t)
  409. if _, err := req.MultipartReader(); err != nil {
  410. t.Fatalf("MultipartReader: %v", err)
  411. }
  412. if err := req.ParseMultipartForm(1024); err == nil {
  413. t.Fatal("expected an error from ParseMultipartForm after call to MultipartReader")
  414. }
  415. }
  416. // Test that MultipartReader errors if called
  417. // after ParseMultipartForm on the same request.
  418. func TestMultipartReaderOrder(t *testing.T) {
  419. req := newTestMultipartRequest(t)
  420. if err := req.ParseMultipartForm(25); err != nil {
  421. t.Fatalf("ParseMultipartForm: %v", err)
  422. }
  423. defer req.MultipartForm.RemoveAll()
  424. if _, err := req.MultipartReader(); err == nil {
  425. t.Fatal("expected an error from MultipartReader after call to ParseMultipartForm")
  426. }
  427. }
  428. // Test that FormFile errors if called after
  429. // MultipartReader on the same request.
  430. func TestFormFileOrder(t *testing.T) {
  431. req := newTestMultipartRequest(t)
  432. if _, err := req.MultipartReader(); err != nil {
  433. t.Fatalf("MultipartReader: %v", err)
  434. }
  435. if _, _, err := req.FormFile(""); err == nil {
  436. t.Fatal("expected an error from FormFile after call to MultipartReader")
  437. }
  438. }
  439. var readRequestErrorTests = []struct {
  440. in string
  441. err string
  442. header Header
  443. }{
  444. 0: {"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", "", Header{"Header": {"foo"}}},
  445. 1: {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF.Error(), nil},
  446. 2: {"", io.EOF.Error(), nil},
  447. 3: {
  448. in: "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
  449. err: "http: method cannot contain a Content-Length",
  450. },
  451. 4: {
  452. in: "HEAD / HTTP/1.1\r\n\r\n",
  453. header: Header{},
  454. },
  455. // Multiple Content-Length values should either be
  456. // deduplicated if same or reject otherwise
  457. // See Issue 16490.
  458. 5: {
  459. in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n",
  460. err: "cannot contain multiple Content-Length headers",
  461. },
  462. 6: {
  463. in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n",
  464. err: "cannot contain multiple Content-Length headers",
  465. },
  466. 7: {
  467. in: "PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n",
  468. err: "",
  469. header: Header{"Content-Length": {"6"}},
  470. },
  471. 8: {
  472. in: "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n",
  473. err: "cannot contain multiple Content-Length headers",
  474. },
  475. 9: {
  476. in: "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n",
  477. err: "cannot contain multiple Content-Length headers",
  478. },
  479. 10: {
  480. in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
  481. header: Header{"Content-Length": {"0"}},
  482. },
  483. 11: {
  484. in: "HEAD / HTTP/1.1\r\nHost: foo\r\nHost: bar\r\n\r\n\r\n\r\n",
  485. err: "too many Host headers",
  486. },
  487. }
  488. func TestReadRequestErrors(t *testing.T) {
  489. for i, tt := range readRequestErrorTests {
  490. req, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in)))
  491. if err == nil {
  492. if tt.err != "" {
  493. t.Errorf("#%d: got nil err; want %q", i, tt.err)
  494. }
  495. if !reflect.DeepEqual(tt.header, req.Header) {
  496. t.Errorf("#%d: gotHeader: %q wantHeader: %q", i, req.Header, tt.header)
  497. }
  498. continue
  499. }
  500. if tt.err == "" || !strings.Contains(err.Error(), tt.err) {
  501. t.Errorf("%d: got error = %v; want %v", i, err, tt.err)
  502. }
  503. }
  504. }
  505. var newRequestHostTests = []struct {
  506. in, out string
  507. }{
  508. {"http://www.example.com/", "www.example.com"},
  509. {"http://www.example.com:8080/", "www.example.com:8080"},
  510. {"http://192.168.0.1/", "192.168.0.1"},
  511. {"http://192.168.0.1:8080/", "192.168.0.1:8080"},
  512. {"http://192.168.0.1:/", "192.168.0.1"},
  513. {"http://[fe80::1]/", "[fe80::1]"},
  514. {"http://[fe80::1]:8080/", "[fe80::1]:8080"},
  515. {"http://[fe80::1%25en0]/", "[fe80::1%en0]"},
  516. {"http://[fe80::1%25en0]:8080/", "[fe80::1%en0]:8080"},
  517. {"http://[fe80::1%25en0]:/", "[fe80::1%en0]"},
  518. }
  519. func TestNewRequestHost(t *testing.T) {
  520. for i, tt := range newRequestHostTests {
  521. req, err := NewRequest("GET", tt.in, nil)
  522. if err != nil {
  523. t.Errorf("#%v: %v", i, err)
  524. continue
  525. }
  526. if req.Host != tt.out {
  527. t.Errorf("got %q; want %q", req.Host, tt.out)
  528. }
  529. }
  530. }
  531. func TestRequestInvalidMethod(t *testing.T) {
  532. _, err := NewRequest("bad method", "http://foo.com/", nil)
  533. if err == nil {
  534. t.Error("expected error from NewRequest with invalid method")
  535. }
  536. req, err := NewRequest("GET", "http://foo.example/", nil)
  537. if err != nil {
  538. t.Fatal(err)
  539. }
  540. req.Method = "bad method"
  541. _, err = DefaultClient.Do(req)
  542. if err == nil || !strings.Contains(err.Error(), "invalid method") {
  543. t.Errorf("Transport error = %v; want invalid method", err)
  544. }
  545. req, err = NewRequest("", "http://foo.com/", nil)
  546. if err != nil {
  547. t.Errorf("NewRequest(empty method) = %v; want nil", err)
  548. } else if req.Method != "GET" {
  549. t.Errorf("NewRequest(empty method) has method %q; want GET", req.Method)
  550. }
  551. }
  552. func TestNewRequestContentLength(t *testing.T) {
  553. readByte := func(r io.Reader) io.Reader {
  554. var b [1]byte
  555. r.Read(b[:])
  556. return r
  557. }
  558. tests := []struct {
  559. r io.Reader
  560. want int64
  561. }{
  562. {bytes.NewReader([]byte("123")), 3},
  563. {bytes.NewBuffer([]byte("1234")), 4},
  564. {strings.NewReader("12345"), 5},
  565. {strings.NewReader(""), 0},
  566. {NoBody, 0},
  567. // Not detected. During Go 1.8 we tried to make these set to -1, but
  568. // due to Issue 18117, we keep these returning 0, even though they're
  569. // unknown.
  570. {struct{ io.Reader }{strings.NewReader("xyz")}, 0},
  571. {io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
  572. {readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
  573. }
  574. for i, tt := range tests {
  575. req, err := NewRequest("POST", "http://localhost/", tt.r)
  576. if err != nil {
  577. t.Fatal(err)
  578. }
  579. if req.ContentLength != tt.want {
  580. t.Errorf("test[%d]: ContentLength(%T) = %d; want %d", i, tt.r, req.ContentLength, tt.want)
  581. }
  582. }
  583. }
  584. var parseHTTPVersionTests = []struct {
  585. vers string
  586. major, minor int
  587. ok bool
  588. }{
  589. {"HTTP/0.0", 0, 0, true},
  590. {"HTTP/0.9", 0, 9, true},
  591. {"HTTP/1.0", 1, 0, true},
  592. {"HTTP/1.1", 1, 1, true},
  593. {"HTTP", 0, 0, false},
  594. {"HTTP/one.one", 0, 0, false},
  595. {"HTTP/1.1/", 0, 0, false},
  596. {"HTTP/-1,0", 0, 0, false},
  597. {"HTTP/0,-1", 0, 0, false},
  598. {"HTTP/", 0, 0, false},
  599. {"HTTP/1,1", 0, 0, false},
  600. {"HTTP/+1.1", 0, 0, false},
  601. {"HTTP/1.+1", 0, 0, false},
  602. {"HTTP/0000000001.1", 0, 0, false},
  603. {"HTTP/1.0000000001", 0, 0, false},
  604. {"HTTP/3.14", 0, 0, false},
  605. {"HTTP/12.3", 0, 0, false},
  606. }
  607. func TestParseHTTPVersion(t *testing.T) {
  608. for _, tt := range parseHTTPVersionTests {
  609. major, minor, ok := ParseHTTPVersion(tt.vers)
  610. if ok != tt.ok || major != tt.major || minor != tt.minor {
  611. type version struct {
  612. major, minor int
  613. ok bool
  614. }
  615. t.Errorf("failed to parse %q, expected: %#v, got %#v", tt.vers, version{tt.major, tt.minor, tt.ok}, version{major, minor, ok})
  616. }
  617. }
  618. }
  619. type getBasicAuthTest struct {
  620. username, password string
  621. ok bool
  622. }
  623. type basicAuthCredentialsTest struct {
  624. username, password string
  625. }
  626. var getBasicAuthTests = []struct {
  627. username, password string
  628. ok bool
  629. }{
  630. {"Aladdin", "open sesame", true},
  631. {"Aladdin", "open:sesame", true},
  632. {"", "", true},
  633. }
  634. func TestGetBasicAuth(t *testing.T) {
  635. for _, tt := range getBasicAuthTests {
  636. r, _ := NewRequest("GET", "http://example.com/", nil)
  637. r.SetBasicAuth(tt.username, tt.password)
  638. username, password, ok := r.BasicAuth()
  639. if ok != tt.ok || username != tt.username || password != tt.password {
  640. t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
  641. getBasicAuthTest{tt.username, tt.password, tt.ok})
  642. }
  643. }
  644. // Unauthenticated request.
  645. r, _ := NewRequest("GET", "http://example.com/", nil)
  646. username, password, ok := r.BasicAuth()
  647. if ok {
  648. t.Errorf("expected false from BasicAuth when the request is unauthenticated")
  649. }
  650. want := basicAuthCredentialsTest{"", ""}
  651. if username != want.username || password != want.password {
  652. t.Errorf("expected credentials: %#v when the request is unauthenticated, got %#v",
  653. want, basicAuthCredentialsTest{username, password})
  654. }
  655. }
  656. var parseBasicAuthTests = []struct {
  657. header, username, password string
  658. ok bool
  659. }{
  660. {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true},
  661. // Case doesn't matter:
  662. {"BASIC " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true},
  663. {"basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "Aladdin", "open sesame", true},
  664. {"Basic " + base64.StdEncoding.EncodeToString([]byte("Aladdin:open:sesame")), "Aladdin", "open:sesame", true},
  665. {"Basic " + base64.StdEncoding.EncodeToString([]byte(":")), "", "", true},
  666. {"Basic" + base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
  667. {base64.StdEncoding.EncodeToString([]byte("Aladdin:open sesame")), "", "", false},
  668. {"Basic ", "", "", false},
  669. {"Basic Aladdin:open sesame", "", "", false},
  670. {`Digest username="Aladdin"`, "", "", false},
  671. }
  672. func TestParseBasicAuth(t *testing.T) {
  673. for _, tt := range parseBasicAuthTests {
  674. r, _ := NewRequest("GET", "http://example.com/", nil)
  675. r.Header.Set("Authorization", tt.header)
  676. username, password, ok := r.BasicAuth()
  677. if ok != tt.ok || username != tt.username || password != tt.password {
  678. t.Errorf("BasicAuth() = %#v, want %#v", getBasicAuthTest{username, password, ok},
  679. getBasicAuthTest{tt.username, tt.password, tt.ok})
  680. }
  681. }
  682. }
  683. type logWrites struct {
  684. t *testing.T
  685. dst *[]string
  686. }
  687. func (l logWrites) WriteByte(c byte) error {
  688. l.t.Fatalf("unexpected WriteByte call")
  689. return nil
  690. }
  691. func (l logWrites) Write(p []byte) (n int, err error) {
  692. *l.dst = append(*l.dst, string(p))
  693. return len(p), nil
  694. }
  695. func TestRequestWriteBufferedWriter(t *testing.T) {
  696. got := []string{}
  697. req, _ := NewRequest("GET", "http://foo.com/", nil)
  698. req.Write(logWrites{t, &got})
  699. want := []string{
  700. "GET / HTTP/1.1\r\n",
  701. "Host: foo.com\r\n",
  702. "User-Agent: " + DefaultUserAgent + "\r\n",
  703. "\r\n",
  704. }
  705. if !reflect.DeepEqual(got, want) {
  706. t.Errorf("Writes = %q\n Want = %q", got, want)
  707. }
  708. }
  709. func TestRequestBadHost(t *testing.T) {
  710. got := []string{}
  711. req, err := NewRequest("GET", "http://foo/after", nil)
  712. if err != nil {
  713. t.Fatal(err)
  714. }
  715. req.Host = "foo.com with spaces"
  716. req.URL.Host = "foo.com with spaces"
  717. req.Write(logWrites{t, &got})
  718. want := []string{
  719. "GET /after HTTP/1.1\r\n",
  720. "Host: foo.com\r\n",
  721. "User-Agent: " + DefaultUserAgent + "\r\n",
  722. "\r\n",
  723. }
  724. if !reflect.DeepEqual(got, want) {
  725. t.Errorf("Writes = %q\n Want = %q", got, want)
  726. }
  727. }
  728. func TestStarRequest(t *testing.T) {
  729. req, err := ReadRequest(bufio.NewReader(strings.NewReader("M-SEARCH * HTTP/1.1\r\n\r\n")))
  730. if err != nil {
  731. return
  732. }
  733. if req.ContentLength != 0 {
  734. t.Errorf("ContentLength = %d; want 0", req.ContentLength)
  735. }
  736. if req.Body == nil {
  737. t.Errorf("Body = nil; want non-nil")
  738. }
  739. // Request.Write has Client semantics for Body/ContentLength,
  740. // where ContentLength 0 means unknown if Body is non-nil, and
  741. // thus chunking will happen unless we change semantics and
  742. // signal that we want to serialize it as exactly zero. The
  743. // only way to do that for outbound requests is with a nil
  744. // Body:
  745. clientReq := *req
  746. clientReq.Body = nil
  747. var out bytes.Buffer
  748. if err := clientReq.Write(&out); err != nil {
  749. t.Fatal(err)
  750. }
  751. if strings.Contains(out.String(), "chunked") {
  752. t.Error("wrote chunked request; want no body")
  753. }
  754. back, err := ReadRequest(bufio.NewReader(bytes.NewReader(out.Bytes())))
  755. if err != nil {
  756. t.Fatal(err)
  757. }
  758. // Ignore the Headers (the User-Agent breaks the deep equal,
  759. // but we don't care about it)
  760. req.Header = nil
  761. back.Header = nil
  762. if !reflect.DeepEqual(req, back) {
  763. t.Errorf("Original request doesn't match Request read back.")
  764. t.Logf("Original: %#v", req)
  765. t.Logf("Original.URL: %#v", req.URL)
  766. t.Logf("Wrote: %s", out.Bytes())
  767. t.Logf("Read back (doesn't match Original): %#v", back)
  768. }
  769. }
  770. type responseWriterJustWriter struct {
  771. io.Writer
  772. }
  773. func (responseWriterJustWriter) Header() Header { panic("should not be called") }
  774. func (responseWriterJustWriter) WriteHeader(int) { panic("should not be called") }
  775. // delayedEOFReader never returns (n > 0, io.EOF), instead putting
  776. // off the io.EOF until a subsequent Read call.
  777. type delayedEOFReader struct {
  778. r io.Reader
  779. }
  780. func (dr delayedEOFReader) Read(p []byte) (n int, err error) {
  781. n, err = dr.r.Read(p)
  782. if n > 0 && err == io.EOF {
  783. err = nil
  784. }
  785. return
  786. }
  787. func TestIssue10884_MaxBytesEOF(t *testing.T) {
  788. dst := io.Discard
  789. _, err := io.Copy(dst, MaxBytesReader(
  790. responseWriterJustWriter{dst},
  791. io.NopCloser(delayedEOFReader{strings.NewReader("12345")}),
  792. 5))
  793. if err != nil {
  794. t.Fatal(err)
  795. }
  796. }
  797. // Issue 14981: MaxBytesReader's return error wasn't sticky. It
  798. // doesn't technically need to be, but people expected it to be.
  799. func TestMaxBytesReaderStickyError(t *testing.T) {
  800. isSticky := func(r io.Reader) error {
  801. var log bytes.Buffer
  802. buf := make([]byte, 1000)
  803. var firstErr error
  804. for {
  805. n, err := r.Read(buf)
  806. fmt.Fprintf(&log, "Read(%d) = %d, %v\n", len(buf), n, err)
  807. if err == nil {
  808. continue
  809. }
  810. if firstErr == nil {
  811. firstErr = err
  812. continue
  813. }
  814. if !reflect.DeepEqual(err, firstErr) {
  815. return fmt.Errorf("non-sticky error. got log:\n%s", log.Bytes())
  816. }
  817. t.Logf("Got log: %s", log.Bytes())
  818. return nil
  819. }
  820. }
  821. tests := [...]struct {
  822. readable int
  823. limit int64
  824. }{
  825. 0: {99, 100},
  826. 1: {100, 100},
  827. 2: {101, 100},
  828. }
  829. for i, tt := range tests {
  830. rc := MaxBytesReader(nil, io.NopCloser(bytes.NewReader(make([]byte, tt.readable))), tt.limit)
  831. if err := isSticky(rc); err != nil {
  832. t.Errorf("%d. error: %v", i, err)
  833. }
  834. }
  835. }
  836. // Issue 45101: maxBytesReader's Read panicked when n < -1. This test
  837. // also ensures that Read treats negative limits as equivalent to 0.
  838. func TestMaxBytesReaderDifferentLimits(t *testing.T) {
  839. const testStr = "1234"
  840. tests := [...]struct {
  841. limit int64
  842. lenP int
  843. wantN int
  844. wantErr bool
  845. }{
  846. 0: {
  847. limit: -123,
  848. lenP: 0,
  849. wantN: 0,
  850. wantErr: false, // Ensure we won't return an error when the limit is negative, but we don't need to read.
  851. },
  852. 1: {
  853. limit: -100,
  854. lenP: 32 * 1024,
  855. wantN: 0,
  856. wantErr: true,
  857. },
  858. 2: {
  859. limit: -2,
  860. lenP: 1,
  861. wantN: 0,
  862. wantErr: true,
  863. },
  864. 3: {
  865. limit: -1,
  866. lenP: 2,
  867. wantN: 0,
  868. wantErr: true,
  869. },
  870. 4: {
  871. limit: 0,
  872. lenP: 3,
  873. wantN: 0,
  874. wantErr: true,
  875. },
  876. 5: {
  877. limit: 1,
  878. lenP: 4,
  879. wantN: 1,
  880. wantErr: true,
  881. },
  882. 6: {
  883. limit: 2,
  884. lenP: 5,
  885. wantN: 2,
  886. wantErr: true,
  887. },
  888. 7: {
  889. limit: 3,
  890. lenP: 2,
  891. wantN: 2,
  892. wantErr: false,
  893. },
  894. 8: {
  895. limit: int64(len(testStr)),
  896. lenP: len(testStr),
  897. wantN: len(testStr),
  898. wantErr: false,
  899. },
  900. 9: {
  901. limit: 100,
  902. lenP: 6,
  903. wantN: len(testStr),
  904. wantErr: false,
  905. },
  906. }
  907. for i, tt := range tests {
  908. rc := MaxBytesReader(nil, io.NopCloser(strings.NewReader(testStr)), tt.limit)
  909. n, err := rc.Read(make([]byte, tt.lenP))
  910. if n != tt.wantN {
  911. t.Errorf("%d. n: %d, want n: %d", i, n, tt.wantN)
  912. }
  913. if (err != nil) != tt.wantErr {
  914. t.Errorf("%d. error: %v", i, err)
  915. }
  916. }
  917. }
  918. func TestWithContextDeepCopiesURL(t *testing.T) {
  919. req, err := NewRequest("POST", "https://golang.org/", nil)
  920. if err != nil {
  921. t.Fatal(err)
  922. }
  923. reqCopy := req.WithContext(context.Background())
  924. reqCopy.URL.Scheme = "http"
  925. firstURL, secondURL := req.URL.String(), reqCopy.URL.String()
  926. if firstURL == secondURL {
  927. t.Errorf("unexpected change to original request's URL")
  928. }
  929. // And also check we don't crash on nil (Issue 20601)
  930. req.URL = nil
  931. reqCopy = req.WithContext(context.Background())
  932. if reqCopy.URL != nil {
  933. t.Error("expected nil URL in cloned request")
  934. }
  935. }
  936. // Ensure that Request.Clone creates a deep copy of TransferEncoding.
  937. // See issue 41907.
  938. func TestRequestCloneTransferEncoding(t *testing.T) {
  939. body := strings.NewReader("body")
  940. req, _ := NewRequest("POST", "https://example.org/", body)
  941. req.TransferEncoding = []string{
  942. "encoding1",
  943. }
  944. clonedReq := req.Clone(context.Background())
  945. // modify original after deep copy
  946. req.TransferEncoding[0] = "encoding2"
  947. if req.TransferEncoding[0] != "encoding2" {
  948. t.Error("expected req.TransferEncoding to be changed")
  949. }
  950. if clonedReq.TransferEncoding[0] != "encoding1" {
  951. t.Error("expected clonedReq.TransferEncoding to be unchanged")
  952. }
  953. }
  954. func TestNoPanicOnRoundTripWithBasicAuth_h1(t *testing.T) {
  955. testNoPanicWithBasicAuth(t, h1Mode)
  956. }
  957. func TestNoPanicOnRoundTripWithBasicAuth_h2(t *testing.T) {
  958. testNoPanicWithBasicAuth(t, h2Mode)
  959. }
  960. // Issue 34878: verify we don't panic when including basic auth (Go 1.13 regression)
  961. func testNoPanicWithBasicAuth(t *testing.T, h2 bool) {
  962. defer afterTest(t)
  963. cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {}))
  964. defer cst.close()
  965. u, err := url.Parse(cst.ts.URL)
  966. if err != nil {
  967. t.Fatal(err)
  968. }
  969. u.User = url.UserPassword("foo", "bar")
  970. req := &Request{
  971. URL: u,
  972. Method: "GET",
  973. }
  974. if _, err := cst.c.Do(req); err != nil {
  975. t.Fatalf("Unexpected error: %v", err)
  976. }
  977. }
  978. // verify that NewRequest sets Request.GetBody and that it works
  979. func TestNewRequestGetBody(t *testing.T) {
  980. tests := []struct {
  981. r io.Reader
  982. }{
  983. {r: strings.NewReader("hello")},
  984. {r: bytes.NewReader([]byte("hello"))},
  985. {r: bytes.NewBuffer([]byte("hello"))},
  986. }
  987. for i, tt := range tests {
  988. req, err := NewRequest("POST", "http://foo.tld/", tt.r)
  989. if err != nil {
  990. t.Errorf("test[%d]: %v", i, err)
  991. continue
  992. }
  993. if req.Body == nil {
  994. t.Errorf("test[%d]: Body = nil", i)
  995. continue
  996. }
  997. if req.GetBody == nil {
  998. t.Errorf("test[%d]: GetBody = nil", i)
  999. continue
  1000. }
  1001. slurp1, err := io.ReadAll(req.Body)
  1002. if err != nil {
  1003. t.Errorf("test[%d]: ReadAll(Body) = %v", i, err)
  1004. }
  1005. newBody, err := req.GetBody()
  1006. if err != nil {
  1007. t.Errorf("test[%d]: GetBody = %v", i, err)
  1008. }
  1009. slurp2, err := io.ReadAll(newBody)
  1010. if err != nil {
  1011. t.Errorf("test[%d]: ReadAll(GetBody()) = %v", i, err)
  1012. }
  1013. if string(slurp1) != string(slurp2) {
  1014. t.Errorf("test[%d]: Body %q != GetBody %q", i, slurp1, slurp2)
  1015. }
  1016. }
  1017. }
  1018. func testMissingFile(t *testing.T, req *Request) {
  1019. f, fh, err := req.FormFile("missing")
  1020. if f != nil {
  1021. t.Errorf("FormFile file = %v, want nil", f)
  1022. }
  1023. if fh != nil {
  1024. t.Errorf("FormFile file header = %q, want nil", fh)
  1025. }
  1026. if err != ErrMissingFile {
  1027. t.Errorf("FormFile err = %q, want ErrMissingFile", err)
  1028. }
  1029. }
  1030. func newTestMultipartRequest(t *testing.T) *Request {
  1031. b := strings.NewReader(strings.ReplaceAll(message, "\n", "\r\n"))
  1032. req, err := NewRequest("POST", "/", b)
  1033. if err != nil {
  1034. t.Fatal("NewRequest:", err)
  1035. }
  1036. ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
  1037. req.Header.Set("Content-type", ctype)
  1038. return req
  1039. }
  1040. func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
  1041. if g, e := req.FormValue("texta"), textaValue; g != e {
  1042. t.Errorf("texta value = %q, want %q", g, e)
  1043. }
  1044. if g, e := req.FormValue("textb"), textbValue; g != e {
  1045. t.Errorf("textb value = %q, want %q", g, e)
  1046. }
  1047. if g := req.FormValue("missing"); g != "" {
  1048. t.Errorf("missing value = %q, want empty string", g)
  1049. }
  1050. assertMem := func(n string, fd multipart.File) {
  1051. if _, ok := fd.(*os.File); ok {
  1052. t.Error(n, " is *os.File, should not be")
  1053. }
  1054. }
  1055. fda := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
  1056. defer fda.Close()
  1057. assertMem("filea", fda)
  1058. fdb := testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
  1059. defer fdb.Close()
  1060. if allMem {
  1061. assertMem("fileb", fdb)
  1062. } else {
  1063. if _, ok := fdb.(*os.File); !ok {
  1064. t.Errorf("fileb has unexpected underlying type %T", fdb)
  1065. }
  1066. }
  1067. testMissingFile(t, req)
  1068. }
  1069. func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
  1070. f, fh, err := req.FormFile(key)
  1071. if err != nil {
  1072. t.Fatalf("FormFile(%q): %q", key, err)
  1073. }
  1074. if fh.Filename != expectFilename {
  1075. t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
  1076. }
  1077. var b bytes.Buffer
  1078. _, err = io.Copy(&b, f)
  1079. if err != nil {
  1080. t.Fatal("copying contents:", err)
  1081. }
  1082. if g := b.String(); g != expectContent {
  1083. t.Errorf("contents = %q, want %q", g, expectContent)
  1084. }
  1085. return f
  1086. }
  1087. const (
  1088. fileaContents = "This is a test file."
  1089. filebContents = "Another test file."
  1090. textaValue = "foo"
  1091. textbValue = "bar"
  1092. boundary = `MyBoundary`
  1093. )
  1094. const message = `
  1095. --MyBoundary
  1096. Content-Disposition: form-data; name="filea"; filename="filea.txt"
  1097. Content-Type: text/plain
  1098. ` + fileaContents + `
  1099. --MyBoundary
  1100. Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
  1101. Content-Type: text/plain
  1102. ` + filebContents + `
  1103. --MyBoundary
  1104. Content-Disposition: form-data; name="texta"
  1105. ` + textaValue + `
  1106. --MyBoundary
  1107. Content-Disposition: form-data; name="textb"
  1108. ` + textbValue + `
  1109. --MyBoundary--
  1110. `
  1111. func benchmarkReadRequest(b *testing.B, request string) {
  1112. request = request + "\n" // final \n
  1113. request = strings.ReplaceAll(request, "\n", "\r\n") // expand \n to \r\n
  1114. b.SetBytes(int64(len(request)))
  1115. r := bufio.NewReader(&infiniteReader{buf: []byte(request)})
  1116. b.ReportAllocs()
  1117. b.ResetTimer()
  1118. for i := 0; i < b.N; i++ {
  1119. _, err := ReadRequest(r)
  1120. if err != nil {
  1121. b.Fatalf("failed to read request: %v", err)
  1122. }
  1123. }
  1124. }
  1125. // infiniteReader satisfies Read requests as if the contents of buf
  1126. // loop indefinitely.
  1127. type infiniteReader struct {
  1128. buf []byte
  1129. offset int
  1130. }
  1131. func (r *infiniteReader) Read(b []byte) (int, error) {
  1132. n := copy(b, r.buf[r.offset:])
  1133. r.offset = (r.offset + n) % len(r.buf)
  1134. return n, nil
  1135. }
  1136. func BenchmarkReadRequestChrome(b *testing.B) {
  1137. // https://github.com/felixge/node-http-perf/blob/master/fixtures/get.http
  1138. benchmarkReadRequest(b, `GET / HTTP/1.1
  1139. Host: localhost:8080
  1140. Connection: keep-alive
  1141. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  1142. User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
  1143. Accept-Encoding: gzip,deflate,sdch
  1144. Accept-Language: en-US,en;q=0.8
  1145. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
  1146. Cookie: __utma=1.1978842379.1323102373.1323102373.1323102373.1; EPi:NumberOfVisits=1,2012-02-28T13:42:18; CrmSession=5b707226b9563e1bc69084d07a107c98; plushContainerWidth=100%25; plushNoTopMenu=0; hudson_auto_refresh=false
  1147. `)
  1148. }
  1149. func BenchmarkReadRequestCurl(b *testing.B) {
  1150. // curl http://localhost:8080/
  1151. benchmarkReadRequest(b, `GET / HTTP/1.1
  1152. User-Agent: curl/7.27.0
  1153. Host: localhost:8080
  1154. Accept: */*
  1155. `)
  1156. }
  1157. func BenchmarkReadRequestApachebench(b *testing.B) {
  1158. // ab -n 1 -c 1 http://localhost:8080/
  1159. benchmarkReadRequest(b, `GET / HTTP/1.0
  1160. Host: localhost:8080
  1161. User-Agent: ApacheBench/2.3
  1162. Accept: */*
  1163. `)
  1164. }
  1165. func BenchmarkReadRequestSiege(b *testing.B) {
  1166. // siege -r 1 -c 1 http://localhost:8080/
  1167. benchmarkReadRequest(b, `GET / HTTP/1.1
  1168. Host: localhost:8080
  1169. Accept: */*
  1170. Accept-Encoding: gzip
  1171. User-Agent: JoeDog/1.00 [en] (X11; I; Siege 2.70)
  1172. Connection: keep-alive
  1173. `)
  1174. }
  1175. func BenchmarkReadRequestWrk(b *testing.B) {
  1176. // wrk -t 1 -r 1 -c 1 http://localhost:8080/
  1177. benchmarkReadRequest(b, `GET / HTTP/1.1
  1178. Host: localhost:8080
  1179. `)
  1180. }
  1181. const (
  1182. withTLS = true
  1183. noTLS = false
  1184. )
  1185. func BenchmarkFileAndServer_1KB(b *testing.B) {
  1186. benchmarkFileAndServer(b, 1<<10)
  1187. }
  1188. func BenchmarkFileAndServer_16MB(b *testing.B) {
  1189. benchmarkFileAndServer(b, 1<<24)
  1190. }
  1191. func BenchmarkFileAndServer_64MB(b *testing.B) {
  1192. benchmarkFileAndServer(b, 1<<26)
  1193. }
  1194. func benchmarkFileAndServer(b *testing.B, n int64) {
  1195. f, err := os.CreateTemp(os.TempDir(), "go-bench-http-file-and-server")
  1196. if err != nil {
  1197. b.Fatalf("Failed to create temp file: %v", err)
  1198. }
  1199. defer func() {
  1200. f.Close()
  1201. os.RemoveAll(f.Name())
  1202. }()
  1203. if _, err := io.CopyN(f, rand.Reader, n); err != nil {
  1204. b.Fatalf("Failed to copy %d bytes: %v", n, err)
  1205. }
  1206. b.Run("NoTLS", func(b *testing.B) {
  1207. runFileAndServerBenchmarks(b, noTLS, f, n)
  1208. })
  1209. b.Run("TLS", func(b *testing.B) {
  1210. runFileAndServerBenchmarks(b, withTLS, f, n)
  1211. })
  1212. }
  1213. func runFileAndServerBenchmarks(b *testing.B, tlsOption bool, f *os.File, n int64) {
  1214. handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
  1215. defer req.Body.Close()
  1216. nc, err := io.Copy(io.Discard, req.Body)
  1217. if err != nil {
  1218. panic(err)
  1219. }
  1220. if nc != n {
  1221. panic(fmt.Errorf("Copied %d Wanted %d bytes", nc, n))
  1222. }
  1223. })
  1224. var cst *httptest.Server
  1225. if tlsOption == withTLS {
  1226. cst = httptest.NewTLSServer(handler)
  1227. } else {
  1228. cst = httptest.NewServer(handler)
  1229. }
  1230. defer cst.Close()
  1231. b.ResetTimer()
  1232. for i := 0; i < b.N; i++ {
  1233. // Perform some setup.
  1234. b.StopTimer()
  1235. if _, err := f.Seek(0, 0); err != nil {
  1236. b.Fatalf("Failed to seek back to file: %v", err)
  1237. }
  1238. b.StartTimer()
  1239. req, err := NewRequest("PUT", cst.URL, io.NopCloser(f))
  1240. if err != nil {
  1241. b.Fatal(err)
  1242. }
  1243. req.ContentLength = n
  1244. // Prevent mime sniffing by setting the Content-Type.
  1245. req.Header.Set("Content-Type", "application/octet-stream")
  1246. res, err := cst.Client().Do(req)
  1247. if err != nil {
  1248. b.Fatalf("Failed to make request to backend: %v", err)
  1249. }
  1250. res.Body.Close()
  1251. b.SetBytes(n)
  1252. }
  1253. }