transport_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright 2015 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 http2
  5. import (
  6. "crypto/tls"
  7. "flag"
  8. "io"
  9. "io/ioutil"
  10. "net"
  11. "net/http"
  12. "net/url"
  13. "os"
  14. "reflect"
  15. "strings"
  16. "sync"
  17. "testing"
  18. "time"
  19. )
  20. var (
  21. extNet = flag.Bool("extnet", false, "do external network tests")
  22. transportHost = flag.String("transporthost", "http2.golang.org", "hostname to use for TestTransport")
  23. insecure = flag.Bool("insecure", false, "insecure TLS dials")
  24. )
  25. var tlsConfigInsecure = &tls.Config{InsecureSkipVerify: true}
  26. func TestTransportExternal(t *testing.T) {
  27. if !*extNet {
  28. t.Skip("skipping external network test")
  29. }
  30. req, _ := http.NewRequest("GET", "https://"+*transportHost+"/", nil)
  31. rt := &Transport{TLSClientConfig: tlsConfigInsecure}
  32. res, err := rt.RoundTrip(req)
  33. if err != nil {
  34. t.Fatalf("%v", err)
  35. }
  36. res.Write(os.Stdout)
  37. }
  38. func TestTransport(t *testing.T) {
  39. const body = "sup"
  40. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  41. io.WriteString(w, body)
  42. }, optOnlyServer)
  43. defer st.Close()
  44. tr := &Transport{TLSClientConfig: tlsConfigInsecure}
  45. defer tr.CloseIdleConnections()
  46. req, err := http.NewRequest("GET", st.ts.URL, nil)
  47. if err != nil {
  48. t.Fatal(err)
  49. }
  50. res, err := tr.RoundTrip(req)
  51. if err != nil {
  52. t.Fatal(err)
  53. }
  54. defer res.Body.Close()
  55. t.Logf("Got res: %+v", res)
  56. if g, w := res.StatusCode, 200; g != w {
  57. t.Errorf("StatusCode = %v; want %v", g, w)
  58. }
  59. if g, w := res.Status, "200 OK"; g != w {
  60. t.Errorf("Status = %q; want %q", g, w)
  61. }
  62. wantHeader := http.Header{
  63. "Content-Length": []string{"3"},
  64. "Content-Type": []string{"text/plain; charset=utf-8"},
  65. }
  66. if !reflect.DeepEqual(res.Header, wantHeader) {
  67. t.Errorf("res Header = %v; want %v", res.Header, wantHeader)
  68. }
  69. if res.Request != req {
  70. t.Errorf("Response.Request = %p; want %p", res.Request, req)
  71. }
  72. if res.TLS == nil {
  73. t.Error("Response.TLS = nil; want non-nil")
  74. }
  75. slurp, err := ioutil.ReadAll(res.Body)
  76. if err != nil {
  77. t.Errorf("Body read: %v", err)
  78. } else if string(slurp) != body {
  79. t.Errorf("Body = %q; want %q", slurp, body)
  80. }
  81. }
  82. func TestTransportReusesConns(t *testing.T) {
  83. st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
  84. io.WriteString(w, r.RemoteAddr)
  85. }, optOnlyServer)
  86. defer st.Close()
  87. tr := &Transport{TLSClientConfig: tlsConfigInsecure}
  88. defer tr.CloseIdleConnections()
  89. get := func() string {
  90. req, err := http.NewRequest("GET", st.ts.URL, nil)
  91. if err != nil {
  92. t.Fatal(err)
  93. }
  94. res, err := tr.RoundTrip(req)
  95. if err != nil {
  96. t.Fatal(err)
  97. }
  98. defer res.Body.Close()
  99. slurp, err := ioutil.ReadAll(res.Body)
  100. if err != nil {
  101. t.Fatalf("Body read: %v", err)
  102. }
  103. addr := strings.TrimSpace(string(slurp))
  104. if addr == "" {
  105. t.Fatalf("didn't get an addr in response")
  106. }
  107. return addr
  108. }
  109. first := get()
  110. second := get()
  111. if first != second {
  112. t.Errorf("first and second responses were on different connections: %q vs %q", first, second)
  113. }
  114. }
  115. func TestTransportAbortClosesPipes(t *testing.T) {
  116. shutdown := make(chan struct{})
  117. st := newServerTester(t,
  118. func(w http.ResponseWriter, r *http.Request) {
  119. w.(http.Flusher).Flush()
  120. <-shutdown
  121. },
  122. optOnlyServer,
  123. )
  124. defer st.Close()
  125. defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
  126. done := make(chan struct{})
  127. requestMade := make(chan struct{})
  128. go func() {
  129. defer close(done)
  130. tr := &Transport{TLSClientConfig: tlsConfigInsecure}
  131. req, err := http.NewRequest("GET", st.ts.URL, nil)
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. res, err := tr.RoundTrip(req)
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. defer res.Body.Close()
  140. close(requestMade)
  141. _, err = ioutil.ReadAll(res.Body)
  142. if err == nil {
  143. t.Error("expected error from res.Body.Read")
  144. }
  145. }()
  146. <-requestMade
  147. // Now force the serve loop to end, via closing the connection.
  148. st.closeConn()
  149. // deadlock? that's a bug.
  150. select {
  151. case <-done:
  152. case <-time.After(3 * time.Second):
  153. t.Fatal("timeout")
  154. }
  155. }
  156. // TODO: merge this with TestTransportBody to make TestTransportRequest? This
  157. // could be a table-driven test with extra goodies.
  158. func TestTransportPath(t *testing.T) {
  159. gotc := make(chan *url.URL, 1)
  160. st := newServerTester(t,
  161. func(w http.ResponseWriter, r *http.Request) {
  162. gotc <- r.URL
  163. },
  164. optOnlyServer,
  165. )
  166. defer st.Close()
  167. tr := &Transport{TLSClientConfig: tlsConfigInsecure}
  168. defer tr.CloseIdleConnections()
  169. const (
  170. path = "/testpath"
  171. query = "q=1"
  172. )
  173. surl := st.ts.URL + path + "?" + query
  174. req, err := http.NewRequest("POST", surl, nil)
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. c := &http.Client{Transport: tr}
  179. res, err := c.Do(req)
  180. if err != nil {
  181. t.Fatal(err)
  182. }
  183. defer res.Body.Close()
  184. got := <-gotc
  185. if got.Path != path {
  186. t.Errorf("Read Path = %q; want %q", got.Path, path)
  187. }
  188. if got.RawQuery != query {
  189. t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
  190. }
  191. }
  192. func TestTransportBody(t *testing.T) {
  193. gotc := make(chan interface{}, 1)
  194. st := newServerTester(t,
  195. func(w http.ResponseWriter, r *http.Request) {
  196. slurp, err := ioutil.ReadAll(r.Body)
  197. if err != nil {
  198. gotc <- err
  199. } else {
  200. gotc <- string(slurp)
  201. }
  202. },
  203. optOnlyServer,
  204. )
  205. defer st.Close()
  206. tr := &Transport{TLSClientConfig: tlsConfigInsecure}
  207. defer tr.CloseIdleConnections()
  208. const body = "Some message"
  209. req, err := http.NewRequest("POST", st.ts.URL, strings.NewReader(body))
  210. if err != nil {
  211. t.Fatal(err)
  212. }
  213. c := &http.Client{Transport: tr}
  214. res, err := c.Do(req)
  215. if err != nil {
  216. t.Fatal(err)
  217. }
  218. defer res.Body.Close()
  219. got := <-gotc
  220. if err, ok := got.(error); ok {
  221. t.Fatal(err)
  222. } else if got.(string) != body {
  223. t.Errorf("Read body = %q; want %q", got, body)
  224. }
  225. }
  226. func TestTransportDialTLS(t *testing.T) {
  227. var mu sync.Mutex // guards following
  228. var gotReq, didDial bool
  229. ts := newServerTester(t,
  230. func(w http.ResponseWriter, r *http.Request) {
  231. mu.Lock()
  232. gotReq = true
  233. mu.Unlock()
  234. },
  235. optOnlyServer,
  236. )
  237. defer ts.Close()
  238. tr := &Transport{
  239. DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
  240. mu.Lock()
  241. didDial = true
  242. mu.Unlock()
  243. cfg.InsecureSkipVerify = true
  244. c, err := tls.Dial(netw, addr, cfg)
  245. if err != nil {
  246. return nil, err
  247. }
  248. return c, c.Handshake()
  249. },
  250. }
  251. defer tr.CloseIdleConnections()
  252. client := &http.Client{Transport: tr}
  253. res, err := client.Get(ts.ts.URL)
  254. if err != nil {
  255. t.Fatal(err)
  256. }
  257. res.Body.Close()
  258. mu.Lock()
  259. if !gotReq {
  260. t.Error("didn't get request")
  261. }
  262. if !didDial {
  263. t.Error("didn't use dial hook")
  264. }
  265. }