-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrequestopts.go
129 lines (113 loc) · 3.18 KB
/
requestopts.go
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package client
import (
"fmt"
"net/http"
"net/url"
"path/filepath"
"strings"
// Namespace imports
. "github.com/djthorpe/go-errors"
)
///////////////////////////////////////////////////////////////////////////////
// TYPES
type requestOpts struct {
*http.Request
noTimeout bool // OptNoTimeout
textStreamCallback TextStreamCallback // OptTextStreamCallback
jsonStreamCallback JsonStreamCallback // OptJsonStreamCallback
}
type RequestOpt func(*requestOpts) error
///////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
// OptReqEndpoint modifies the request endpoint for this request only
func OptReqEndpoint(value string) RequestOpt {
return func(r *requestOpts) error {
if url, err := url.Parse(value); err != nil {
return err
} else if url.Scheme == "" || url.Host == "" {
return ErrBadParameter.Withf("endpoint: %q", value)
} else if url.Scheme != "http" && url.Scheme != "https" {
return ErrBadParameter.Withf("endpoint: %q", value)
} else {
r.URL = url
r.Host = url.Hostname()
}
return nil
}
}
// OptPath appends path elements onto a request
func OptPath(value ...any) RequestOpt {
return func(r *requestOpts) error {
// Make a copy
url := *r.URL
// Clean up and append path
url.Path = PathSeparator + filepath.Join(strings.Trim(url.Path, PathSeparator), strings.TrimPrefix(join(value, PathSeparator), PathSeparator))
// Set new path
r.URL = &url
return nil
}
}
// OptToken adds an authorization header. The header format is "Authorization: Bearer <token>"
func OptToken(value Token) RequestOpt {
return func(r *requestOpts) error {
if value.Value != "" {
r.Header.Set("Authorization", value.String())
} else {
r.Header.Del("Authorization")
}
return nil
}
}
// OptQuery adds query parameters to a request
func OptQuery(value url.Values) RequestOpt {
return func(r *requestOpts) error {
// Make a copy
url := *r.URL
// Append query
url.RawQuery = value.Encode()
// Set new query
r.URL = &url
return nil
}
}
// OptReqHeader sets a header value to the request
func OptReqHeader(name, value string) RequestOpt {
return func(r *requestOpts) error {
r.Header.Set(name, value)
return nil
}
}
// OptNoTimeout disables the timeout for this request, useful for long-running
// requests. The context can be used instead for cancelling requests
func OptNoTimeout() RequestOpt {
return func(r *requestOpts) error {
r.noTimeout = true
return nil
}
}
// OptTextStreamCallback is called for each event in a text stream
func OptTextStreamCallback(fn TextStreamCallback) RequestOpt {
return func(r *requestOpts) error {
r.textStreamCallback = fn
return nil
}
}
// OptJsonStreamCallback is called for each decoded JSON event
func OptJsonStreamCallback(fn JsonStreamCallback) RequestOpt {
return func(r *requestOpts) error {
r.jsonStreamCallback = fn
return nil
}
}
///////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
func join(values []any, sep string) string {
if len(values) == 0 {
return ""
}
str := make([]string, len(values))
for i, v := range values {
str[i] = fmt.Sprint(v)
}
return strings.Join(str, sep)
}