1
0
mirror of https://github.com/fumiama/terasu.git synced 2026-06-08 20:10:37 +08:00

feat: add plugin

This commit is contained in:
源文雨
2026-02-16 15:20:45 +08:00
parent f6d5336492
commit 1d573cf2be
14 changed files with 234 additions and 295 deletions

View File

@@ -2,96 +2,18 @@
package http2
import (
"context"
"crypto/tls"
"errors"
"io"
"net"
"net/http"
"net/url"
"time"
"golang.org/x/net/http2"
"github.com/fumiama/terasu"
"github.com/fumiama/terasu/dns"
"golang.org/x/net/http2"
)
// ErrEmptyHostAddress is returned when DNS lookup for a host returns no addresses
var ErrEmptyHostAddress = errors.New("empty host addr")
// defaultDialer is the default dialer used for establishing TCP connections
var defaultDialer = net.Dialer{
Timeout: 10 * time.Second,
}
// SetDefaultClientTimeout sets the default timeout for all HTTP2 client connections
func SetDefaultClientTimeout(t time.Duration) {
defaultDialer.Timeout = t
}
// DefaultClient is the default HTTP2 client that supports HTTP/2 and DNS resolution
var DefaultClient = http.Client{
Transport: &http2.Transport{
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
addrs, err := dns.LookupHost(ctx, host)
if err != nil {
return nil, err
}
if len(addrs) == 0 {
return nil, ErrEmptyHostAddress
}
var conn net.Conn
var tlsConn *tls.Conn
for _, a := range addrs {
if defaultDialer.Timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), defaultDialer.Timeout)
defer cancel()
} else if !defaultDialer.Deadline.IsZero() {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(context.Background(), defaultDialer.Deadline)
defer cancel()
}
conn, err = defaultDialer.DialContext(ctx, network, net.JoinHostPort(a, port))
if err != nil {
continue
}
tlsConn = tls.Client(terasu.NewConn(conn), cfg)
// re-init ctx due to deadline settings in tcp dial
if defaultDialer.Timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(context.Background(), defaultDialer.Timeout)
defer cancel()
} else if !defaultDialer.Deadline.IsZero() {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(context.Background(), defaultDialer.Deadline)
defer cancel()
}
err = tlsConn.HandshakeContext(ctx)
if err == nil {
break
}
_ = tlsConn.Close()
tlsConn = nil
conn, err = defaultDialer.DialContext(ctx, network, net.JoinHostPort(a, port))
if err != nil {
continue
}
tlsConn = tls.Client(terasu.NewConn(conn), cfg)
err = tlsConn.HandshakeContext(ctx)
if err == nil {
break
}
_ = tlsConn.Close()
tlsConn = nil
}
return tlsConn, err
},
DialTLSContext: dns.DialTLSContextWithConfig,
},
}