gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/http2/h2c/h2c.go (about)

     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  
     5  // Package h2c implements the unencrypted "h2c" form of HTTP/2.
     6  //
     7  // The h2c protocol is the non-TLS version of HTTP/2 which is not available from
     8  // net/http or golang.org/x/net/http2.
     9  package h2c
    10  
    11  import (
    12  	"bufio"
    13  	"bytes"
    14  	"encoding/base64"
    15  	"encoding/binary"
    16  	"errors"
    17  	"fmt"
    18  	"io"
    19  	"log"
    20  	"net"
    21  	"net/textproto"
    22  	"os"
    23  	"strings"
    24  
    25  	http "gitee.com/ks-custle/core-gm/gmhttp"
    26  	"gitee.com/ks-custle/core-gm/net/http/httpguts"
    27  	"gitee.com/ks-custle/core-gm/net/http2"
    28  	"gitee.com/ks-custle/core-gm/net/http2/hpack"
    29  )
    30  
    31  var (
    32  	http2VerboseLogs bool
    33  )
    34  
    35  func init() {
    36  	e := os.Getenv("GODEBUG")
    37  	if strings.Contains(e, "http2debug=1") || strings.Contains(e, "http2debug=2") {
    38  		http2VerboseLogs = true
    39  	}
    40  }
    41  
    42  // h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
    43  // that should be h2c traffic. There are two ways to begin a h2c connection
    44  // (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
    45  // works by starting an h2c connection with a string of bytes that is valid
    46  // HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
    47  // h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
    48  // h2c. When either of those situations occur we hijack the HTTP/1 connection,
    49  // convert it to a HTTP/2 connection and pass the net.Conn to http2.ServeConn.
    50  type h2cHandler struct {
    51  	Handler http.Handler
    52  	s       *http2.Server
    53  }
    54  
    55  // NewHandler returns an http.Handler that wraps h, intercepting any h2c
    56  // traffic. If a request is an h2c connection, it's hijacked and redirected to
    57  // s.ServeConn. Otherwise the returned Handler just forwards requests to h. This
    58  // works because h2c is designed to be parseable as valid HTTP/1, but ignored by
    59  // any HTTP server that does not handle h2c. Therefore we leverage the HTTP/1
    60  // compatible parts of the Go http library to parse and recognize h2c requests.
    61  // Once a request is recognized as h2c, we hijack the connection and convert it
    62  // to an HTTP/2 connection which is understandable to s.ServeConn. (s.ServeConn
    63  // understands HTTP/2 except for the h2c part of it.)
    64  func NewHandler(h http.Handler, s *http2.Server) http.Handler {
    65  	return &h2cHandler{
    66  		Handler: h,
    67  		s:       s,
    68  	}
    69  }
    70  
    71  // ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
    72  func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    73  	// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
    74  	if r.Method == "PRI" && len(r.Header) == 0 && r.URL.Path == "*" && r.Proto == "HTTP/2.0" {
    75  		if http2VerboseLogs {
    76  			log.Print("h2c: attempting h2c with prior knowledge.")
    77  		}
    78  		conn, err := initH2CWithPriorKnowledge(w)
    79  		if err != nil {
    80  			if http2VerboseLogs {
    81  				log.Printf("h2c: error h2c with prior knowledge: %v", err)
    82  			}
    83  			return
    84  		}
    85  		defer conn.Close()
    86  
    87  		s.s.ServeConn(conn, &http2.ServeConnOpts{
    88  			Context: r.Context(),
    89  			Handler: s.Handler,
    90  		})
    91  		return
    92  	}
    93  	// Handle Upgrade to h2c (RFC 7540 Section 3.2)
    94  	if conn, err := h2cUpgrade(w, r); err == nil {
    95  		defer conn.Close()
    96  
    97  		s.s.ServeConn(conn, &http2.ServeConnOpts{
    98  			Context: r.Context(),
    99  			Handler: s.Handler,
   100  		})
   101  		return
   102  	}
   103  
   104  	s.Handler.ServeHTTP(w, r)
   105  	return
   106  }
   107  
   108  // initH2CWithPriorKnowledge implements creating a h2c connection with prior
   109  // knowledge (Section 3.4) and creates a net.Conn suitable for http2.ServeConn.
   110  // All we have to do is look for the client preface that is suppose to be part
   111  // of the body, and reforward the client preface on the net.Conn this function
   112  // creates.
   113  func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) {
   114  	hijacker, ok := w.(http.Hijacker)
   115  	if !ok {
   116  		panic("Hijack not supported.")
   117  	}
   118  	conn, rw, err := hijacker.Hijack()
   119  	if err != nil {
   120  		panic(fmt.Sprintf("Hijack failed: %v", err))
   121  	}
   122  
   123  	const expectedBody = "SM\r\n\r\n"
   124  
   125  	buf := make([]byte, len(expectedBody))
   126  	n, err := io.ReadFull(rw, buf)
   127  	if err != nil {
   128  		return nil, fmt.Errorf("could not read from the buffer: %s", err)
   129  	}
   130  
   131  	if string(buf[:n]) == expectedBody {
   132  		c := &rwConn{
   133  			Conn:      conn,
   134  			Reader:    io.MultiReader(strings.NewReader(http2.ClientPreface), rw),
   135  			BufWriter: rw.Writer,
   136  		}
   137  		return c, nil
   138  	}
   139  
   140  	conn.Close()
   141  	if http2VerboseLogs {
   142  		log.Printf(
   143  			"h2c: missing the request body portion of the client preface. Wanted: %v Got: %v",
   144  			[]byte(expectedBody),
   145  			buf[0:n],
   146  		)
   147  	}
   148  	return nil, errors.New("invalid client preface")
   149  }
   150  
   151  // drainClientPreface reads a single instance of the HTTP/2 client preface from
   152  // the supplied reader.
   153  func drainClientPreface(r io.Reader) error {
   154  	var buf bytes.Buffer
   155  	prefaceLen := int64(len(http2.ClientPreface))
   156  	n, err := io.CopyN(&buf, r, prefaceLen)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	if n != prefaceLen || buf.String() != http2.ClientPreface {
   161  		return fmt.Errorf("Client never sent: %s", http2.ClientPreface)
   162  	}
   163  	return nil
   164  }
   165  
   166  // h2cUpgrade establishes a h2c connection using the HTTP/1 upgrade (Section 3.2).
   167  func h2cUpgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
   168  	if !isH2CUpgrade(r.Header) {
   169  		return nil, errors.New("non-conforming h2c headers")
   170  	}
   171  
   172  	// Initial bytes we put into conn to fool http2 server
   173  	initBytes, _, err := convertH1ReqToH2(r)
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  
   178  	hijacker, ok := w.(http.Hijacker)
   179  	if !ok {
   180  		return nil, errors.New("hijack not supported.")
   181  	}
   182  	conn, rw, err := hijacker.Hijack()
   183  	if err != nil {
   184  		return nil, fmt.Errorf("hijack failed: %v", err)
   185  	}
   186  
   187  	rw.Write([]byte("HTTP/1.1 101 Switching Protocols\r\n" +
   188  		"Connection: Upgrade\r\n" +
   189  		"Upgrade: h2c\r\n\r\n"))
   190  	rw.Flush()
   191  
   192  	// A conforming client will now send an H2 client preface which need to drain
   193  	// since we already sent this.
   194  	if err := drainClientPreface(rw); err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	c := &rwConn{
   199  		Conn:      conn,
   200  		Reader:    io.MultiReader(initBytes, rw),
   201  		BufWriter: newSettingsAckSwallowWriter(rw.Writer),
   202  	}
   203  	return c, nil
   204  }
   205  
   206  // convert the data contained in the HTTP/1 upgrade request into the HTTP/2
   207  // version in byte form.
   208  func convertH1ReqToH2(r *http.Request) (*bytes.Buffer, []http2.Setting, error) {
   209  	h2Bytes := bytes.NewBuffer([]byte((http2.ClientPreface)))
   210  	framer := http2.NewFramer(h2Bytes, nil)
   211  	settings, err := getH2Settings(r.Header)
   212  	if err != nil {
   213  		return nil, nil, err
   214  	}
   215  
   216  	if err := framer.WriteSettings(settings...); err != nil {
   217  		return nil, nil, err
   218  	}
   219  
   220  	headerBytes, err := getH2HeaderBytes(r, getMaxHeaderTableSize(settings))
   221  	if err != nil {
   222  		return nil, nil, err
   223  	}
   224  
   225  	maxFrameSize := int(getMaxFrameSize(settings))
   226  	needOneHeader := len(headerBytes) < maxFrameSize
   227  	err = framer.WriteHeaders(http2.HeadersFrameParam{
   228  		StreamID:      1,
   229  		BlockFragment: headerBytes,
   230  		EndHeaders:    needOneHeader,
   231  	})
   232  	if err != nil {
   233  		return nil, nil, err
   234  	}
   235  
   236  	for i := maxFrameSize; i < len(headerBytes); i += maxFrameSize {
   237  		if len(headerBytes)-i > maxFrameSize {
   238  			if err := framer.WriteContinuation(1,
   239  				false, // endHeaders
   240  				headerBytes[i:maxFrameSize]); err != nil {
   241  				return nil, nil, err
   242  			}
   243  		} else {
   244  			if err := framer.WriteContinuation(1,
   245  				true, // endHeaders
   246  				headerBytes[i:]); err != nil {
   247  				return nil, nil, err
   248  			}
   249  		}
   250  	}
   251  
   252  	return h2Bytes, settings, nil
   253  }
   254  
   255  // getMaxFrameSize returns the SETTINGS_MAX_FRAME_SIZE. If not present default
   256  // value is 16384 as specified by RFC 7540 Section 6.5.2.
   257  func getMaxFrameSize(settings []http2.Setting) uint32 {
   258  	for _, setting := range settings {
   259  		if setting.ID == http2.SettingMaxFrameSize {
   260  			return setting.Val
   261  		}
   262  	}
   263  	return 16384
   264  }
   265  
   266  // getMaxHeaderTableSize returns the SETTINGS_HEADER_TABLE_SIZE. If not present
   267  // default value is 4096 as specified by RFC 7540 Section 6.5.2.
   268  func getMaxHeaderTableSize(settings []http2.Setting) uint32 {
   269  	for _, setting := range settings {
   270  		if setting.ID == http2.SettingHeaderTableSize {
   271  			return setting.Val
   272  		}
   273  	}
   274  	return 4096
   275  }
   276  
   277  // bufWriter is a Writer interface that also has a Flush method.
   278  type bufWriter interface {
   279  	io.Writer
   280  	Flush() error
   281  }
   282  
   283  // rwConn implements net.Conn but overrides Read and Write so that reads and
   284  // writes are forwarded to the provided io.Reader and bufWriter.
   285  type rwConn struct {
   286  	net.Conn
   287  	io.Reader
   288  	BufWriter bufWriter
   289  }
   290  
   291  // Read forwards reads to the underlying Reader.
   292  func (c *rwConn) Read(p []byte) (int, error) {
   293  	return c.Reader.Read(p)
   294  }
   295  
   296  // Write forwards writes to the underlying bufWriter and immediately flushes.
   297  func (c *rwConn) Write(p []byte) (int, error) {
   298  	n, err := c.BufWriter.Write(p)
   299  	if err := c.BufWriter.Flush(); err != nil {
   300  		return 0, err
   301  	}
   302  	return n, err
   303  }
   304  
   305  // settingsAckSwallowWriter is a writer that normally forwards bytes to its
   306  // underlying Writer, but swallows the first SettingsAck frame that it sees.
   307  type settingsAckSwallowWriter struct {
   308  	Writer     *bufio.Writer
   309  	buf        []byte
   310  	didSwallow bool
   311  }
   312  
   313  // newSettingsAckSwallowWriter returns a new settingsAckSwallowWriter.
   314  func newSettingsAckSwallowWriter(w *bufio.Writer) *settingsAckSwallowWriter {
   315  	return &settingsAckSwallowWriter{
   316  		Writer:     w,
   317  		buf:        make([]byte, 0),
   318  		didSwallow: false,
   319  	}
   320  }
   321  
   322  // Write implements io.Writer interface. Normally forwards bytes to w.Writer,
   323  // except for the first Settings ACK frame that it sees.
   324  func (w *settingsAckSwallowWriter) Write(p []byte) (int, error) {
   325  	if !w.didSwallow {
   326  		w.buf = append(w.buf, p...)
   327  		// Process all the frames we have collected into w.buf
   328  		for {
   329  			// Append until we get full frame header which is 9 bytes
   330  			if len(w.buf) < 9 {
   331  				break
   332  			}
   333  			// Check if we have collected a whole frame.
   334  			fh, err := http2.ReadFrameHeader(bytes.NewBuffer(w.buf))
   335  			if err != nil {
   336  				// Corrupted frame, fail current Write
   337  				return 0, err
   338  			}
   339  			fSize := fh.Length + 9
   340  			if uint32(len(w.buf)) < fSize {
   341  				// Have not collected whole frame. Stop processing buf, and withhold on
   342  				// forward bytes to w.Writer until we get the full frame.
   343  				break
   344  			}
   345  
   346  			// We have now collected a whole frame.
   347  			if fh.Type == http2.FrameSettings && fh.Flags.Has(http2.FlagSettingsAck) {
   348  				// If Settings ACK frame, do not forward to underlying writer, remove
   349  				// bytes from w.buf, and record that we have swallowed Settings Ack
   350  				// frame.
   351  				w.didSwallow = true
   352  				w.buf = w.buf[fSize:]
   353  				continue
   354  			}
   355  
   356  			// Not settings ack frame. Forward bytes to w.Writer.
   357  			if _, err := w.Writer.Write(w.buf[:fSize]); err != nil {
   358  				// Couldn't forward bytes. Fail current Write.
   359  				return 0, err
   360  			}
   361  			w.buf = w.buf[fSize:]
   362  		}
   363  		return len(p), nil
   364  	}
   365  	return w.Writer.Write(p)
   366  }
   367  
   368  // Flush calls w.Writer.Flush.
   369  func (w *settingsAckSwallowWriter) Flush() error {
   370  	return w.Writer.Flush()
   371  }
   372  
   373  // isH2CUpgrade returns true if the header properly request an upgrade to h2c
   374  // as specified by Section 3.2.
   375  func isH2CUpgrade(h http.Header) bool {
   376  	return httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
   377  		httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
   378  }
   379  
   380  // getH2Settings returns the []http2.Setting that are encoded in the
   381  // HTTP2-Settings header.
   382  func getH2Settings(h http.Header) ([]http2.Setting, error) {
   383  	vals, ok := h[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")]
   384  	if !ok {
   385  		return nil, errors.New("missing HTTP2-Settings header")
   386  	}
   387  	if len(vals) != 1 {
   388  		return nil, fmt.Errorf("expected 1 HTTP2-Settings. Got: %v", vals)
   389  	}
   390  	settings, err := decodeSettings(vals[0])
   391  	if err != nil {
   392  		return nil, fmt.Errorf("Invalid HTTP2-Settings: %q", vals[0])
   393  	}
   394  	return settings, nil
   395  }
   396  
   397  // decodeSettings decodes the base64url header value of the HTTP2-Settings
   398  // header. RFC 7540 Section 3.2.1.
   399  func decodeSettings(headerVal string) ([]http2.Setting, error) {
   400  	b, err := base64.RawURLEncoding.DecodeString(headerVal)
   401  	if err != nil {
   402  		return nil, err
   403  	}
   404  	if len(b)%6 != 0 {
   405  		return nil, err
   406  	}
   407  	settings := make([]http2.Setting, 0)
   408  	for i := 0; i < len(b)/6; i++ {
   409  		settings = append(settings, http2.Setting{
   410  			ID:  http2.SettingID(binary.BigEndian.Uint16(b[i*6 : i*6+2])),
   411  			Val: binary.BigEndian.Uint32(b[i*6+2 : i*6+6]),
   412  		})
   413  	}
   414  
   415  	return settings, nil
   416  }
   417  
   418  // getH2HeaderBytes return the headers in r a []bytes encoded by HPACK.
   419  func getH2HeaderBytes(r *http.Request, maxHeaderTableSize uint32) ([]byte, error) {
   420  	headerBytes := bytes.NewBuffer(nil)
   421  	hpackEnc := hpack.NewEncoder(headerBytes)
   422  	hpackEnc.SetMaxDynamicTableSize(maxHeaderTableSize)
   423  
   424  	// Section 8.1.2.3
   425  	err := hpackEnc.WriteField(hpack.HeaderField{
   426  		Name:  ":method",
   427  		Value: r.Method,
   428  	})
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  
   433  	err = hpackEnc.WriteField(hpack.HeaderField{
   434  		Name:  ":scheme",
   435  		Value: "http",
   436  	})
   437  	if err != nil {
   438  		return nil, err
   439  	}
   440  
   441  	err = hpackEnc.WriteField(hpack.HeaderField{
   442  		Name:  ":authority",
   443  		Value: r.Host,
   444  	})
   445  	if err != nil {
   446  		return nil, err
   447  	}
   448  
   449  	path := r.URL.Path
   450  	if r.URL.RawQuery != "" {
   451  		path = strings.Join([]string{path, r.URL.RawQuery}, "?")
   452  	}
   453  	err = hpackEnc.WriteField(hpack.HeaderField{
   454  		Name:  ":path",
   455  		Value: path,
   456  	})
   457  	if err != nil {
   458  		return nil, err
   459  	}
   460  
   461  	// TODO Implement Section 8.3
   462  
   463  	for header, values := range r.Header {
   464  		// Skip non h2 headers
   465  		if isNonH2Header(header) {
   466  			continue
   467  		}
   468  		for _, v := range values {
   469  			err := hpackEnc.WriteField(hpack.HeaderField{
   470  				Name:  strings.ToLower(header),
   471  				Value: v,
   472  			})
   473  			if err != nil {
   474  				return nil, err
   475  			}
   476  		}
   477  	}
   478  	return headerBytes.Bytes(), nil
   479  }
   480  
   481  // Connection specific headers listed in RFC 7540 Section 8.1.2.2 that are not
   482  // suppose to be transferred to HTTP/2. The Http2-Settings header is skipped
   483  // since already use to create the HTTP/2 SETTINGS frame.
   484  var nonH2Headers = []string{
   485  	"Connection",
   486  	"Keep-Alive",
   487  	"Proxy-Connection",
   488  	"Transfer-Encoding",
   489  	"Upgrade",
   490  	"Http2-Settings",
   491  }
   492  
   493  // isNonH2Header returns true if header should not be transferred to HTTP/2.
   494  func isNonH2Header(header string) bool {
   495  	for _, nonH2h := range nonH2Headers {
   496  		if header == nonH2h {
   497  			return true
   498  		}
   499  	}
   500  	return false
   501  }