http2_transport.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package httpclient
  2. import (
  3. "context"
  4. stdTLS "crypto/tls"
  5. "net"
  6. "net/http"
  7. "github.com/sagernet/sing-box/common/tls"
  8. "github.com/sagernet/sing-box/option"
  9. M "github.com/sagernet/sing/common/metadata"
  10. N "github.com/sagernet/sing/common/network"
  11. "golang.org/x/net/http2"
  12. )
  13. type http2Transport struct {
  14. h2Transport *http2.Transport
  15. h1Transport *http1Transport
  16. }
  17. func newHTTP2Transport(rawDialer N.Dialer, baseTLSConfig tls.Config, options option.HTTP2Options) (*http2Transport, error) {
  18. h1 := newHTTP1Transport(rawDialer, baseTLSConfig)
  19. h2Transport, err := ConfigureHTTP2Transport(options)
  20. if err != nil {
  21. return nil, err
  22. }
  23. h2Transport.DialTLSContext = func(ctx context.Context, network, addr string, _ *stdTLS.Config) (net.Conn, error) {
  24. return dialTLS(ctx, rawDialer, baseTLSConfig, M.ParseSocksaddr(addr), []string{http2.NextProtoTLS}, http2.NextProtoTLS)
  25. }
  26. return &http2Transport{
  27. h2Transport: h2Transport,
  28. h1Transport: h1,
  29. }, nil
  30. }
  31. func (t *http2Transport) RoundTrip(request *http.Request) (*http.Response, error) {
  32. if request.URL.Scheme != "https" || requestRequiresHTTP1(request) {
  33. return t.h1Transport.RoundTrip(request)
  34. }
  35. return t.h2Transport.RoundTrip(request)
  36. }
  37. func (t *http2Transport) CloseIdleConnections() {
  38. t.h1Transport.CloseIdleConnections()
  39. t.h2Transport.CloseIdleConnections()
  40. }
  41. func (t *http2Transport) Close() error {
  42. t.CloseIdleConnections()
  43. return nil
  44. }