Source file src/net/http/http2server.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 && !nethttpomithttp2server
     6  
     7  package http
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"io"
    13  	"log"
    14  	"net"
    15  	"net/http/internal/http2"
    16  	"time"
    17  )
    18  
    19  // This file connects the net/http Server to the HTTP/2 server
    20  // in the net/http/internal/http2 package. It is omitted when
    21  // the nethttpomithttp2 or nethttpomithttp2server build tag is set.
    22  
    23  const omitHTTP2Server = false
    24  
    25  type http2Server = http2.Server
    26  
    27  func (s *Server) configureHTTP2() {
    28  	h2srv := &http2.Server{}
    29  
    30  	// Historically, we've configured the HTTP/2 idle timeout in this fashion:
    31  	// Set once at configuration time.
    32  	if s.IdleTimeout != 0 {
    33  		s.h2IdleTimeout = s.IdleTimeout
    34  	} else {
    35  		s.h2IdleTimeout = s.ReadTimeout
    36  	}
    37  
    38  	if s.TLSConfig == nil {
    39  		s.TLSConfig = &tls.Config{}
    40  	}
    41  	s.nextProtoErr = h2srv.Configure(http2ServerConfig{s}, s.TLSConfig)
    42  	if s.nextProtoErr != nil {
    43  		return
    44  	}
    45  
    46  	s.RegisterOnShutdown(h2srv.GracefulShutdown)
    47  
    48  	if s.TLSNextProto == nil {
    49  		s.TLSNextProto = make(map[string]func(*Server, *tls.Conn, Handler))
    50  	}
    51  	// Historically, the presence of a TLSNextProto["h2"] key has been the signal to
    52  	// enable/disable HTTP/2 support. Set a value in the map, but we'll never use it.
    53  	s.TLSNextProto["h2"] = func(hs *Server, c *tls.Conn, h Handler) {
    54  		c.Close()
    55  	}
    56  
    57  	s.h2 = h2srv
    58  }
    59  
    60  func (s *Server) setHTTP2Config(conf http2ExternalServerConfig) {
    61  	if s.h2Config != nil {
    62  		panic("http: HTTP/2 Server already registered")
    63  	}
    64  	s.h2Config = conf
    65  	s.h2Config.ServeConnFunc(func(ctx context.Context, nc net.Conn, h Handler, sawClientPreface bool, upgradeReq *Request, settings []byte) {
    66  		s.serveHTTP2Conn(ctx, nc, h, sawClientPreface, upgradeReq, settings, nil)
    67  	})
    68  	s.configureHTTP2()
    69  }
    70  
    71  // serveHTTP2Conn serves nc with the HTTP/2 server. It may return before the
    72  // connection is done being served (an idle HTTP/2 connection doesn't hold
    73  // onto a goroutine); onClose, if non-nil, runs once the connection is done
    74  // and has been closed.
    75  func (s *Server) serveHTTP2Conn(ctx context.Context, nc net.Conn, h Handler, sawClientPreface bool, upgradeReq *Request, settings []byte, onClose func()) {
    76  	s.setupHTTP2_ServeTLS()
    77  	var serverUpgradeReq *http2.ServerRequest
    78  	if upgradeReq != nil {
    79  		serverUpgradeReq = http2ServerRequestFromRequest(upgradeReq)
    80  	}
    81  	nc.SetReadDeadline(time.Time{})
    82  	nc.SetWriteDeadline(time.Time{})
    83  	s.h2.ServeConn(nc, &http2.ServeConnOpts{
    84  		Context:          ctx,
    85  		Handler:          http2Handler{h},
    86  		BaseConfig:       http2ServerConfig{s},
    87  		SawClientPreface: sawClientPreface,
    88  		UpgradeRequest:   serverUpgradeReq,
    89  		Settings:         settings,
    90  		OnClose:          onClose,
    91  	})
    92  }
    93  
    94  func http2ServerRequestFromRequest(req *Request) *http2.ServerRequest {
    95  	return &http2.ServerRequest{
    96  		Context:       req.Context(),
    97  		Proto:         req.Proto,
    98  		ProtoMajor:    req.ProtoMajor,
    99  		ProtoMinor:    req.ProtoMinor,
   100  		Method:        req.Method,
   101  		URL:           req.URL,
   102  		Header:        http2.Header(req.Header),
   103  		Trailer:       http2.Header(req.Trailer),
   104  		Body:          req.Body,
   105  		Host:          req.Host,
   106  		ContentLength: req.ContentLength,
   107  		RemoteAddr:    req.RemoteAddr,
   108  		RequestURI:    req.RequestURI,
   109  		TLS:           req.TLS,
   110  	}
   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  	})
   134  }
   135  
   136  type http2ResponseWriter struct {
   137  	*http2.ResponseWriter
   138  }
   139  
   140  // Optional http.ResponseWriter interfaces implemented.
   141  var (
   142  	_ CloseNotifier   = http2ResponseWriter{}
   143  	_ Flusher         = http2ResponseWriter{}
   144  	_ io.StringWriter = http2ResponseWriter{}
   145  )
   146  
   147  func (w http2ResponseWriter) Flush()            { w.ResponseWriter.FlushError() }
   148  func (w http2ResponseWriter) FlushError() error { return w.ResponseWriter.FlushError() }
   149  
   150  func (w http2ResponseWriter) Header() Header { return Header(w.ResponseWriter.Header()) }
   151  
   152  func (w http2ResponseWriter) Push(target string, opts *PushOptions) error {
   153  	var (
   154  		method string
   155  		header http2.Header
   156  	)
   157  	if opts != nil {
   158  		method = opts.Method
   159  		header = http2.Header(opts.Header)
   160  	}
   161  	err := w.ResponseWriter.Push(target, method, header)
   162  	if err == http2.ErrNotSupported {
   163  		err = ErrNotSupported
   164  	}
   165  	return err
   166  }
   167  
   168  type http2ServerConfig struct {
   169  	s *Server
   170  }
   171  
   172  func (s http2ServerConfig) MaxHeaderBytes() int      { return s.s.MaxHeaderBytes }
   173  func (s http2ServerConfig) MaxHeaderValueCount() int { return s.s.maxHeaderValueCount() }
   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) ReadTimeout() time.Duration     { return s.s.ReadTimeout }
   184  func (s http2ServerConfig) DisableClientPriority() bool    { return s.s.DisableClientPriority }
   185  
   186  func (s http2ServerConfig) IdleTimeout() time.Duration {
   187  	if s.s.h2Config != nil {
   188  		return s.s.h2Config.IdleTimeout()
   189  	}
   190  	return s.s.h2IdleTimeout
   191  }
   192  
   193  func (s http2ServerConfig) HTTP2Config() http2.Config {
   194  	return mergeHTTP2Config(s.s.HTTP2, s.s.h2Config)
   195  }
   196  
   197  // http2ExternalServerConfig is an HTTP/2 configuration provided by x/net/http2.
   198  //
   199  // When a x/net/http2.Server wraps a net/http.Server, we need to support the user
   200  // setting configuration settings on the x/net Server:
   201  //
   202  //	s1 := &http.Server{}
   203  //	s2 := &http2.Server{}
   204  //	http2.ConfigureServer(s1, s2)
   205  //
   206  //	// This setting needs to affect s1:
   207  //	s2.MaxReadFrameSize = 10000
   208  //
   209  // We handle this by having http2.ConfigureServer pass us an http2ExternalServerConfig
   210  // (see http.Server.Serve) which we can use to query the current state of the http2.Server.
   211  type http2ExternalServerConfig interface {
   212  	// Various configuration settings:
   213  	HTTP2Config() HTTP2Config
   214  	IdleTimeout() time.Duration
   215  
   216  	// ServeConnFunc provides a function to the x/net/http2.Server which it
   217  	// can use to serve a new connection.
   218  	ServeConnFunc(func(ctx context.Context, nc net.Conn, h Handler, sawClientPreface bool, upgradeReq *Request, settings []byte))
   219  }
   220  

View as plain text