Total Lines | 43 |
Duplicated Lines | 0 % |
Changes | 0 |
1 | package client |
||
2 | |||
3 | import ( |
||
4 | "errors" |
||
5 | "fmt" |
||
6 | "net/http" |
||
7 | "sync" |
||
8 | ) |
||
9 | |||
10 | var ( |
||
11 | // ErrRequestRedundant this error is returned when trying to perform the |
||
12 | // same request (method, host, path) more than one time. |
||
13 | ErrRequestRedundant = errors.New("this request has been made already") |
||
14 | ) |
||
15 | |||
16 | func decorateTransportWithRequestCacheDecorator(decorated http.RoundTripper) (*requestCacheTransportDecorator, error) { |
||
17 | if decorated == nil { |
||
18 | return nil, errors.New("decorated round tripper is nil") |
||
19 | } |
||
20 | |||
21 | return &requestCacheTransportDecorator{decorated: decorated}, nil |
||
22 | } |
||
23 | |||
24 | type requestCacheTransportDecorator struct { |
||
25 | decorated http.RoundTripper |
||
26 | requestMap sync.Map |
||
27 | } |
||
28 | |||
29 | func (u *requestCacheTransportDecorator) RoundTrip(r *http.Request) (*http.Response, error) { |
||
30 | key := u.keyForRequest(r) |
||
31 | |||
32 | _, found := u.requestMap.Load(key) |
||
33 | if found { |
||
34 | return nil, ErrRequestRedundant |
||
35 | } |
||
36 | |||
37 | u.requestMap.Store(key, struct{}{}) |
||
38 | |||
39 | return u.decorated.RoundTrip(r) |
||
40 | } |
||
41 | |||
42 | func (u *requestCacheTransportDecorator) keyForRequest(r *http.Request) string { |
||
43 | return fmt.Sprintf("%s~%s~%s", r.Method, r.Host, r.URL.Path) |
||
44 | } |
||
45 |