h2c.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright 2018 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 h2c implements the unencrypted "h2c" form of HTTP/2.
  5. //
  6. // The h2c protocol is the non-TLS version of HTTP/2 which is not available from
  7. // net/http or golang.org/x/net/http2.
  8. package h2c
  9. import (
  10. "bufio"
  11. "bytes"
  12. "encoding/base64"
  13. "errors"
  14. "fmt"
  15. "io"
  16. "log"
  17. "net"
  18. "net/http"
  19. "net/textproto"
  20. "os"
  21. "strings"
  22. "golang.org/x/net/http/httpguts"
  23. "golang.org/x/net/http2"
  24. )
  25. var (
  26. http2VerboseLogs bool
  27. )
  28. func init() {
  29. e := os.Getenv("GODEBUG")
  30. if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") {
  31. http2VerboseLogs = true
  32. }
  33. }
  34. // h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
  35. // that should be h2c traffic. There are two ways to begin a h2c connection
  36. // (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
  37. // works by starting an h2c connection with a string of bytes that is valid
  38. // HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
  39. // h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
  40. // h2c. When either of those situations occur we hijack the HTTP/1 connection,
  41. // convert it to an HTTP/2 connection and pass the net.Conn to http2.ServeConn.
  42. type h2cHandler struct {
  43. Handler http.Handler
  44. s *http2.Server
  45. }
  46. // NewHandler returns an http.Handler that wraps h, intercepting any h2c
  47. // traffic. If a request is an h2c connection, it's hijacked and redirected to
  48. // s.ServeConn. Otherwise the returned Handler just forwards requests to h. This
  49. // works because h2c is designed to be parseable as valid HTTP/1, but ignored by
  50. // any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1
  51. // compatible parts of the Go http library to parse and recognize h2c requests.
  52. // Once a request is recognized as h2c, we hijack the connection and convert it
  53. // to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn
  54. // understands HTTP/2 except for the h2c part of it.)
  55. //
  56. // The first request on an h2c connection is read entirely into memory before
  57. // the Handler is called. To limit the memory consumed by this request, wrap
  58. // the result of NewHandler in an http.MaxBytesHandler.
  59. func NewHandler(h http.Handler, s *http2.Server) http.Handler {
  60. return &h2cHandler{
  61. Handler: h,
  62. s: s,
  63. }
  64. }
  65. // extractServer extracts existing http.Server instance from http.Request or create an empty http.Server
  66. func extractServer(r *http.Request) *http.Server {
  67. server, ok := r.Context().Value(http.ServerContextKey).(*http.Server)
  68. if ok {
  69. return server
  70. }
  71. return new(http.Server)
  72. }
  73. // ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
  74. func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  75. // Handle h2c with prior knowledge (RFC 7540 Section 3.4)
  76. if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" {
  77. if http2VerboseLogs {
  78. log.Print("h2c: attempting h2c with prior knowledge.")
  79. }
  80. conn, err := initH2CWithPriorKnowledge(w)
  81. if err != nil {
  82. if http2VerboseLogs {
  83. log.Printf("h2c: error h2c with prior knowledge: %v", err)
  84. }
  85. return
  86. }
  87. defer conn.Close()
  88. s.s.ServeConn(conn, &http2.ServeConnOpts{
  89. Context: r.Context(),
  90. BaseConfig: extractServer(r),
  91. Handler: s.Handler,
  92. SawClientPreface: true,
  93. })
  94. return
  95. }
  96. // Handle Upgrade to h2c (RFC 7540 Section 3.2)
  97. if isH2CUpgrade(r.Header) {
  98. conn, settings, err := h2cUpgrade(w, r)
  99. if err != nil {
  100. if http2VerboseLogs {
  101. log.Printf("h2c: error h2c upgrade: %v", err)
  102. }
  103. w.WriteHeader(http.StatusInternalServerError)
  104. return
  105. }
  106. defer conn.Close()
  107. s.s.ServeConn(conn, &http2.ServeConnOpts{
  108. Context: r.Context(),
  109. BaseConfig: extractServer(r),
  110. Handler: s.Handler,
  111. UpgradeRequest: r,
  112. Settings: settings,
  113. })
  114. return
  115. }
  116. s.Handler.ServeHTTP(w, r)
  117. return
  118. }
  119. // initH2CWithPriorKnowledge implements creating a h2c connection with prior
  120. // knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn.
  121. // All we have to do is look for the client preface that is suppose to be part
  122. // of the body, and reforward the client preface on the net.Conn this function
  123. // creates.
  124. func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) {
  125. rc := http.NewResponseController(w)
  126. conn, rw, err := rc.Hijack()
  127. if err != nil {
  128. return nil, err
  129. }
  130. const expectedBody = "SM\r\n\r\n"
  131. buf := make([]byte, len(expectedBody))
  132. n, err := io.ReadFull(rw, buf)
  133. if err != nil {
  134. return nil, fmt.Errorf("h2c: error reading client preface: %s", err)
  135. }
  136. if string(buf[:n]) == expectedBody {
  137. return newBufConn(conn, rw), nil
  138. }
  139. conn.Close()
  140. return nil, errors.New("h2c: invalid client preface")
  141. }
  142. // h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
  143. func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings []byte, err error) {
  144. settings, err = getH2Settings(r.Header)
  145. if err != nil {
  146. return nil, nil, err
  147. }
  148. body, err := io.ReadAll(r.Body)
  149. if err != nil {
  150. return nil, nil, err
  151. }
  152. r.Body = io.NopCloser(bytes.NewBuffer(body))
  153. rc := http.NewResponseController(w)
  154. conn, rw, err := rc.Hijack()
  155. if err != nil {
  156. return nil, nil, err
  157. }
  158. rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
  159. "Connection: Upgrade\r\n" +
  160. "Upgrade: h2c\r\n\r\n"))
  161. return newBufConn(conn, rw), settings, nil
  162. }
  163. // isH2CUpgrade returns true if the header properly request an upgrade to h2c
  164. // as specified by Section 3.2.
  165. func isH2CUpgrade(h http.Header) bool {
  166. return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
  167. httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
  168. }
  169. // getH2Settings returns the settings in the HTTP2-Settings header.
  170. func getH2Settings(h http.Header) ([]byte, error) {
  171. vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
  172. if !ok {
  173. return nil, errors.New("missing HTTP2-Settings header")
  174. }
  175. if len(vals) != 1 {
  176. return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
  177. }
  178. settings, err := base64.RawURLEncoding.DecodeString(vals[0])
  179. if err != nil {
  180. return nil, err
  181. }
  182. return settings, nil
  183. }
  184. func newBufConn(conn net.Conn, rw *bufio.ReadWriter) net.Conn {
  185. rw.Flush()
  186. if rw.Reader.Buffered() == 0 {
  187. // If there's no buffered data to be read,
  188. // we can just discard the bufio.ReadWriter.
  189. return conn
  190. }
  191. return &bufConn{conn, rw.Reader}
  192. }
  193. // bufConn wraps a net.Conn, but reads drain the bufio.Reader first.
  194. type bufConn struct {
  195. net.Conn
  196. *bufio.Reader
  197. }
  198. func (c *bufConn) Read(p []byte) (int, error) {
  199. if c.Reader == nil {
  200. return c.Conn.Read(p)
  201. }
  202. n := c.Reader.Buffered()
  203. if n == 0 {
  204. c.Reader = nil
  205. return c.Conn.Read(p)
  206. }
  207. if n < len(p) {
  208. p = p[:n]
  209. }
  210. return c.Reader.Read(p)
  211. }