Source file src/net/http/http2.go

     1  // Copyright 2026 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  //go:build !nethttpomithttp2
     6  
     7  package http
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"errors"
    13  	"io"
    14  	"log"
    15  	"net"
    16  	"net/http/internal/http2"
    17  	"time"
    18  
    19  	_ "unsafe" // for go:linkname
    20  )
    21  
    22  // net/http supports HTTP/2 by default, but this support is removed when
    23  // the nethttpomithttp2 build tag is set.
    24  //
    25  // HTTP/2 support is provided by the net/http/internal/http2 package.
    26  //
    27  // This file (http2.go) connects net/http to the http2 package.
    28  // Since http imports http2, to avoid an import cycle we need to
    29  // translate http package types (e.g., Request) into the equivalent
    30  // http2 package types (e.g., http2.ClientRequest).
    31  //
    32  // The golang.org/x/net/http2 package is the original source of truth for
    33  // the HTTP/2 implementation. At this time, users may still import that
    34  // package and register its implementation on a net/http Transport or Server.
    35  // However, the x/net package is no longer synchronized with std.
    36  
    37  func init() {
    38  	// NoBody and LocalAddrContextKey need to have the same value
    39  	// in the http and http2 packages.
    40  	//
    41  	// We can't define these values in net/http/internal,
    42  	// because their concrete types are part of the net/http API and
    43  	// moving them causes API checker failures.
    44  	// Override the http2 package versions at init time instead.
    45  	http2.LocalAddrContextKey = LocalAddrContextKey
    46  	http2.NoBody = NoBody
    47  }
    48  
    49  type http2Server = http2.Server
    50  
    51  func (s *Server) configureHTTP2() {
    52  	h2srv := &http2.Server{}
    53  
    54  	// Historically, we've configured the HTTP/2 idle timeout in this fashion:
    55  	// Set once at configuration time.
    56  	if s.IdleTimeout != 0 {
    57  		h2srv.IdleTimeout = s.IdleTimeout
    58  	} else {
    59  		h2srv.IdleTimeout = s.ReadTimeout
    60  	}
    61  
    62  	if s.TLSConfig == nil {
    63  		s.TLSConfig = &tls.Config{}
    64  	}
    65  	s.nextProtoErr = h2srv.Configure(http2ServerConfig{s}, s.TLSConfig)
    66  	if s.nextProtoErr != nil {
    67  		return
    68  	}
    69  
    70  	s.RegisterOnShutdown(h2srv.GracefulShutdown)
    71  
    72  	if s.TLSNextProto == nil {
    73  		s.TLSNextProto = make(map[string]func(*Server, *tls.Conn, Handler))
    74  	}
    75  	type baseContexter interface {
    76  		BaseContext() context.Context
    77  	}
    78  	s.TLSNextProto["h2"] = func(hs *Server, c *tls.Conn, h Handler) {
    79  		h2srv.ServeConn(c, &http2.ServeConnOpts{
    80  			Context:    h.(baseContexter).BaseContext(),
    81  			Handler:    http2Handler{h},
    82  			BaseConfig: http2ServerConfig{hs},
    83  		})
    84  	}
    85  	s.TLSNextProto[nextProtoUnencryptedHTTP2] = func(hs *Server, c *tls.Conn, h Handler) {
    86  		nc := c.NetConn().(interface {
    87  			UnencryptedNetConn() net.Conn
    88  		}).UnencryptedNetConn()
    89  		h2srv.ServeConn(nc, &http2.ServeConnOpts{
    90  			Context:          h.(baseContexter).BaseContext(),
    91  			Handler:          http2Handler{h},
    92  			BaseConfig:       http2ServerConfig{hs},
    93  			SawClientPreface: true,
    94  		})
    95  	}
    96  
    97  	s.h2 = h2srv
    98  }
    99  
   100  func serveHTTP2Conn(ctx context.Context, c *conn, h Handler) bool {
   101  	if c.server.h2 == nil {
   102  		return false
   103  	}
   104  	c.server.h2.ServeConn(c.rwc, &http2.ServeConnOpts{
   105  		Context:          ctx,
   106  		Handler:          http2Handler{h},
   107  		BaseConfig:       http2ServerConfig{c.server},
   108  		SawClientPreface: true,
   109  	})
   110  	return true
   111  }
   112  
   113  type http2Handler struct {
   114  	h Handler
   115  }
   116  
   117  func (h http2Handler) ServeHTTP(w *http2.ResponseWriter, req *http2.ServerRequest) {
   118  	h.h.ServeHTTP(http2ResponseWriter{w}, &Request{
   119  		ctx:           req.Context,
   120  		Proto:         "HTTP/2.0",
   121  		ProtoMajor:    2,
   122  		ProtoMinor:    0,
   123  		Method:        req.Method,
   124  		URL:           req.URL,
   125  		Header:        Header(req.Header),
   126  		RequestURI:    req.RequestURI,
   127  		Trailer:       Header(req.Trailer),
   128  		Body:          req.Body,
   129  		Host:          req.Host,
   130  		ContentLength: req.ContentLength,
   131  		RemoteAddr:    req.RemoteAddr,
   132  		TLS:           req.TLS,
   133  		MultipartForm: req.MultipartForm,
   134  	})
   135  }
   136  
   137  type http2ResponseWriter struct {
   138  	*http2.ResponseWriter
   139  }
   140  
   141  // Optional http.ResponseWriter interfaces implemented.
   142  var (
   143  	_ CloseNotifier   = http2ResponseWriter{}
   144  	_ Flusher         = http2ResponseWriter{}
   145  	_ io.StringWriter = http2ResponseWriter{}
   146  )
   147  
   148  func (w http2ResponseWriter) Flush()            { w.ResponseWriter.FlushError() }
   149  func (w http2ResponseWriter) FlushError() error { return w.ResponseWriter.FlushError() }
   150  
   151  func (w http2ResponseWriter) Header() Header { return Header(w.ResponseWriter.Header()) }
   152  
   153  func (w http2ResponseWriter) Push(target string, opts *PushOptions) error {
   154  	var (
   155  		method string
   156  		header http2.Header
   157  	)
   158  	if opts != nil {
   159  		method = opts.Method
   160  		header = http2.Header(opts.Header)
   161  	}
   162  	err := w.ResponseWriter.Push(target, method, header)
   163  	if err == http2.ErrNotSupported {
   164  		err = ErrNotSupported
   165  	}
   166  	return err
   167  }
   168  
   169  type http2ServerConfig struct {
   170  	s *Server
   171  }
   172  
   173  func (s http2ServerConfig) MaxHeaderBytes() int { return s.s.MaxHeaderBytes }
   174  func (s http2ServerConfig) ConnState(c net.Conn, st http2.ConnState) {
   175  	if s.s.ConnState != nil {
   176  		s.s.ConnState(c, ConnState(st))
   177  	}
   178  }
   179  func (s http2ServerConfig) DoKeepAlives() bool             { return s.s.doKeepAlives() }
   180  func (s http2ServerConfig) WriteTimeout() time.Duration    { return s.s.WriteTimeout }
   181  func (s http2ServerConfig) SendPingTimeout() time.Duration { return s.s.ReadTimeout }
   182  func (s http2ServerConfig) ErrorLog() *log.Logger          { return s.s.ErrorLog }
   183  func (s http2ServerConfig) IdleTimeout() time.Duration     { return s.s.IdleTimeout }
   184  func (s http2ServerConfig) ReadTimeout() time.Duration     { return s.s.ReadTimeout }
   185  func (s http2ServerConfig) DisableClientPriority() bool    { return s.s.DisableClientPriority }
   186  func (s http2ServerConfig) HTTP2Config() http2.Config {
   187  	if s.s.HTTP2 == nil {
   188  		return http2.Config{}
   189  	}
   190  	return (http2.Config)(*s.s.HTTP2)
   191  }
   192  
   193  func (t *Transport) configureHTTP2(protocols Protocols) {
   194  	if t.TLSClientConfig == nil {
   195  		t.TLSClientConfig = &tls.Config{}
   196  	}
   197  	if t.HTTP2 == nil {
   198  		t.HTTP2 = &HTTP2Config{}
   199  	}
   200  	t2 := http2.NewTransport(transportConfig{t})
   201  	t2.AllowHTTP = true
   202  	t.h2transport = t2
   203  
   204  	t.registerProtocol("https", http2RoundTripper{t2, true})
   205  	if t.TLSNextProto == nil {
   206  		t.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) RoundTripper)
   207  	}
   208  	t.TLSNextProto["h2"] = func(authority string, c *tls.Conn) RoundTripper {
   209  		err := t2.AddConn("https", authority, c)
   210  		if err != nil {
   211  			return http2ErringRoundTripper{err}
   212  		}
   213  		return http2RoundTripper{t2, false}
   214  	}
   215  	t.TLSNextProto[nextProtoUnencryptedHTTP2] = func(authority string, c *tls.Conn) RoundTripper {
   216  		unencrypted, ok := c.NetConn().(unencryptedNetConnInTLSConn)
   217  		if !ok {
   218  			return http2ErringRoundTripper{errors.New("http: *tls.Conn expected to wrap an unencrypted conn, but does not (BUG)")}
   219  		}
   220  		err := t2.AddConn("http", authority, unencrypted.conn)
   221  		if err != nil {
   222  			return http2ErringRoundTripper{err}
   223  		}
   224  		return http2RoundTripper{t2, false}
   225  	}
   226  
   227  	// Auto-configure the http2.Transport's MaxHeaderListSize from
   228  	// the http.Transport's MaxResponseHeaderBytes. They don't
   229  	// exactly mean the same thing, but they're close.
   230  	if limit1 := t.MaxResponseHeaderBytes; limit1 != 0 && t2.MaxHeaderListSize == 0 {
   231  		const h2max = 1<<32 - 1
   232  		if limit1 >= h2max {
   233  			t2.MaxHeaderListSize = h2max
   234  		} else {
   235  			t2.MaxHeaderListSize = uint32(limit1)
   236  		}
   237  	}
   238  
   239  	// Server.ServeTLS clones the tls.Config before modifying it.
   240  	// Transport doesn't. We may want to make the two consistent some day.
   241  	//
   242  	// http2configureTransport will have already set NextProtos, but adjust it again
   243  	// here to remove HTTP/1.1 if the user has disabled it.
   244  	t.TLSClientConfig.NextProtos = adjustNextProtos(t.TLSClientConfig.NextProtos, protocols)
   245  }
   246  
   247  type http2ErringRoundTripper struct{ err error }
   248  
   249  func (rt http2ErringRoundTripper) RoundTripErr() error                   { return rt.err }
   250  func (rt http2ErringRoundTripper) RoundTrip(*Request) (*Response, error) { return nil, rt.err }
   251  
   252  func http2RoundTrip(req *Request, rt func(*http2.ClientRequest) (*http2.ClientResponse, error)) (*Response, error) {
   253  	resp := &Response{}
   254  	cresp, err := rt(&http2.ClientRequest{
   255  		Context:       req.Context(),
   256  		Method:        req.Method,
   257  		URL:           req.URL,
   258  		Header:        http2.Header(req.Header),
   259  		Trailer:       http2.Header(req.Trailer),
   260  		Body:          req.Body,
   261  		Host:          req.Host,
   262  		GetBody:       req.GetBody,
   263  		ContentLength: req.ContentLength,
   264  		Cancel:        req.Cancel,
   265  		Close:         req.Close,
   266  		ResTrailer:    (*http2.Header)(&resp.Trailer),
   267  	})
   268  	if err != nil {
   269  		return nil, err
   270  	}
   271  	resp.Status = cresp.Status + " " + StatusText(cresp.StatusCode)
   272  	resp.StatusCode = cresp.StatusCode
   273  	resp.Proto = "HTTP/2.0"
   274  	resp.ProtoMajor = 2
   275  	resp.ProtoMinor = 0
   276  	resp.ContentLength = cresp.ContentLength
   277  	resp.Uncompressed = cresp.Uncompressed
   278  	resp.Header = Header(cresp.Header)
   279  	resp.Trailer = Header(cresp.Trailer)
   280  	resp.Body = cresp.Body
   281  	resp.TLS = cresp.TLS
   282  	resp.Request = req
   283  	return resp, nil
   284  }
   285  
   286  type http2RoundTripper struct {
   287  	t                *http2.Transport
   288  	mapCachedConnErr bool
   289  }
   290  
   291  func (rt http2RoundTripper) RoundTrip(req *Request) (*Response, error) {
   292  	resp, err := http2RoundTrip(req, rt.t.RoundTrip)
   293  	if err != nil {
   294  		if rt.mapCachedConnErr && http2isNoCachedConnError(err) {
   295  			err = ErrSkipAltProtocol
   296  		}
   297  		return nil, err
   298  	}
   299  	return resp, nil
   300  }
   301  
   302  func (rt http2RoundTripper) NewClientConn(nc net.Conn, internalStateHook func()) (RoundTripper, error) {
   303  	cc, err := rt.t.NewClientConn(nc, internalStateHook)
   304  	if err != nil {
   305  		return nil, err
   306  	}
   307  	return http2ClientConn{cc}, nil
   308  }
   309  
   310  type http2ClientConn struct {
   311  	http2.NetHTTPClientConn
   312  }
   313  
   314  func (cc http2ClientConn) RoundTrip(req *Request) (*Response, error) {
   315  	return http2RoundTrip(req, cc.NetHTTPClientConn.RoundTrip)
   316  }
   317  
   318  type transportConfig struct {
   319  	t *Transport
   320  }
   321  
   322  func (t transportConfig) MaxResponseHeaderBytes() int64        { return t.t.MaxResponseHeaderBytes }
   323  func (t transportConfig) DisableCompression() bool             { return t.t.DisableCompression }
   324  func (t transportConfig) DisableKeepAlives() bool              { return t.t.DisableKeepAlives }
   325  func (t transportConfig) ExpectContinueTimeout() time.Duration { return t.t.ExpectContinueTimeout }
   326  func (t transportConfig) ResponseHeaderTimeout() time.Duration { return t.t.ResponseHeaderTimeout }
   327  func (t transportConfig) IdleConnTimeout() time.Duration       { return t.t.IdleConnTimeout }
   328  
   329  func (t transportConfig) HTTP2Config() http2.Config {
   330  	return *(*http2.Config)(t.t.HTTP2)
   331  }
   332  
   333  // transportFromH1Transport provides a way for HTTP/2 tests to extract
   334  // the http2.Transport from an http.Transport.
   335  //
   336  //go:linkname transportFromH1Transport net/http/internal/http2_test.transportFromH1Transport
   337  func transportFromH1Transport(t *Transport) any {
   338  	t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
   339  	return t.h2transport
   340  }
   341  

View as plain text