http2_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. type serverTester struct {
  29. cc net.Conn // client conn
  30. t *testing.T
  31. ts *httptest.Server
  32. fr *Framer
  33. }
  34. func newServerTester(t *testing.T, handler http.HandlerFunc) *serverTester {
  35. ts := httptest.NewUnstartedServer(handler)
  36. ConfigureServer(ts.Config, &Server{})
  37. ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
  38. ts.StartTLS()
  39. t.Logf("Running test server at: %s", ts.URL)
  40. cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), &tls.Config{
  41. InsecureSkipVerify: true,
  42. NextProtos: []string{npnProto},
  43. })
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. log.SetOutput(twriter{t})
  48. return &serverTester{
  49. t: t,
  50. ts: ts,
  51. cc: cc,
  52. fr: NewFramer(cc, cc),
  53. }
  54. }
  55. func (st *serverTester) Close() {
  56. st.ts.Close()
  57. st.cc.Close()
  58. log.SetOutput(os.Stderr)
  59. }
  60. func (st *serverTester) writePreface() {
  61. n, err := st.cc.Write(clientPreface)
  62. if err != nil {
  63. st.t.Fatalf("Error writing client preface: %v", err)
  64. }
  65. if n != len(clientPreface) {
  66. st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(clientPreface))
  67. }
  68. }
  69. func (st *serverTester) writeInitialSettings() {
  70. if err := st.fr.WriteSettings(); err != nil {
  71. st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err)
  72. }
  73. }
  74. func (st *serverTester) writeSettingsAck() {
  75. if err := st.fr.WriteSettingsAck(); err != nil {
  76. st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err)
  77. }
  78. }
  79. func (st *serverTester) writeHeaders(p HeadersFrameParam) {
  80. if err := st.fr.WriteHeaders(p); err != nil {
  81. st.t.Fatalf("Error writing HEADERS: %v", err)
  82. }
  83. }
  84. func (st *serverTester) wantSettings() *SettingsFrame {
  85. f, err := st.fr.ReadFrame()
  86. if err != nil {
  87. st.t.Fatal(err)
  88. }
  89. sf, ok := f.(*SettingsFrame)
  90. if !ok {
  91. st.t.Fatalf("got a %T; want *SettingsFrame", f)
  92. }
  93. return sf
  94. }
  95. func (st *serverTester) wantSettingsAck() {
  96. f, err := st.fr.ReadFrame()
  97. if err != nil {
  98. st.t.Fatal(err)
  99. }
  100. sf, ok := f.(*SettingsFrame)
  101. if !ok {
  102. st.t.Fatalf("Wanting a settings ACK, received a %T", f)
  103. }
  104. if !sf.Header().Flags.Has(FlagSettingsAck) {
  105. st.t.Fatal("Settings Frame didn't have ACK set")
  106. }
  107. }
  108. func TestServer(t *testing.T) {
  109. gotReq := make(chan bool, 1)
  110. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  111. w.Header().Set("Foo", "Bar")
  112. t.Logf("GOT REQUEST %#v", r)
  113. gotReq <- true
  114. })
  115. defer st.Close()
  116. covers("3.5", `
  117. The server connection preface consists of a potentially empty
  118. SETTINGS frame ([SETTINGS]) that MUST be the first frame the
  119. server sends in the HTTP/2 connection.
  120. `)
  121. st.writePreface()
  122. st.writeInitialSettings()
  123. st.wantSettings().ForeachSetting(func(s Setting) {
  124. t.Logf("Server sent setting %v = %v", s.ID, s.Val)
  125. })
  126. st.writeSettingsAck()
  127. st.wantSettingsAck()
  128. st.writeHeaders(HeadersFrameParam{
  129. StreamID: 1, // clients send odd numbers
  130. BlockFragment: encodeHeader(t,
  131. ":method", "GET",
  132. ":path", "/",
  133. ":scheme", "https",
  134. ),
  135. EndStream: true, // no DATA frames
  136. EndHeaders: true,
  137. })
  138. select {
  139. case <-gotReq:
  140. case <-time.After(2 * time.Second):
  141. t.Error("timeout waiting for request")
  142. }
  143. }
  144. func TestServer_Request_Get(t *testing.T) {
  145. testServerRequest(t, func(st *serverTester) {
  146. st.writeHeaders(HeadersFrameParam{
  147. StreamID: 1, // clients send odd numbers
  148. BlockFragment: encodeHeader(t,
  149. ":method", "GET",
  150. ":path", "/",
  151. ":scheme", "https",
  152. "foo-bar", "some-value",
  153. ),
  154. EndStream: true, // no DATA frames
  155. EndHeaders: true,
  156. })
  157. }, func(r *http.Request) {
  158. t.Logf("GOT %#v", r)
  159. if r.Method != "GET" {
  160. t.Errorf("Method = %q; want GET", r.Method)
  161. }
  162. if r.ContentLength != 0 {
  163. t.Errorf("ContentLength = %v; want 0", r.ContentLength)
  164. }
  165. if r.Close {
  166. t.Error("Close = true; want false")
  167. }
  168. if !strings.Contains(r.RemoteAddr, ":") {
  169. t.Errorf("RemoteAddr = %q; want something with a colon", r.RemoteAddr)
  170. }
  171. if r.Proto != "HTTP/2.0" || r.ProtoMajor != 2 || r.ProtoMinor != 0 {
  172. t.Errorf("Proto = %q Major=%v,Minor=%v; want HTTP/2.0", r.Proto, r.ProtoMajor, r.ProtoMinor)
  173. }
  174. wantHeader := http.Header{
  175. "Foo-Bar": []string{"some-value"},
  176. }
  177. if !reflect.DeepEqual(r.Header, wantHeader) {
  178. t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
  179. }
  180. if n, err := r.Body.Read([]byte(" ")); err != io.EOF || n != 0 {
  181. t.Errorf("Read = %d, %v; want 0, EOF", n, err)
  182. }
  183. })
  184. }
  185. // Using a Host header, instead of :authority
  186. func TestServer_Request_Get_Host(t *testing.T) {
  187. const host = "example.com"
  188. testServerRequest(t, func(st *serverTester) {
  189. st.writeHeaders(HeadersFrameParam{
  190. StreamID: 1, // clients send odd numbers
  191. BlockFragment: encodeHeader(t,
  192. ":method", "GET",
  193. ":path", "/",
  194. ":scheme", "https",
  195. "host", host,
  196. ),
  197. EndStream: true,
  198. EndHeaders: true,
  199. })
  200. }, func(r *http.Request) {
  201. if r.Host != host {
  202. t.Errorf("Host = %q; want %q", r.Host, host)
  203. }
  204. })
  205. }
  206. // Using an :authority pseudo-header, instead of Host
  207. func TestServer_Request_Get_Authority(t *testing.T) {
  208. const host = "example.com"
  209. testServerRequest(t, func(st *serverTester) {
  210. st.writeHeaders(HeadersFrameParam{
  211. StreamID: 1, // clients send odd numbers
  212. BlockFragment: encodeHeader(t,
  213. ":method", "GET",
  214. ":path", "/",
  215. ":scheme", "https",
  216. ":authority", host,
  217. ),
  218. EndStream: true,
  219. EndHeaders: true,
  220. })
  221. }, func(r *http.Request) {
  222. if r.Host != host {
  223. t.Errorf("Host = %q; want %q", r.Host, host)
  224. }
  225. })
  226. }
  227. func TestServer_Request_WithContinuation(t *testing.T) {
  228. wantHeader := http.Header{
  229. "Foo-One": []string{"value-one"},
  230. "Foo-Two": []string{"value-two"},
  231. "Foo-Three": []string{"value-three"},
  232. }
  233. testServerRequest(t, func(st *serverTester) {
  234. fullHeaders := encodeHeader(t,
  235. ":method", "GET",
  236. ":path", "/",
  237. ":scheme", "https",
  238. "foo-one", "value-one",
  239. "foo-two", "value-two",
  240. "foo-three", "value-three",
  241. )
  242. remain := fullHeaders
  243. chunks := 0
  244. for len(remain) > 0 {
  245. const maxChunkSize = 5
  246. chunk := remain
  247. if len(chunk) > maxChunkSize {
  248. chunk = chunk[:maxChunkSize]
  249. }
  250. remain = remain[len(chunk):]
  251. if chunks == 0 {
  252. st.writeHeaders(HeadersFrameParam{
  253. StreamID: 1, // clients send odd numbers
  254. BlockFragment: chunk,
  255. EndStream: true, // no DATA frames
  256. EndHeaders: false, // we'll have continuation frames
  257. })
  258. } else {
  259. err := st.fr.WriteContinuation(1, len(remain) == 0, chunk)
  260. if err != nil {
  261. t.Fatal(err)
  262. }
  263. }
  264. chunks++
  265. }
  266. if chunks < 2 {
  267. t.Fatal("too few chunks")
  268. }
  269. }, func(r *http.Request) {
  270. if !reflect.DeepEqual(r.Header, wantHeader) {
  271. t.Errorf("Header = %#v; want %#v", r.Header, wantHeader)
  272. }
  273. })
  274. }
  275. // testServerRequest sets up an idle HTTP/2 connection and lets you
  276. // write a single request with writeReq, and then verify that the
  277. // *http.Request is built correctly in checkReq.
  278. func testServerRequest(t *testing.T, writeReq func(*serverTester), checkReq func(*http.Request)) {
  279. gotReq := make(chan bool, 1)
  280. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  281. if r.Body == nil {
  282. t.Fatal("nil Body")
  283. }
  284. checkReq(r)
  285. gotReq <- true
  286. })
  287. defer st.Close()
  288. st.writePreface()
  289. st.writeInitialSettings()
  290. st.wantSettings()
  291. st.writeSettingsAck()
  292. st.wantSettingsAck()
  293. writeReq(st)
  294. select {
  295. case <-gotReq:
  296. case <-time.After(2 * time.Second):
  297. t.Error("timeout waiting for request")
  298. }
  299. }
  300. func TestServerWithCurl(t *testing.T) {
  301. requireCurl(t)
  302. ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  303. // TODO: add a bunch of different tests with different
  304. // behavior, as a function of r or a table.
  305. // -- with request body, without.
  306. // -- no interaction with w.
  307. // -- panic
  308. // -- modify Header only, but no writes or writeheader (this test)
  309. // -- WriteHeader only
  310. // -- Write only
  311. // -- WriteString
  312. // -- both
  313. // -- huge headers over a frame size so we get continuation headers.
  314. // Look at net/http's Server tests for inspiration.
  315. w.Header().Set("Foo", "Bar")
  316. }))
  317. ConfigureServer(ts.Config, &Server{})
  318. ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
  319. ts.StartTLS()
  320. defer ts.Close()
  321. var gotConn int32
  322. testHookOnConn = func() { atomic.StoreInt32(&gotConn, 1) }
  323. t.Logf("Running test server for curl to hit at: %s", ts.URL)
  324. container := curl(t, "--silent", "--http2", "--insecure", "-v", ts.URL)
  325. defer kill(container)
  326. resc := make(chan interface{}, 1)
  327. go func() {
  328. res, err := dockerLogs(container)
  329. if err != nil {
  330. resc <- err
  331. } else {
  332. resc <- res
  333. }
  334. }()
  335. select {
  336. case res := <-resc:
  337. if err, ok := res.(error); ok {
  338. t.Fatal(err)
  339. }
  340. if !strings.Contains(string(res.([]byte)), "< foo:Bar") {
  341. t.Errorf("didn't see foo:Bar header")
  342. t.Logf("Got: %s", res)
  343. }
  344. case <-time.After(3 * time.Second):
  345. t.Errorf("timeout waiting for curl")
  346. }
  347. if atomic.LoadInt32(&gotConn) == 0 {
  348. t.Error("never saw an http2 connection")
  349. }
  350. }
  351. func dockerLogs(container string) ([]byte, error) {
  352. out, err := exec.Command("docker", "wait", container).CombinedOutput()
  353. if err != nil {
  354. return out, err
  355. }
  356. exitStatus, err := strconv.Atoi(strings.TrimSpace(string(out)))
  357. if err != nil {
  358. return out, errors.New("unexpected exit status from docker wait")
  359. }
  360. out, err = exec.Command("docker", "logs", container).CombinedOutput()
  361. exec.Command("docker", "rm", container).Run()
  362. if err == nil && exitStatus != 0 {
  363. err = fmt.Errorf("exit status %d", exitStatus)
  364. }
  365. return out, err
  366. }
  367. func kill(container string) {
  368. exec.Command("docker", "kill", container).Run()
  369. exec.Command("docker", "rm", container).Run()
  370. }
  371. // Verify that curl has http2.
  372. func requireCurl(t *testing.T) {
  373. out, err := dockerLogs(curl(t, "--version"))
  374. if err != nil {
  375. t.Skipf("failed to determine curl features; skipping test")
  376. }
  377. if !strings.Contains(string(out), "HTTP2") {
  378. t.Skip("curl doesn't support HTTP2; skipping test")
  379. }
  380. }
  381. func curl(t *testing.T, args ...string) (container string) {
  382. out, err := exec.Command("docker", append([]string{"run", "-d", "--net=host", "gohttp2/curl"}, args...)...).CombinedOutput()
  383. if err != nil {
  384. t.Skipf("Failed to run curl in docker: %v, %s", err, out)
  385. }
  386. return strings.TrimSpace(string(out))
  387. }
  388. type twriter struct {
  389. t testing.TB
  390. }
  391. func (w twriter) Write(p []byte) (n int, err error) {
  392. w.t.Logf("%s", p)
  393. return len(p), nil
  394. }
  395. func encodeHeader(t *testing.T, kv ...string) []byte {
  396. if len(kv)%2 == 1 {
  397. panic("odd number of kv args")
  398. }
  399. var buf bytes.Buffer
  400. enc := hpack.NewEncoder(&buf)
  401. for len(kv) > 0 {
  402. k, v := kv[0], kv[1]
  403. kv = kv[2:]
  404. if err := enc.WriteField(hpack.HeaderField{Name: k, Value: v}); err != nil {
  405. t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
  406. }
  407. }
  408. return buf.Bytes()
  409. }