touka/http2xconnect.go

88 lines
2.5 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
// Copyright 2026 WJQSERVER. All rights reserved.
// All rights reserved by WJQSERVER, related rights can be exercised by the infinite-iroha organization.
package touka
import (
"crypto/tls"
"net"
"net/http"
"sync"
"time"
_ "unsafe"
"golang.org/x/net/http2"
)
var enableHTTP2ExtendedConnectOnce sync.Once
//go:linkname xnetDisableHTTP2ExtendedConnectProtocol golang.org/x/net/http2.disableExtendedConnectProtocol
var xnetDisableHTTP2ExtendedConnectProtocol bool
func enableHTTP2ExtendedConnectProtocol() {
enableHTTP2ExtendedConnectOnce.Do(func() {
xnetDisableHTTP2ExtendedConnectProtocol = false
})
}
func configureHTTP2ExtendedConnectServer(srv *http.Server) error {
if srv == nil {
return nil
}
enableHTTP2ExtendedConnectProtocol()
return http2.ConfigureServer(srv, nil)
}
func newHTTP2ExtendedConnectTransport() http.RoundTripper {
enableHTTP2ExtendedConnectProtocol()
transport := cloneDefaultTransport()
transport.Protocols = new(http.Protocols)
transport.Protocols.SetHTTP1(true)
transport.Protocols.SetHTTP2(true)
return transport
}
func newHTTP1BridgeTransport() http.RoundTripper {
return newHTTP1BridgeTransportWithTLSConfig(&tls.Config{NextProtos: []string{"http/1.1"}})
}
func newHTTP1BridgeTransportWithTLSConfig(tlsConfig *tls.Config) http.RoundTripper {
transport := cloneDefaultTransport()
transport.Protocols = new(http.Protocols)
transport.Protocols.SetHTTP1(true)
if tlsConfig == nil {
transport.TLSClientConfig = &tls.Config{}
} else {
transport.TLSClientConfig = tlsConfig.Clone()
}
if len(transport.TLSClientConfig.NextProtos) == 0 {
transport.TLSClientConfig.NextProtos = []string{"http/1.1"}
}
return transport
}
func newH2CTransport() http.RoundTripper {
transport := cloneDefaultTransport()
transport.Protocols = new(http.Protocols)
transport.Protocols.SetUnencryptedHTTP2(true)
return transport
}
func cloneDefaultTransport() *http.Transport {
if transport, ok := http.DefaultTransport.(*http.Transport); ok {
return transport.Clone()
}
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}