integrate request builder into HTTP client for googleapis support (#157)
Some checks failed
coverage / build (push) Successful in 2m19s
test / test (push) Failing after 17m15s

This commit is contained in:
2025-09-23 15:30:15 +05:00
committed by GitHub
parent b37fca95cf
commit 24801750a7
32 changed files with 9491 additions and 1736 deletions

View File

@@ -1,126 +1,148 @@
package http
import (
"context"
"crypto/tls"
"net"
"net/http"
"time"
"go.unistack.org/micro/v4/client"
"go.unistack.org/micro/v4/metadata"
)
var (
// DefaultPoolMaxStreams maximum streams on a connectioin
// (20)
DefaultPoolMaxStreams = 20
// DefaultPoolMaxIdle maximum idle conns of a pool
// (50)
DefaultPoolMaxIdle = 50
// DefaultMaxRecvMsgSize maximum message that client can receive
// (4 MB).
DefaultMaxRecvMsgSize = 1024 * 1024 * 4
// DefaultMaxSendMsgSize maximum message that client can send
// (4 MB).
DefaultMaxSendMsgSize = 1024 * 1024 * 4
)
type poolMaxStreams struct{}
// PoolMaxStreams maximum streams on a connectioin
func PoolMaxStreams(n int) client.Option {
return client.SetOption(poolMaxStreams{}, n)
}
type poolMaxIdle struct{}
// PoolMaxIdle maximum idle conns of a pool
func PoolMaxIdle(d int) client.Option {
return client.SetOption(poolMaxIdle{}, d)
}
type maxRecvMsgSizeKey struct{}
// MaxRecvMsgSize set the maximum size of message that client can receive.
func MaxRecvMsgSize(s int) client.Option {
return client.SetOption(maxRecvMsgSizeKey{}, s)
}
type maxSendMsgSizeKey struct{}
// MaxSendMsgSize set the maximum size of message that client can send.
func MaxSendMsgSize(s int) client.Option {
return client.SetOption(maxSendMsgSizeKey{}, s)
}
// --------------------------------------------- HTTPClient option -----------------------------------------------------
type httpClientKey struct{}
// nolint: golint
// HTTPClient pass http.Client option to client Call
func HTTPClient(c *http.Client) client.Option {
return client.SetOption(httpClientKey{}, c)
}
func httpClientFromOpts(opts client.Options) (*http.Client, bool) {
httpClient, ok := opts.Context.Value(httpClientKey{}).(*http.Client)
return httpClient, ok
}
func defaultHTTPClient(
dialer func(ctx context.Context, addr string) (net.Conn, error),
tlsConfig *tls.Config,
) *http.Client {
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return dialer(ctx, addr)
},
ForceAttemptHTTP2: true,
MaxConnsPerHost: 100,
MaxIdleConns: 20,
IdleConnTimeout: 60 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: tlsConfig,
}
return &http.Client{Transport: tr}
}
// --------------------------------------------- HTTPDialer option -----------------------------------------------------
type httpDialerKey struct{}
// nolint: golint
// HTTPDialer pass net.Dialer option to client
func HTTPDialer(d *net.Dialer) client.Option {
return client.SetOption(httpDialerKey{}, d)
}
func httpDialerFromOpts(opts client.Options) (dialerFunc func(context.Context, string) (net.Conn, error), ok bool) {
var d *net.Dialer
if d, ok = opts.Context.Value(httpDialerKey{}).(*net.Dialer); ok {
dialerFunc = func(ctx context.Context, addr string) (net.Conn, error) {
return d.DialContext(ctx, "tcp", addr)
}
}
if opts.ContextDialer != nil {
dialerFunc, ok = opts.ContextDialer, true
}
return dialerFunc, ok
}
func defaultHTTPDialer() func(ctx context.Context, addr string) (net.Conn, error) {
return func(ctx context.Context, addr string) (net.Conn, error) {
d := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}
return d.DialContext(ctx, "tcp", addr)
}
}
// ----------------------------------------------- Method option -------------------------------------------------------
type methodKey struct{}
// Method pass method option to client Call
func Method(m string) client.CallOption {
return client.SetCallOption(methodKey{}, m)
}
func methodFromOpts(opts client.CallOptions) (string, bool) {
m, ok := opts.Context.Value(methodKey{}).(string)
return m, ok
}
// ------------------------------------------------ Path option --------------------------------------------------------
type pathKey struct{}
// Path spcecifies path option to client Call
func Path(p string) client.CallOption {
return client.SetCallOption(pathKey{}, p)
}
func pathFromOpts(opts client.CallOptions) (string, bool) {
p, ok := opts.Context.Value(pathKey{}).(string)
return p, ok
}
// ------------------------------------------------ Body option --------------------------------------------------------
type bodyKey struct{}
// Body specifies body option to client Call
func Body(b string) client.CallOption {
return client.SetCallOption(bodyKey{}, b)
}
func bodyFromOpts(opts client.CallOptions) (string, bool) {
b, ok := opts.Context.Value(bodyKey{}).(string)
return b, ok
}
// ---------------------------------------------- ErrorMap option ------------------------------------------------------
type errorMapKey struct{}
func ErrorMap(m map[string]interface{}) client.CallOption {
func ErrorMap(m map[string]any) client.CallOption {
return client.SetCallOption(errorMapKey{}, m)
}
type structTagsKey struct{}
// StructTags pass tags slice option to client Call
func StructTags(tags []string) client.CallOption {
return client.SetCallOption(structTagsKey{}, tags)
}
type metadataKey struct{}
// Metadata pass metadata to client Call
func Metadata(md metadata.Metadata) client.CallOption {
return client.SetCallOption(metadataKey{}, md)
func errorMapFromOpts(opts client.CallOptions) (map[string]any, bool) {
errMap, ok := opts.Context.Value(errorMapKey{}).(map[string]any)
return errMap, ok
}
// ------------------------------------------------ Cookie option ------------------------------------------------------
type cookieKey struct{}
// Cookie pass cookie to client Call
func Cookie(cookies ...string) client.CallOption {
return client.SetCallOption(cookieKey{}, cookies)
}
func cookieFromOpts(opts client.CallOptions) ([]string, bool) {
c, ok := opts.Context.Value(cookieKey{}).([]string)
return c, ok
}
// ------------------------------------------------ Header option ------------------------------------------------------
type headerKey struct{}
// Header pass cookie to client Call
func Header(headers ...string) client.CallOption {
return client.SetCallOption(headerKey{}, headers)
}
func headerFromOpts(opts client.CallOptions) ([]string, bool) {
h, ok := opts.Context.Value(headerKey{}).([]string)
return h, ok
}