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)
|
||||
|
||||
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
|
||||
|
||||
|
||||
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