http2_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. // Copyright 2014 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. // See https://code.google.com/p/go/source/browse/CONTRIBUTORS
  5. // Licensed under the same terms as Go itself:
  6. // https://code.google.com/p/go/source/browse/LICENSE
  7. package http2
  8. import (
  9. "bytes"
  10. "crypto/tls"
  11. "errors"
  12. "fmt"
  13. "io"
  14. "log"
  15. "net"
  16. "net/http"
  17. "net/http/httptest"
  18. "os"
  19. "os/exec"
  20. "reflect"
  21. "strconv"
  22. "strings"
  23. "sync/atomic"
  24. "testing"
  25. "time"
  26. "github.com/bradfitz/http2/hpack"
  27. )
  28. func init() {
  29. VerboseLogs = true
  30. DebugGoroutines = true
  31. }
  32. type serverTester struct {
  33. cc net.Conn // client conn
  34. t *testing.T
  35. ts *httptest.Server
  36. fr *Framer
  37. logBuf *bytes.Buffer
  38. }
  39. func newServerTester(t *testing.T, handler http.HandlerFunc) *serverTester {
  40. logBuf := new(bytes.Buffer)
  41. ts := httptest.NewUnstartedServer(handler)
  42. ConfigureServer(ts.Config, &Server{})
  43. ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
  44. ts.Config.ErrorLog = log.New(io.MultiWriter(twriter{t: t}, logBuf), "", log.LstdFlags)
  45. ts.StartTLS()
  46. t.Logf("Running test server at: %s", ts.URL)
  47. cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), &tls.Config{
  48. InsecureSkipVerify: true,
  49. NextProtos: []string{npnProto},
  50. })
  51. if err != nil {
  52. t.Fatal(err)
  53. }
  54. log.SetOutput(twriter{t})
  55. return &serverTester{
  56. t: t,
  57. ts: ts,
  58. cc: cc,
  59. fr: NewFramer(cc, cc),
  60. logBuf: logBuf,
  61. }
  62. }
  63. func (st *serverTester) Close() {
  64. st.ts.Close()
  65. st.cc.Close()
  66. log.SetOutput(os.Stderr)
  67. }
  68. // greet initiates the client's HTTP/2 connection into a state where
  69. // frames may be sent.
  70. func (st *serverTester) greet() {
  71. st.writePreface()
  72. st.writeInitialSettings()
  73. st.wantSettings()
  74. st.writeSettingsAck()
  75. st.wantSettingsAck()
  76. }
  77. func (st *serverTester) writePreface() {
  78. n, err := st.cc.Write(clientPreface)
  79. if err != nil {
  80. st.t.Fatalf("Error writing client preface: %v", err)
  81. }
  82. if n != len(clientPreface) {
  83. st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(clientPreface))
  84. }
  85. }
  86. func (st *serverTester) writeInitialSettings() {
  87. if err := st.fr.WriteSettings(); err != nil {
  88. st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err)
  89. }
  90. }
  91. func (st *serverTester) writeSettingsAck() {
  92. if err := st.fr.WriteSettingsAck(); err != nil {
  93. st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err)
  94. }
  95. }
  96. func (st *serverTester) writeHeaders(p HeadersFrameParam) {
  97. if err := st.fr.WriteHeaders(p); err != nil {
  98. st.t.Fatalf("Error writing HEADERS: %v", err)
  99. }
  100. }
  101. // bodylessReq1 writes a HEADERS frames with StreamID 1 and EndStream and EndHeaders set.
  102. func (st *serverTester) bodylessReq1(headers ...string) {
  103. st.writeHeaders(HeadersFrameParam{
  104. StreamID: 1, // clients send odd numbers
  105. BlockFragment: encodeHeader(st.t, headers...),
  106. EndStream: true,
  107. EndHeaders: true,
  108. })
  109. }
  110. func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) {
  111. if err := st.fr.WriteData(streamID, endStream, data); err != nil {
  112. st.t.Fatalf("Error writing DATA: %v", err)
  113. }
  114. }
  115. func (st *serverTester) wantSettings() *SettingsFrame {
  116. f, err := st.fr.ReadFrame()
  117. if err != nil {
  118. st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err)
  119. }
  120. sf, ok := f.(*SettingsFrame)
  121. if !ok {
  122. st.t.Fatalf("got a %T; want *SettingsFrame", f)
  123. }
  124. return sf
  125. }
  126. func (st *serverTester) wantRSTStream(streamID uint32, errCode ErrCode) {
  127. f, err := st.fr.ReadFrame()
  128. if err != nil {
  129. st.t.Fatalf("Error while expecting an RSTStream frame: %v", err)
  130. }
  131. rs, ok := f.(*RSTStreamFrame)
  132. if !ok {
  133. st.t.Fatalf("got a %T; want *RSTStream", f)
  134. }
  135. if rs.FrameHeader.StreamID != streamID {
  136. st.t.Fatalf("RSTStream StreamID = %d; want %d", rs.FrameHeader.StreamID, streamID)
  137. }
  138. if rs.ErrCode != uint32(errCode) {
  139. st.t.Fatalf("RSTStream ErrCode = %d (%s); want %d (%s)", rs.ErrCode, rs.ErrCode, errCode, errCode)
  140. }
  141. }
  142. func (st *serverTester) wantSettingsAck() {
  143. f, err := st.fr.ReadFrame()
  144. if err != nil {
  145. st.t.Fatal(err)
  146. }
  147. sf, ok := f.(*SettingsFrame)
  148. if !ok {
  149. st.t.Fatalf("Wanting a settings ACK, received a %T", f)
  150. }
  151. if !sf.Header().Flags.Has(FlagSettingsAck) {
  152. st.t.Fatal("Settings Frame didn't have ACK set")
  153. }
  154. }
  155. func TestServer(t *testing.T) {
  156. gotReq := make(chan bool, 1)
  157. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  158. w.Header().Set("Foo", "Bar")
  159. t.Logf("GOT REQUEST %#v", r)
  160. gotReq <- true
  161. })
  162. defer st.Close()
  163. covers("3.5", `
  164. The server connection preface consists of a potentially empty
  165. SETTINGS frame ([SETTINGS]) that MUST be the first frame the
  166. server sends in the HTTP/2 connection.
  167. `)
  168. st.writePreface()
  169. st.writeInitialSettings()
  170. st.wantSettings().ForeachSetting(func(s Setting) {
  171. t.Logf("Server sent setting %v = %v", s.ID, s.Val)
  172. })
  173. st.writeSettingsAck()
  174. st.wantSettingsAck()
  175. st.writeHeaders(HeadersFrameParam{
  176. StreamID: 1, // clients send odd numbers
  177. BlockFragment: encodeHeader(t),
  178. EndStream: true, // no DATA frames
  179. EndHeaders: true,
  180. })
  181. select {
  182. case <-gotReq:
  183. case <-time.After(2 * time.Second):
  184. t.Error("timeout waiting for request")
  185. }
  186. }
  187. func TestServer_Request_Get(t *testing.T) {
  188. testServerRequest(t, func(st *serverTester) {
  189. st.writeHeaders(HeadersFrameParam{
  190. StreamID: 1, // clients send odd numbers
  191. BlockFragment: encodeHeader(t, "foo-bar", "some-value"),
  192. EndStream: true, // no DATA frames
  193. EndHeaders: true,
  194. })
  195. }, func(r *http.Request) {
  196. if r.Method != "GET" {
  197. t.Errorf("Method = %q; want GET", r.Method)
  198. }
  199. if r.ContentLength != 0 {
  200. t.Errorf("ContentLength = %v; want 0", r.ContentLength)
  201. }
  202. if r.Close {
  203. t.Error("Close = true; want false")
  204. }
  205. if !strings.Contains(r.RemoteAddr, ":") {
  206. t.Errorf("RemoteAddr = %q; want something with a colon", r.RemoteAddr)
  207. }
  208. if r.Proto != "HTTP/2.0" || r.ProtoMajor != 2 || r.ProtoMinor != 0 {
  209. t.Errorf("Proto = %q Major=%v,Minor=%v; want HTTP/2.0", r.Proto, r.ProtoMajor, r.ProtoMinor)
  210. }
  211. wantHeader := http.Header{
  212. "Foo-Bar": []string{"some-value"},
  213. }
  214. if !reflect.DeepEqual(r.Header, wantHeader) {
  215. t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
  216. }
  217. if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
  218. t.Errorf("Read = %d, %v; want 0, EOF", n, err)
  219. }
  220. })
  221. }
  222. // TODO: add a test with EndStream=true on the HEADERS but setting a
  223. // Content-Length anyway. Should we just omit it and force it to
  224. // zero?
  225. func TestServer_Request_Post_NoContentLength_EndStream(t *testing.T) {
  226. testServerRequest(t, func(st *serverTester) {
  227. st.writeHeaders(HeadersFrameParam{
  228. StreamID: 1, // clients send odd numbers
  229. BlockFragment: encodeHeader(t, ":method", "POST"),
  230. EndStream: true,
  231. EndHeaders: true,
  232. })
  233. }, func(r *http.Request) {
  234. if r.Method != "POST" {
  235. t.Errorf("Method = %q; want POST", r.Method)
  236. }
  237. if r.ContentLength != 0 {
  238. t.Errorf("ContentLength = %v; want 0", r.ContentLength)
  239. }
  240. if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
  241. t.Errorf("Read = %d, %v; want 0, EOF", n, err)
  242. }
  243. })
  244. }
  245. func TestServer_Request_Post_Body(t *testing.T) {
  246. t.Skip("TODO: post bodies not yet implemented")
  247. testServerRequest(t, func(st *serverTester) {
  248. st.writeHeaders(HeadersFrameParam{
  249. StreamID: 1, // clients send odd numbers
  250. BlockFragment: encodeHeader(t, ":method", "POST"),
  251. EndStream: false, // migth be DATA frames
  252. EndHeaders: true,
  253. })
  254. st.writeData(1, true, nil)
  255. }, func(r *http.Request) {
  256. if r.Method != "POST" {
  257. t.Errorf("Method = %q; want POST", r.Method)
  258. }
  259. if r.ContentLength != -1 {
  260. t.Errorf("ContentLength = %v; want -1", r.ContentLength)
  261. }
  262. if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
  263. t.Errorf("Read = %d, %v; want 0, EOF", n, err)
  264. }
  265. })
  266. }
  267. // Using a Host header, instead of :authority
  268. func TestServer_Request_Get_Host(t *testing.T) {
  269. const host = "example.com"
  270. testServerRequest(t, func(st *serverTester) {
  271. st.writeHeaders(HeadersFrameParam{
  272. StreamID: 1, // clients send odd numbers
  273. BlockFragment: encodeHeader(t, "host", host),
  274. EndStream: true,
  275. EndHeaders: true,
  276. })
  277. }, func(r *http.Request) {
  278. if r.Host != host {
  279. t.Errorf("Host = %q; want %q", r.Host, host)
  280. }
  281. })
  282. }
  283. // Using an :authority pseudo-header, instead of Host
  284. func TestServer_Request_Get_Authority(t *testing.T) {
  285. const host = "example.com"
  286. testServerRequest(t, func(st *serverTester) {
  287. st.writeHeaders(HeadersFrameParam{
  288. StreamID: 1, // clients send odd numbers
  289. BlockFragment: encodeHeader(t, ":authority", host),
  290. EndStream: true,
  291. EndHeaders: true,
  292. })
  293. }, func(r *http.Request) {
  294. if r.Host != host {
  295. t.Errorf("Host = %q; want %q", r.Host, host)
  296. }
  297. })
  298. }
  299. func TestServer_Request_WithContinuation(t *testing.T) {
  300. wantHeader := http.Header{
  301. "Foo-One": []string{"value-one"},
  302. "Foo-Two": []string{"value-two"},
  303. "Foo-Three": []string{"value-three"},
  304. }
  305. testServerRequest(t, func(st *serverTester) {
  306. fullHeaders := encodeHeader(t,
  307. "foo-one", "value-one",
  308. "foo-two", "value-two",
  309. "foo-three", "value-three",
  310. )
  311. remain := fullHeaders
  312. chunks := 0
  313. for len(remain) > 0 {
  314. const maxChunkSize = 5
  315. chunk := remain
  316. if len(chunk) > maxChunkSize {
  317. chunk = chunk[:maxChunkSize]
  318. }
  319. remain = remain[len(chunk):]
  320. if chunks == 0 {
  321. st.writeHeaders(HeadersFrameParam{
  322. StreamID: 1, // clients send odd numbers
  323. BlockFragment: chunk,
  324. EndStream: true, // no DATA frames
  325. EndHeaders: false, // we'll have continuation frames
  326. })
  327. } else {
  328. err := st.fr.WriteContinuation(1, len(remain) == 0, chunk)
  329. if err != nil {
  330. t.Fatal(err)
  331. }
  332. }
  333. chunks++
  334. }
  335. if chunks < 2 {
  336. t.Fatal("too few chunks")
  337. }
  338. }, func(r *http.Request) {
  339. if !reflect.DeepEqual(r.Header, wantHeader) {
  340. t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
  341. }
  342. })
  343. }
  344. // Concatenated cookie headers. ("8.1.2.5 Compressing the Cookie Header Field")
  345. func TestServer_Request_CookieConcat(t *testing.T) {
  346. const host = "example.com"
  347. testServerRequest(t, func(st *serverTester) {
  348. st.bodylessReq1(
  349. ":authority", host,
  350. "cookie", "a=b",
  351. "cookie", "c=d",
  352. "cookie", "e=f",
  353. )
  354. }, func(r *http.Request) {
  355. const want = "a=b; c=d; e=f"
  356. if got := r.Header.Get("Cookie"); got != want {
  357. t.Errorf("Cookie = %q; want %q", got, want)
  358. }
  359. })
  360. }
  361. func TestServer_Request_RejectCapitalHeader(t *testing.T) {
  362. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  363. t.Fatal("server request made it to handler; should've been rejected")
  364. })
  365. defer st.Close()
  366. st.greet()
  367. st.bodylessReq1("UPPER", "v")
  368. st.wantRSTStream(1, ErrCodeProtocol)
  369. }
  370. // TODO: test HEADERS w/o EndHeaders + another HEADERS (should get rejected)
  371. // TODO: test HEADERS w/ EndHeaders + a continuation HEADERS (should get rejected)
  372. // testServerRequest sets up an idle HTTP/2 connection and lets you
  373. // write a single request with writeReq, and then verify that the
  374. // *http.Request is built correctly in checkReq.
  375. func testServerRequest(t *testing.T, writeReq func(*serverTester), checkReq func(*http.Request)) {
  376. gotReq := make(chan bool, 1)
  377. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  378. if r.Body == nil {
  379. t.Fatal("nil Body")
  380. }
  381. checkReq(r)
  382. gotReq <- true
  383. })
  384. defer st.Close()
  385. st.greet()
  386. writeReq(st)
  387. select {
  388. case <-gotReq:
  389. case <-time.After(2 * time.Second):
  390. t.Error("timeout waiting for request")
  391. }
  392. }
  393. func TestServerWithCurl(t *testing.T) {
  394. requireCurl(t)
  395. ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  396. // TODO: add a bunch of different tests with different
  397. // behavior, as a function of r or a table.
  398. // -- with request body, without.
  399. // -- no interaction with w.
  400. // -- panic
  401. // -- modify Header only, but no writes or writeheader (this test)
  402. // -- WriteHeader only
  403. // -- Write only
  404. // -- WriteString
  405. // -- both
  406. // -- huge headers over a frame size so we get continuation headers.
  407. // Look at net/http's Server tests for inspiration.
  408. w.Header().Set("Foo", "Bar")
  409. }))
  410. ConfigureServer(ts.Config, &Server{})
  411. ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
  412. ts.StartTLS()
  413. defer ts.Close()
  414. var gotConn int32
  415. testHookOnConn = func() { atomic.StoreInt32(&gotConn, 1) }
  416. t.Logf("Running test server for curl to hit at: %s", ts.URL)
  417. container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL)
  418. defer kill(container)
  419. resc := make(chan interface{}, 1)
  420. go func() {
  421. res, err := dockerLogs(container)
  422. if err != nil {
  423. resc <- err
  424. } else {
  425. resc <- res
  426. }
  427. }()
  428. select {
  429. case res := <-resc:
  430. if err, ok := res.(error); ok {
  431. t.Fatal(err)
  432. }
  433. if !strings.Contains(string(res.([]byte)), "< foo:Bar") {
  434. t.Errorf("didn't see foo:Bar header")
  435. t.Logf("Got: %s", res)
  436. }
  437. case <-time.After(3 * time.Second):
  438. t.Errorf("timeout waiting for curl")
  439. }
  440. if atomic.LoadInt32(&gotConn) == 0 {
  441. t.Error("never saw an http2 connection")
  442. }
  443. }
  444. func dockerLogs(container string) ([]byte, error) {
  445. out, err := exec.Command("docker", "wait", container).CombinedOutput()
  446. if err != nil {
  447. return out, err
  448. }
  449. exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
  450. if err != nil {
  451. return out, errors.New("unexpected exit status from docker wait")
  452. }
  453. out, err = exec.Command("docker", "logs", container).CombinedOutput()
  454. exec.Command("docker", "rm", container).Run()
  455. if err == nil && exitStatus != 0 {
  456. err = fmt.Errorf("exit status %d", exitStatus)
  457. }
  458. return out, err
  459. }
  460. func kill(container string) {
  461. exec.Command("docker", "kill", container).Run()
  462. exec.Command("docker", "rm", container).Run()
  463. }
  464. // Verify that curl has http2.
  465. func requireCurl(t *testing.T) {
  466. out, err := dockerLogs(curl(t, "--version"))
  467. if err != nil {
  468. t.Skipf("failed to determine curl features; skipping test")
  469. }
  470. if !strings.Contains(string(out), "HTTP2") {
  471. t.Skip("curl doesn't support HTTP2; skipping test")
  472. }
  473. }
  474. func curl(t *testing.T, args ...string) (container string) {
  475. out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).CombinedOutput()
  476. if err != nil {
  477. t.Skipf("Failed to run curl in docker: %v, %s", err, out)
  478. }
  479. return strings.TrimSpace(string(out))
  480. }
  481. type twriter struct {
  482. t testing.TB
  483. }
  484. func (w twriter) Write(p []byte) (n int, err error) {
  485. w.t.Logf("%s", p)
  486. return len(p), nil
  487. }
  488. // encodeHeader encodes headers and returns their HPACK bytes. headers
  489. // must contain an even number of key/value pairs. There may be
  490. // multiple pairs for keys (e.g. "cookie"). The :method, :path, and
  491. // :scheme headers default to GET, / and https.
  492. func encodeHeader(t *testing.T, headers ...string) []byte {
  493. if len(headers)%2 == 1 {
  494. panic("odd number of kv args")
  495. }
  496. keys := []string{":method", ":path", ":scheme"}
  497. vals := map[string][]string{
  498. ":method": {"GET"},
  499. ":path": {"/"},
  500. ":scheme": {"https"},
  501. }
  502. for len(headers) > 0 {
  503. k, v := headers[0], headers[1]
  504. headers = headers[2:]
  505. if _, ok := vals[k]; !ok {
  506. keys = append(keys, k)
  507. }
  508. if strings.HasPrefix(k, ":") {
  509. vals[k] = []string{v}
  510. } else {
  511. vals[k] = append(vals[k], v)
  512. }
  513. }
  514. var buf bytes.Buffer
  515. enc := hpack.NewEncoder(&buf)
  516. for _, k := range keys {
  517. for _, v := range vals[k] {
  518. if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil {
  519. t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  520. }
  521. }
  522. }
  523. return buf.Bytes()
  524. }