h2c.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. hijacker, ok := w.(http.Hijacker)
  126. if !ok {
  127. return nil, errors.New("h2c: connection does not support Hijack")
  128. }
  129. conn, rw, err := hijacker.Hijack()
  130. if err != nil {
  131. return nil, err
  132. }
  133. const expectedBody = "SM\r\n\r\n"
  134. buf := make([]byte, len(expectedBody))
  135. n, err := io.ReadFull(rw, buf)
  136. if err != nil {
  137. return nil, fmt.Errorf("h2c: error reading client preface: %s", err)
  138. }
  139. if string(buf[:n]) == expectedBody {
  140. return newBufConn(conn, rw), nil
  141. }
  142. conn.Close()
  143. return nil, errors.New("h2c: invalid client preface")
  144. }
  145. // h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
  146. func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings []byte, err error) {
  147. settings, err = getH2Settings(r.Header)
  148. if err != nil {
  149. return nil, nil, err
  150. }
  151. hijacker, ok := w.(http.Hijacker)
  152. if !ok {
  153. return nil, nil, errors.New("h2c: connection does not support Hijack")
  154. }
  155. body, err := io.ReadAll(r.Body)
  156. if err != nil {
  157. return nil, nil, err
  158. }
  159. r.Body = io.NopCloser(bytes.NewBuffer(body))
  160. conn, rw, err := hijacker.Hijack()
  161. if err != nil {
  162. return nil, nil, err
  163. }
  164. rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
  165. "Connection: Upgrade\r\n" +
  166. "Upgrade: h2c\r\n\r\n"))
  167. return newBufConn(conn, rw), settings, nil
  168. }
  169. // isH2CUpgrade returns true if the header properly request an upgrade to h2c
  170. // as specified by Section 3.2.
  171. func isH2CUpgrade(h http.Header) bool {
  172. return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
  173. httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
  174. }
  175. // getH2Settings returns the settings in the HTTP2-Settings header.
  176. func getH2Settings(h http.Header) ([]byte, error) {
  177. vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
  178. if !ok {
  179. return nil, errors.New("missing HTTP2-Settings header")
  180. }
  181. if len(vals) != 1 {
  182. return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
  183. }
  184. settings, err := base64.RawURLEncoding.DecodeString(vals[0])
  185. if err != nil {
  186. return nil, err
  187. }
  188. return settings, nil
  189. }
  190. func newBufConn(conn net.Conn, rw *bufio.ReadWriter) net.Conn {
  191. rw.Flush()
  192. if rw.Reader.Buffered() == 0 {
  193. // If there's no buffered data to be read,
  194. // we can just discard the bufio.ReadWriter.
  195. return conn
  196. }
  197. return &bufConn{conn, rw.Reader}
  198. }
  199. // bufConn wraps a net.Conn, but reads drain the bufio.Reader first.
  200. type bufConn struct {
  201. net.Conn
  202. *bufio.Reader
  203. }
  204. func (c *bufConn) Read(p []byte) (int, error) {
  205. if c.Reader == nil {
  206. return c.Conn.Read(p)
  207. }
  208. n := c.Reader.Buffered()
  209. if n == 0 {
  210. c.Reader = nil
  211. return c.Conn.Read(p)
  212. }
  213. if n < len(p) {
  214. p = p[:n]
  215. }
  216. return c.Reader.Read(p)
  217. }