149 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package http
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"crypto/tls"
 | |
| 	"net"
 | |
| 	"net/http"
 | |
| 	"time"
 | |
| 
 | |
| 	"go.unistack.org/micro/v4/client"
 | |
| )
 | |
| 
 | |
| // --------------------------------------------- HTTPClient option -----------------------------------------------------
 | |
| type httpClientKey struct{}
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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]any) client.CallOption {
 | |
| 	return client.SetCallOption(errorMapKey{}, m)
 | |
| }
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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{}
 | |
| 
 | |
| 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
 | |
| }
 |