mirror of
https://github.com/therootcompany/golib.git
synced 2026-11-04 06:55:00 +00:00
ref!(https): rewrite with latest best practices, for publish
This commit is contained in:
parent
71671b7852
commit
c66c4a8de4
@ -1,6 +1,6 @@
|
|||||||
# https (as in secure)
|
# https (as in secure)
|
||||||
|
|
||||||
This wrappers and helpers to supplement Go's built-in `net/http` with reasonable and safe defaults.
|
This wrappers and helpers to supplement Go's built-in `net/http` with reasonable and safe defaults, even when used with `http`.
|
||||||
|
|
||||||
See
|
See
|
||||||
|
|
||||||
|
|||||||
48
https/default.go
Normal file
48
https/default.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package https
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDefaultDialer expects connections to be established quickly
|
||||||
|
func NewDefaultDialer() *net.Dialer {
|
||||||
|
return &net.Dialer{
|
||||||
|
Timeout: 4 * time.Second,
|
||||||
|
KeepAlive: 25 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultTransport expects quick tls termination, but allows for
|
||||||
|
// sluggish header response times (the server often doesn't know
|
||||||
|
// what headers to send until the response is nearly ready due to API
|
||||||
|
// calls, db queries, etc)
|
||||||
|
func NewDefaultTransport() *http.Transport {
|
||||||
|
dialer := NewDefaultDialer()
|
||||||
|
|
||||||
|
return &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: dialer.DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
|
||||||
|
MaxConnsPerHost: 100,
|
||||||
|
MaxIdleConnsPerHost: 10,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 59 * time.Second, // less than 59s firewall timeouts
|
||||||
|
|
||||||
|
TLSHandshakeTimeout: 4 * time.Second,
|
||||||
|
ResponseHeaderTimeout: 20 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultClient creates a new http client with reasonable and safe defaults
|
||||||
|
// for API services that are expected to connect and reply relatively quickly.
|
||||||
|
// DO NOT use for long streaming downloads or extremely slow APIs.
|
||||||
|
func NewDefaultClient() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Timeout: 25 * time.Second,
|
||||||
|
Transport: NewDefaultTransport(),
|
||||||
|
}
|
||||||
|
}
|
||||||
3
https/go.mod
Normal file
3
https/go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/therootcompany/golib/https
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
@ -1,22 +0,0 @@
|
|||||||
package https
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewHTTPClient creates a new http client with reasonable and safe defaults
|
|
||||||
func NewHTTPClient() *http.Client {
|
|
||||||
transport := &http.Transport{
|
|
||||||
Dial: (&net.Dialer{
|
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
TLSHandshakeTimeout: 5 * time.Second,
|
|
||||||
}
|
|
||||||
client := &http.Client{
|
|
||||||
Timeout: time.Second * 5,
|
|
||||||
Transport: transport,
|
|
||||||
}
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
44
https/internal.go
Normal file
44
https/internal.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package https
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewInternalDialer is aggressive because we expect very low network latency.
|
||||||
|
func NewInternalDialer() *net.Dialer {
|
||||||
|
return &net.Dialer{
|
||||||
|
Timeout: 2 * time.Second, // plenty for DNS + <200 ms RTT + Happy Eyeballs
|
||||||
|
KeepAlive: 27 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInternalTransport prioritizes fast failure and high connection reuse
|
||||||
|
// for internal service-to-service traffic.
|
||||||
|
func NewInternalTransport() *http.Transport {
|
||||||
|
dialer := NewInternalDialer()
|
||||||
|
return &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: dialer.DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
|
||||||
|
MaxIdleConns: 200,
|
||||||
|
MaxIdleConnsPerHost: 50, // higher – few hosts, high concurrency
|
||||||
|
MaxConnsPerHost: 200,
|
||||||
|
IdleConnTimeout: 29 * time.Second,
|
||||||
|
|
||||||
|
TLSHandshakeTimeout: 1 * time.Second,
|
||||||
|
ResponseHeaderTimeout: 11 * time.Second, // still allows modest backend work
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInternalClient is for internal APIs that should be fast.
|
||||||
|
// Do not use for slow batch jobs or external calls.
|
||||||
|
func NewInternalClient() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Timeout: 13 * time.Second,
|
||||||
|
Transport: NewInternalTransport(),
|
||||||
|
}
|
||||||
|
}
|
||||||
45
https/slow.go
Normal file
45
https/slow.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package https
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmp"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSlowDialer allows more time for DNS, Happy Eyeballs, and high-latency links.
|
||||||
|
func NewSlowDialer() *net.Dialer {
|
||||||
|
return &net.Dialer{
|
||||||
|
Timeout: 15 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSlowTransport is tolerant of slow networks and sluggish servers.
|
||||||
|
// Still protects against completely hung connections.
|
||||||
|
func NewSlowTransport() *http.Transport {
|
||||||
|
dialer := NewSlowDialer()
|
||||||
|
return &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
DialContext: dialer.DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
MaxIdleConnsPerHost: 20,
|
||||||
|
MaxConnsPerHost: 100,
|
||||||
|
IdleConnTimeout: 89 * time.Second,
|
||||||
|
|
||||||
|
TLSHandshakeTimeout: 15 * time.Second,
|
||||||
|
ResponseHeaderTimeout: 59 * time.Second,
|
||||||
|
ExpectContinueTimeout: 2 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSlowClient is for requests that may legitimately take a long time.
|
||||||
|
// Prefer request-level context timeouts when you need finer control.
|
||||||
|
func NewSlowClient(timeout time.Duration) *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Timeout: cmp.Or(timeout, 89*time.Second),
|
||||||
|
Transport: NewSlowTransport(),
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user