Skip to content

Commit 0aacee3

Browse files
committed
🦟 internal/httpreq: add DefaultHttpTransportClone
Moved from producer/ipapi for shared use.
1 parent 99718d9 commit 0aacee3

2 files changed

Lines changed: 27 additions & 21 deletions

File tree

internal/httpreq/httpreq.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"encoding/json"
77
"fmt"
88
"io"
9+
"net"
910
"net/http"
1011
"net/url"
1112
"strings"
13+
"time"
1214

1315
ddnsgo "github.com/database64128/ddns-go"
1416
)
@@ -75,3 +77,26 @@ func ReadResponseBody(buf *bytes.Buffer, resp *http.Response, maxSize int64) err
7577
}
7678
return nil
7779
}
80+
81+
// DefaultHttpTransportClone returns a clone of [http.DefaultTransport] if possible,
82+
// or a best-effort approximation of the original if it has been changed by user code
83+
// to a custom implementation.
84+
func DefaultHttpTransportClone() *http.Transport {
85+
transport, ok := http.DefaultTransport.(*http.Transport)
86+
if !ok {
87+
dialer := net.Dialer{
88+
Timeout: 30 * time.Second,
89+
KeepAlive: 30 * time.Second,
90+
}
91+
return &http.Transport{
92+
Proxy: http.ProxyFromEnvironment,
93+
DialContext: dialer.DialContext,
94+
ForceAttemptHTTP2: true,
95+
MaxIdleConns: 100,
96+
IdleConnTimeout: 90 * time.Second,
97+
TLSHandshakeTimeout: 10 * time.Second,
98+
ExpectContinueTimeout: 1 * time.Second,
99+
}
100+
}
101+
return transport.Clone()
102+
}

producer/ipapi/text.go

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"net/http"
99
"net/netip"
1010
"sync"
11-
"time"
1211

1312
"github.com/database64128/ddns-go/internal/httpreq"
1413
"github.com/database64128/ddns-go/producer"
@@ -150,28 +149,10 @@ func (s *textSource) get(ctx context.Context) (netip.Addr, error) {
150149
return addr.Unmap(), nil
151150
}
152151

153-
func defaultHttpTransportClone() *http.Transport {
154-
transport, ok := http.DefaultTransport.(*http.Transport)
155-
if !ok {
156-
// http.DefaultTransport was changed by user code to some custom implementation,
157-
// so here we create a best-effort approximation of the original.
158-
return &http.Transport{
159-
Proxy: http.ProxyFromEnvironment,
160-
// DialContext will be set by caller.
161-
ForceAttemptHTTP2: true,
162-
MaxIdleConns: 100,
163-
IdleConnTimeout: 90 * time.Second,
164-
TLSHandshakeTimeout: 10 * time.Second,
165-
ExpectContinueTimeout: 1 * time.Second,
166-
}
167-
}
168-
return transport.Clone()
169-
}
170-
171152
// defaultHttpClient4 returns an [*http.Client] that behaves like
172153
// [http.DefaultClient] but forces connections to use IPv4 only.
173154
var defaultHttpClient4 = sync.OnceValue(func() *http.Client {
174-
transport := defaultHttpTransportClone()
155+
transport := httpreq.DefaultHttpTransportClone()
175156
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
176157
switch network {
177158
case "tcp":
@@ -188,7 +169,7 @@ var defaultHttpClient4 = sync.OnceValue(func() *http.Client {
188169
// defaultHttpClient6 returns an [*http.Client] that behaves like
189170
// [http.DefaultClient] but forces connections to use IPv6 only.
190171
var defaultHttpClient6 = sync.OnceValue(func() *http.Client {
191-
transport := defaultHttpTransportClone()
172+
transport := httpreq.DefaultHttpTransportClone()
192173
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
193174
switch network {
194175
case "tcp":

0 commit comments

Comments
 (0)