http2_test.go 8.7 KB

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