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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
package meilisearch
import (
"context"
"crypto/tls"
"encoding/json"
"net"
"net/http"
"net/url"
"time"
)
type meiliOpt struct {
client *http.Client
transport *http.Transport
apiKey string
contentEncoding *encodingOpt
retryOnStatus map[int]bool
disableRetry bool
maxRetries uint8
jsonMarshaler JSONMarshal
jsonUnmarshaler JSONUnmarshal
}
type encodingOpt struct {
encodingType ContentEncoding
level EncodingCompressionLevel
}
type Option func(*meiliOpt)
func _defaultOpts() *meiliOpt {
transport := baseTransport()
return &meiliOpt{
client: &http.Client{
Transport: transport,
},
transport: transport,
contentEncoding: &encodingOpt{
level: DefaultCompression,
},
retryOnStatus: map[int]bool{
502: true,
503: true,
504: true,
},
disableRetry: false,
maxRetries: 3,
jsonMarshaler: json.Marshal,
jsonUnmarshaler: json.Unmarshal,
}
}
// WithCustomClient set custom http.Client
func WithCustomClient(client *http.Client) Option {
return func(opt *meiliOpt) {
opt.client = client
}
}
// WithCustomProxy sets a custom proxy function
func WithCustomProxy(proxy func(*http.Request) (*url.URL, error)) Option {
return func(opt *meiliOpt) {
if proxy != nil {
opt.transport.Proxy = proxy
}
}
}
// WithCustomDialContext sets a custom dial context
func WithCustomDialContext(dial func(ctx context.Context, network, addr string) (net.Conn, error)) Option {
return func(opt *meiliOpt) {
if dial != nil {
opt.transport.DialContext = dial
}
}
}
// WithCustomMaxIdleConns sets the max number of idle connections
func WithCustomMaxIdleConns(maxIdleConns int) Option {
return func(opt *meiliOpt) {
opt.transport.MaxIdleConns = maxIdleConns
}
}
// WithCustomMaxIdleConnsPerHost sets max idle connections per host
func WithCustomMaxIdleConnsPerHost(maxIdleConnsPerHost int) Option {
return func(opt *meiliOpt) {
opt.transport.MaxIdleConnsPerHost = maxIdleConnsPerHost
}
}
// WithCustomIdleConnTimeout sets the idle connection timeout
func WithCustomIdleConnTimeout(timeout time.Duration) Option {
return func(opt *meiliOpt) {
opt.transport.IdleConnTimeout = timeout
}
}
// WithCustomTLSHandshakeTimeout sets the TLS handshake timeout
func WithCustomTLSHandshakeTimeout(timeout time.Duration) Option {
return func(opt *meiliOpt) {
opt.transport.TLSHandshakeTimeout = timeout
}
}
// WithCustomExpectContinueTimeout sets the Expect-Continue timeout
func WithCustomExpectContinueTimeout(timeout time.Duration) Option {
return func(opt *meiliOpt) {
opt.transport.ExpectContinueTimeout = timeout
}
}
// WithCustomClientWithTLS client support tls configuration
func WithCustomClientWithTLS(tlsConfig *tls.Config) Option {
return func(opt *meiliOpt) {
trans := baseTransport()
trans.TLSClientConfig = tlsConfig
opt.client = &http.Client{Transport: trans}
}
}
// WithAPIKey is API key or master key.
//
// more: https://www.meilisearch.com/docs/reference/api/keys
func WithAPIKey(key string) Option {
return func(opt *meiliOpt) {
opt.apiKey = key
}
}
// WithContentEncoding support the Content-Encoding header indicates the media type is compressed by a given algorithm.
// compression improves transfer speed and reduces bandwidth consumption by sending and receiving smaller payloads.
// the Accept-Encoding header, instead, indicates the compression algorithm the client understands.
//
// more: https://www.meilisearch.com/docs/reference/api/overview#content-encoding
func WithContentEncoding(encodingType ContentEncoding, level EncodingCompressionLevel) Option {
return func(opt *meiliOpt) {
opt.contentEncoding = &encodingOpt{
encodingType: encodingType,
level: level,
}
}
}
// WithCustomRetries set retry on specific http error code and max retries (min: 1, max: 255)
func WithCustomRetries(retryOnStatus []int, maxRetries uint8) Option {
return func(opt *meiliOpt) {
opt.retryOnStatus = make(map[int]bool)
for _, status := range retryOnStatus {
opt.retryOnStatus[status] = true
}
if maxRetries == 0 {
maxRetries = 1
}
opt.maxRetries = maxRetries
}
}
// DisableRetries disable retry logic in client
func DisableRetries() Option {
return func(opt *meiliOpt) {
opt.disableRetry = true
}
}
// WithCustomJsonMarshaler set custom marshal from external packages instead encoding/json.
// we use encoding/json as default json library due to stability and producibility. However,
// the standard library is a bit slow compared to 3rd party libraries. If you're not happy with
// the performance of encoding/json.
//
// supported package: goccy/go-json, bytedance/sonic, segmentio/encoding, minio/simdjson-go, wI2L/jettison, mailru/easyjson.
//
// default is encoding/json
func WithCustomJsonMarshaler(marshal JSONMarshal) Option {
return func(opt *meiliOpt) {
opt.jsonMarshaler = marshal
}
}
// WithCustomJsonUnmarshaler set custom unmarshal from external packages instead encoding/json.
// we use encoding/json as default json library due to stability and producibility. However,
// the standard library is a bit slow compared to 3rd party libraries. If you're not happy with
// the performance of encoding/json.
//
// supported package: goccy/go-json, bytedance/sonic, segmentio/encoding, minio/simdjson-go, wI2L/jettison, mailru/easyjson.
//
// default is encoding/json
func WithCustomJsonUnmarshaler(unmarshal JSONUnmarshal) Option {
return func(opt *meiliOpt) {
opt.jsonUnmarshaler = unmarshal
}
}
func baseTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
|