package http
import (
_
)
func () {
http2.LocalAddrContextKey = LocalAddrContextKey
http2.NoBody = NoBody
}
type http2Server = http2.Server
type http2Transport = http2.Transport
func ( *Server) () {
:= &http2.Server{}
if .IdleTimeout != 0 {
.h2IdleTimeout = .IdleTimeout
} else {
.h2IdleTimeout = .ReadTimeout
}
if .TLSConfig == nil {
.TLSConfig = &tls.Config{}
}
.nextProtoErr = .Configure(http2ServerConfig{}, .TLSConfig)
if .nextProtoErr != nil {
return
}
.RegisterOnShutdown(.GracefulShutdown)
if .TLSNextProto == nil {
.TLSNextProto = make(map[string]func(*Server, *tls.Conn, Handler))
}
.TLSNextProto["h2"] = func( *Server, *tls.Conn, Handler) {
.Close()
}
.h2 =
}
func ( *Server) ( http2ExternalServerConfig) {
if .h2Config != nil {
panic("http: HTTP/2 Server already registered")
}
.h2Config =
.h2Config.ServeConnFunc(.serveHTTP2Conn)
.configureHTTP2()
}
func ( *Server) ( context.Context, net.Conn, Handler, bool, *Request, []byte) {
.setupHTTP2_ServeTLS()
var *http2.ServerRequest
if != nil {
= http2ServerRequestFromRequest()
}
.SetReadDeadline(time.Time{})
.SetWriteDeadline(time.Time{})
.h2.ServeConn(, &http2.ServeConnOpts{
Context: ,
Handler: http2Handler{},
BaseConfig: http2ServerConfig{},
SawClientPreface: ,
UpgradeRequest: ,
Settings: ,
})
}
func ( *Request) *http2.ServerRequest {
return &http2.ServerRequest{
Context: .Context(),
Proto: .Proto,
ProtoMajor: .ProtoMajor,
ProtoMinor: .ProtoMinor,
Method: .Method,
URL: .URL,
Header: http2.Header(.Header),
Trailer: http2.Header(.Trailer),
Body: .Body,
Host: .Host,
ContentLength: .ContentLength,
RemoteAddr: .RemoteAddr,
RequestURI: .RequestURI,
TLS: .TLS,
MultipartForm: .MultipartForm,
}
}
type http2Handler struct {
h Handler
}
func ( http2Handler) ( *http2.ResponseWriter, *http2.ServerRequest) {
.h.ServeHTTP(http2ResponseWriter{}, &Request{
ctx: .Context,
Proto: "HTTP/2.0",
ProtoMajor: 2,
ProtoMinor: 0,
Method: .Method,
URL: .URL,
Header: Header(.Header),
RequestURI: .RequestURI,
Trailer: Header(.Trailer),
Body: .Body,
Host: .Host,
ContentLength: .ContentLength,
RemoteAddr: .RemoteAddr,
TLS: .TLS,
MultipartForm: .MultipartForm,
})
}
type http2ResponseWriter struct {
*http2.ResponseWriter
}
var (
_ CloseNotifier = http2ResponseWriter{}
_ Flusher = http2ResponseWriter{}
_ io.StringWriter = http2ResponseWriter{}
)
func ( http2ResponseWriter) () { .ResponseWriter.FlushError() }
func ( http2ResponseWriter) () error { return .ResponseWriter.FlushError() }
func ( http2ResponseWriter) () Header { return Header(.ResponseWriter.Header()) }
func ( http2ResponseWriter) ( string, *PushOptions) error {
var (
string
http2.Header
)
if != nil {
= .Method
= http2.Header(.Header)
}
:= .ResponseWriter.Push(, , )
if == http2.ErrNotSupported {
= ErrNotSupported
}
return
}
type http2ServerConfig struct {
s *Server
}
func ( http2ServerConfig) () int { return .s.MaxHeaderBytes }
func ( http2ServerConfig) () int { return .s.maxHeaderValueCount() }
func ( http2ServerConfig) ( net.Conn, http2.ConnState) {
if .s.ConnState != nil {
.s.ConnState(, ConnState())
}
}
func ( http2ServerConfig) () bool { return .s.doKeepAlives() }
func ( http2ServerConfig) () time.Duration { return .s.WriteTimeout }
func ( http2ServerConfig) () time.Duration { return .s.ReadTimeout }
func ( http2ServerConfig) () *log.Logger { return .s.ErrorLog }
func ( http2ServerConfig) () time.Duration { return .s.ReadTimeout }
func ( http2ServerConfig) () bool { return .s.DisableClientPriority }
func ( http2ServerConfig) () time.Duration {
if .s.h2Config != nil {
return .s.h2Config.IdleTimeout()
}
return .s.h2IdleTimeout
}
func ( http2ServerConfig) () http2.Config {
return mergeHTTP2Config(.s.HTTP2, .s.h2Config)
}
type http2ExternalServerConfig interface {
HTTP2Config() HTTP2Config
IdleTimeout() time.Duration
ServeConnFunc(func(ctx context.Context, nc net.Conn, h Handler, sawClientPreface bool, upgradeReq *Request, settings []byte))
}
type http2ExternalTransportConfig interface {
HTTP2Config() HTTP2Config
DisableCompression() bool
MaxHeaderListSize() int64
IdleConnTimeout() time.Duration
ConnFromContext(context.Context) net.Conn
DialFromContext(ctx context.Context, network, addr string) (net.Conn, error)
ExternalRoundTrip() bool
RoundTrip(*Request) (*Response, error)
Registered(*Transport)
}
func ( *Transport) ( Protocols) {
if .TLSClientConfig == nil {
.TLSClientConfig = &tls.Config{}
}
if .HTTP2 == nil {
.HTTP2 = &HTTP2Config{}
}
:= http2.NewTransport(transportConfig{})
.h2Transport =
.registerProtocol("https", http2RoundTripper{, true})
if .TLSNextProto == nil {
.TLSNextProto = make(map[string]func( string, *tls.Conn) RoundTripper)
}
.TLSNextProto["h2"] = func( string, *tls.Conn) RoundTripper {
return http2ErringRoundTripper{
errors.New("unexpected use of stub RoundTripper"),
}
}
.TLSClientConfig.NextProtos = adjustNextProtos(.TLSClientConfig.NextProtos, )
}
type http2ErringRoundTripper struct{ err error }
func ( http2ErringRoundTripper) () error { return .err }
func ( http2ErringRoundTripper) (*Request) (*Response, error) { return nil, .err }
func ( *Request, func(*http2.ClientRequest) (*http2.ClientResponse, error)) (*Response, error) {
:= &Response{}
, := (&http2.ClientRequest{
Context: .Context(),
Method: .Method,
URL: .URL,
Header: http2.Header(.Header),
Trailer: http2.Header(.Trailer),
Body: .Body,
Host: .Host,
GetBody: .GetBody,
ContentLength: .ContentLength,
Cancel: .Cancel,
Close: .Close,
ResTrailer: (*http2.Header)(&.Trailer),
})
if != nil {
return nil,
}
.Status = .Status + " " + StatusText(.StatusCode)
.StatusCode = .StatusCode
.Proto = "HTTP/2.0"
.ProtoMajor = 2
.ProtoMinor = 0
.ContentLength = .ContentLength
.Uncompressed = .Uncompressed
.Header = Header(.Header)
.Trailer = Header(.Trailer)
.Body = .Body
.TLS = .TLS
.Request =
return , nil
}
func ( *Transport) (, string, net.Conn) (RoundTripper, error) {
if .h2Transport == nil {
return nil, errors.ErrUnsupported
}
:= .h2Transport.AddConn(, , )
if != nil {
return nil,
}
return http2RoundTripper{.h2Transport, false}, nil
}
func ( *Transport) ( net.Conn, func()) (genericClientConn, error) {
if .h2Transport == nil {
return nil, errors.ErrUnsupported
}
, := .h2Transport.NewClientConn(, )
if != nil {
return nil,
}
return http2ClientConn{}, nil
}
func ( *Transport) ( context.Context) (*ClientConn, error) {
if .h2Config == nil {
return nil, errors.ErrUnsupported
}
:= .h2Config.ConnFromContext()
if == nil {
return nil, errors.ErrUnsupported
}
if .h2Transport == nil {
return nil, errors.New("http: Transport does not support HTTP/2")
}
:= &ClientConn{}
, := .http2NewClientConn(, .maybeRunStateHook)
if != nil {
return nil,
}
.stateHookMu.Lock()
defer .stateHookMu.Unlock()
.cc =
.lastAvailable = .Available()
return , nil
}
func ( *Transport) ( context.Context, connectMethod) (RoundTripper, error) {
if .h2Config == nil {
return nil, errors.ErrUnsupported
}
, := .h2Config.DialFromContext(, "tcp", .targetAddr)
if != nil {
return nil,
}
return .http2AddConn(.targetScheme, .targetAddr, )
}
type http2RoundTripper struct {
t *http2.Transport
mapCachedConnErr bool
}
func ( http2RoundTripper) ( *Request) (*Response, error) {
, := http2RoundTrip(, .t.RoundTrip)
if != nil {
if .mapCachedConnErr && http2isNoCachedConnError() {
= ErrSkipAltProtocol
}
return nil,
}
return , nil
}
type http2ClientConn struct {
http2.NetHTTPClientConn
}
func ( http2ClientConn) ( *Request) (*Response, error) {
return http2RoundTrip(, .NetHTTPClientConn.RoundTrip)
}
type transportConfig struct {
t *Transport
}
func ( transportConfig) () int64 { return .t.MaxResponseHeaderBytes }
func ( transportConfig) () bool { return .t.DisableKeepAlives }
func ( transportConfig) () time.Duration { return .t.ExpectContinueTimeout }
func ( transportConfig) () time.Duration { return .t.ResponseHeaderTimeout }
func ( transportConfig) () int64 {
if .t.h2Config != nil {
return .t.h2Config.MaxHeaderListSize()
}
return 0
}
func ( transportConfig) () bool {
if .t.h2Config != nil && .t.h2Config.DisableCompression() {
return true
}
return .t.DisableCompression
}
func ( transportConfig) () time.Duration {
if .t.h2Config != nil {
if := .t.h2Config.IdleConnTimeout(); != 0 {
return
}
}
return .t.IdleConnTimeout
}
type http2Configer interface {
HTTP2Config() HTTP2Config
}
func ( *HTTP2Config, http2Configer) http2.Config {
if == nil && == nil {
return http2.Config{}
}
var http2.Config
if != nil {
= (http2.Config)(*)
}
var HTTP2Config
if != nil {
= .HTTP2Config()
}
if .MaxConcurrentStreams == 0 {
.MaxConcurrentStreams = .MaxConcurrentStreams
}
if .StrictMaxConcurrentRequests {
.StrictMaxConcurrentRequests = true
}
if .MaxDecoderHeaderTableSize == 0 {
.MaxDecoderHeaderTableSize = .MaxDecoderHeaderTableSize
}
if .MaxEncoderHeaderTableSize == 0 {
.MaxEncoderHeaderTableSize = .MaxEncoderHeaderTableSize
}
if .MaxReadFrameSize == 0 {
.MaxReadFrameSize = .MaxReadFrameSize
}
if .MaxReceiveBufferPerConnection == 0 {
.MaxReceiveBufferPerConnection = .MaxReceiveBufferPerConnection
}
if .MaxReceiveBufferPerStream == 0 {
.MaxReceiveBufferPerStream = .MaxReceiveBufferPerStream
}
if .SendPingTimeout == 0 {
.SendPingTimeout = .SendPingTimeout
}
if .PingTimeout == 0 {
.PingTimeout = .PingTimeout
}
if .WriteByteTimeout == 0 {
.WriteByteTimeout = .WriteByteTimeout
}
if .PermitProhibitedCipherSuites {
.PermitProhibitedCipherSuites = true
}
if .CountError == nil {
.CountError = .CountError
}
return
}
func ( transportConfig) () http2.Config {
return mergeHTTP2Config(.t.HTTP2, .t.h2Config)
}
func ( *Transport) any {
.nextProtoOnce.Do(.onceSetNextProtoDefaults)
return .h2Transport
}