1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package eventstream
import (
"errors"
"net/http"
"time"
"github.com/johnandersen777/socialweb-computer-kcp/internal/component"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/opt"
)
type fallbackHTTPTransport struct {
primary http.RoundTripper
fallback http.RoundTripper
}
func (t fallbackHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if t.primary != nil && req.URL != nil && req.URL.Scheme == "http" {
response, err := t.primary.RoundTrip(req)
if err == nil {
return response, nil
}
if !errors.Is(err, component.ErrNoHandler) {
return nil, err
}
}
if t.fallback == nil {
return nil, errors.New("eventstream: no HTTP transport")
}
return t.fallback.RoundTrip(req)
}
func httpClientWithFallback(primary, external *http.Client) *http.Client {
if primary == nil {
if external != nil {
return external
}
return &http.Client{Timeout: 20 * time.Second}
}
fallback := http.RoundTripper(http.DefaultTransport)
if transport, ok := primary.Transport.(*http.Transport); ok && transport != nil {
cloned := transport.Clone()
cloned.Proxy = http.ProxyFromEnvironment
fallback = cloned
}
if external != nil && external.Transport != nil {
fallback = external.Transport
}
timeout := primary.Timeout
timeout = opt.Positive(timeout, 20*time.Second)
return &http.Client{
Transport: fallbackHTTPTransport{primary: primary.Transport, fallback: fallback},
Timeout: timeout,
}
}