refactor: improve http client implement
This commit is contained in:
parent
6f36998df8
commit
84946743d9
@ -21,70 +21,62 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientOption func(client *Client) error
|
type ClientOption func(client *Client)
|
||||||
type BeegoHttpRequestOption func(request *BeegoHTTPRequest) error
|
type BeegoHttpRequestOption func(request *BeegoHTTPRequest)
|
||||||
|
|
||||||
// WithEnableCookie will enable cookie in all subsequent request
|
// WithEnableCookie will enable cookie in all subsequent request
|
||||||
func WithEnableCookie(enable bool) ClientOption {
|
func WithEnableCookie(enable bool) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.EnableCookie = enable
|
client.Setting.EnableCookie = enable
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithEnableCookie will adds UA in all subsequent request
|
// WithEnableCookie will adds UA in all subsequent request
|
||||||
func WithUserAgent(userAgent string) ClientOption {
|
func WithUserAgent(userAgent string) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.UserAgent = userAgent
|
client.Setting.UserAgent = userAgent
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTLSClientConfig will adds tls config in all subsequent request
|
// WithTLSClientConfig will adds tls config in all subsequent request
|
||||||
func WithTLSClientConfig(config *tls.Config) ClientOption {
|
func WithTLSClientConfig(config *tls.Config) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.TLSClientConfig = config
|
client.Setting.TLSClientConfig = config
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTransport will set transport field in all subsequent request
|
// WithTransport will set transport field in all subsequent request
|
||||||
func WithTransport(transport http.RoundTripper) ClientOption {
|
func WithTransport(transport http.RoundTripper) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.Transport = transport
|
client.Setting.Transport = transport
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithProxy will set http proxy field in all subsequent request
|
// WithProxy will set http proxy field in all subsequent request
|
||||||
func WithProxy(proxy func(*http.Request) (*url.URL, error)) ClientOption {
|
func WithProxy(proxy func(*http.Request) (*url.URL, error)) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.Proxy = proxy
|
client.Setting.Proxy = proxy
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCheckRedirect will specifies the policy for handling redirects in all subsequent request
|
// WithCheckRedirect will specifies the policy for handling redirects in all subsequent request
|
||||||
func WithCheckRedirect(redirect func(req *http.Request, via []*http.Request) error) ClientOption {
|
func WithCheckRedirect(redirect func(req *http.Request, via []*http.Request) error) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.CheckRedirect = redirect
|
client.Setting.CheckRedirect = redirect
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHTTPSetting can replace beegoHTTPSeting
|
// WithHTTPSetting can replace beegoHTTPSeting
|
||||||
func WithHTTPSetting(setting BeegoHTTPSettings) ClientOption {
|
func WithHTTPSetting(setting BeegoHTTPSettings) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting = &setting
|
client.Setting = setting
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithEnableGzip will enable gzip in all subsequent request
|
// WithEnableGzip will enable gzip in all subsequent request
|
||||||
func WithEnableGzip(enable bool) ClientOption {
|
func WithEnableGzip(enable bool) ClientOption {
|
||||||
return func(client *Client) error {
|
return func(client *Client) {
|
||||||
client.Setting.Gzip = enable
|
client.Setting.Gzip = enable
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,73 +84,60 @@ func WithEnableGzip(enable bool) ClientOption {
|
|||||||
|
|
||||||
// WithTimeout sets connect time out and read-write time out for BeegoRequest.
|
// WithTimeout sets connect time out and read-write time out for BeegoRequest.
|
||||||
func WithTimeout(connectTimeout, readWriteTimeout time.Duration) BeegoHttpRequestOption {
|
func WithTimeout(connectTimeout, readWriteTimeout time.Duration) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.SetTimeout(connectTimeout, readWriteTimeout)
|
request.SetTimeout(connectTimeout, readWriteTimeout)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHeader adds header item string in request.
|
// WithHeader adds header item string in request.
|
||||||
func WithHeader(key, value string) BeegoHttpRequestOption {
|
func WithHeader(key, value string) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.Header(key, value)
|
request.Header(key, value)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCookie adds a cookie to the request.
|
// WithCookie adds a cookie to the request.
|
||||||
func WithCookie(cookie *http.Cookie) BeegoHttpRequestOption {
|
func WithCookie(cookie *http.Cookie) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.Header("Cookie", cookie.String())
|
request.Header("Cookie", cookie.String())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Withtokenfactory adds a custom function to set Authorization
|
// Withtokenfactory adds a custom function to set Authorization
|
||||||
func WithTokenFactory(tokenFactory func() (string, error)) BeegoHttpRequestOption {
|
func WithTokenFactory(tokenFactory func() string) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
t, err := tokenFactory()
|
t := tokenFactory()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
request.Header("Authorization", t)
|
request.Header("Authorization", t)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithBasicAuth adds a custom function to set basic auth
|
// WithBasicAuth adds a custom function to set basic auth
|
||||||
func WithBasicAuth(basicAuth func() (string, string, error)) BeegoHttpRequestOption {
|
func WithBasicAuth(basicAuth func() (string, string)) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
username, password, err := basicAuth()
|
username, password := basicAuth()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
request.SetBasicAuth(username, password)
|
request.SetBasicAuth(username, password)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithFilters will use the filter as the invocation filters
|
// WithFilters will use the filter as the invocation filters
|
||||||
func WithFilters(fcs ...FilterChain) BeegoHttpRequestOption {
|
func WithFilters(fcs ...FilterChain) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.SetFilters(fcs...)
|
request.SetFilters(fcs...)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithContentType adds ContentType in header
|
// WithContentType adds ContentType in header
|
||||||
func WithContentType(contentType string) BeegoHttpRequestOption {
|
func WithContentType(contentType string) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.Header("Content-Type", contentType)
|
request.Header(contentTypeKey, contentType)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithParam adds query param in to request.
|
// WithParam adds query param in to request.
|
||||||
func WithParam(key, value string) BeegoHttpRequestOption {
|
func WithParam(key, value string) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.Param(key, value)
|
request.Param(key, value)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,9 +146,8 @@ func WithParam(key, value string) BeegoHttpRequestOption {
|
|||||||
// -1 retry indefinitely (forever)
|
// -1 retry indefinitely (forever)
|
||||||
// Other numbers specify the exact retry amount
|
// Other numbers specify the exact retry amount
|
||||||
func WithRetry(times int, delay time.Duration) BeegoHttpRequestOption {
|
func WithRetry(times int, delay time.Duration) BeegoHttpRequestOption {
|
||||||
return func(request *BeegoHTTPRequest) error {
|
return func(request *BeegoHTTPRequest) {
|
||||||
request.Retries(times)
|
request.Retries(times)
|
||||||
request.RetryDelay(delay)
|
request.RetryDelay(delay)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,8 +147,8 @@ func TestOption_WithTokenFactory(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
client.CommonOpts = append(client.CommonOpts,
|
client.CommonOpts = append(client.CommonOpts,
|
||||||
WithTokenFactory(func() (string, error) {
|
WithTokenFactory(func() string {
|
||||||
return "testauth", nil
|
return "testauth"
|
||||||
}))
|
}))
|
||||||
|
|
||||||
var str *string
|
var str *string
|
||||||
@ -172,8 +172,8 @@ func TestOption_WithBasicAuth(t *testing.T) {
|
|||||||
|
|
||||||
var str *string
|
var str *string
|
||||||
err = client.Get(&str, "/basic-auth/user/passwd",
|
err = client.Get(&str, "/basic-auth/user/passwd",
|
||||||
WithBasicAuth(func() (string, string, error) {
|
WithBasicAuth(func() (string, string) {
|
||||||
return "user", "passwd", nil
|
return "user", "passwd"
|
||||||
}))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -240,7 +240,9 @@ func TestOption_WithRetry(t *testing.T) {
|
|||||||
|
|
||||||
err = client.Get(nil, "", WithRetry(retryAmount, retryDelay))
|
err = client.Get(nil, "", WithRetry(retryAmount, retryDelay))
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
endTime := time.Now().UnixNano() / int64(time.Millisecond)
|
endTime := time.Now().UnixNano() / int64(time.Millisecond)
|
||||||
elapsedTime := endTime - startTime
|
elapsedTime := endTime - startTime
|
||||||
delayedTime := int64(retryAmount) * retryDelay.Milliseconds()
|
delayedTime := int64(retryAmount) * retryDelay.Milliseconds()
|
||||||
|
|||||||
@ -16,9 +16,6 @@ package httplib
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/core/berror"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client provides an HTTP client supporting chain call
|
// Client provides an HTTP client supporting chain call
|
||||||
@ -27,8 +24,8 @@ type Client struct {
|
|||||||
Endpoint string
|
Endpoint string
|
||||||
CommonOpts []BeegoHttpRequestOption
|
CommonOpts []BeegoHttpRequestOption
|
||||||
|
|
||||||
Setting *BeegoHTTPSettings
|
Setting BeegoHTTPSettings
|
||||||
pointer *responsePointer
|
pointer responsePointer
|
||||||
}
|
}
|
||||||
|
|
||||||
type responsePointer struct {
|
type responsePointer struct {
|
||||||
@ -46,72 +43,43 @@ func NewClient(name string, endpoint string, opts ...ClientOption) (*Client, err
|
|||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
setting := GetDefaultSetting()
|
setting := GetDefaultSetting()
|
||||||
res.Setting = &setting
|
res.Setting = setting
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
err := o(res)
|
o(res)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response will set response to the pointer
|
// Response will set response to the pointer
|
||||||
func (c *Client) Response(resp **http.Response) *Client {
|
func (c *Client) Response(resp **http.Response) *Client {
|
||||||
if c.pointer == nil {
|
|
||||||
newC := *c
|
newC := *c
|
||||||
newC.pointer = &responsePointer{
|
newC.pointer.response = resp
|
||||||
response: resp,
|
|
||||||
}
|
|
||||||
return &newC
|
return &newC
|
||||||
}
|
}
|
||||||
c.pointer.response = resp
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatusCode will set response StatusCode to the pointer
|
// StatusCode will set response StatusCode to the pointer
|
||||||
func (c *Client) StatusCode(code **int) *Client {
|
func (c *Client) StatusCode(code **int) *Client {
|
||||||
if c.pointer == nil {
|
|
||||||
newC := *c
|
newC := *c
|
||||||
newC.pointer = &responsePointer{
|
newC.pointer.statusCode = code
|
||||||
statusCode: code,
|
|
||||||
}
|
|
||||||
return &newC
|
return &newC
|
||||||
}
|
}
|
||||||
c.pointer.statusCode = code
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Headers will set response Headers to the pointer
|
// Headers will set response Headers to the pointer
|
||||||
func (c *Client) Headers(headers **http.Header) *Client {
|
func (c *Client) Headers(headers **http.Header) *Client {
|
||||||
if c.pointer == nil {
|
|
||||||
newC := *c
|
newC := *c
|
||||||
newC.pointer = &responsePointer{
|
newC.pointer.header = headers
|
||||||
header: headers,
|
|
||||||
}
|
|
||||||
return &newC
|
return &newC
|
||||||
}
|
}
|
||||||
c.pointer.header = headers
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeaderValue will set response HeaderValue to the pointer
|
// HeaderValue will set response HeaderValue to the pointer
|
||||||
func (c *Client) HeaderValue(key string, value **string) *Client {
|
func (c *Client) HeaderValue(key string, value **string) *Client {
|
||||||
if c.pointer == nil {
|
|
||||||
newC := *c
|
newC := *c
|
||||||
newC.pointer = &responsePointer{
|
if newC.pointer.headerValues == nil {
|
||||||
headerValues: map[string]**string{
|
newC.pointer.headerValues = make(map[string]**string)
|
||||||
key: value,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
newC.pointer.headerValues[key] = value
|
||||||
return &newC
|
return &newC
|
||||||
}
|
}
|
||||||
if c.pointer.headerValues == nil {
|
|
||||||
c.pointer.headerValues = map[string]**string{}
|
|
||||||
}
|
|
||||||
c.pointer.headerValues[key] = value
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContentType will set response ContentType to the pointer
|
// ContentType will set response ContentType to the pointer
|
||||||
func (c *Client) ContentType(contentType **string) *Client {
|
func (c *Client) ContentType(contentType **string) *Client {
|
||||||
@ -120,22 +88,13 @@ func (c *Client) ContentType(contentType **string) *Client {
|
|||||||
|
|
||||||
// ContentLength will set response ContentLength to the pointer
|
// ContentLength will set response ContentLength to the pointer
|
||||||
func (c *Client) ContentLength(contentLength **int64) *Client {
|
func (c *Client) ContentLength(contentLength **int64) *Client {
|
||||||
if c.pointer == nil {
|
|
||||||
newC := *c
|
newC := *c
|
||||||
newC.pointer = &responsePointer{
|
newC.pointer.contentLength = contentLength
|
||||||
contentLength: contentLength,
|
|
||||||
}
|
|
||||||
return &newC
|
return &newC
|
||||||
}
|
}
|
||||||
c.pointer.contentLength = contentLength
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointers set the http response value to pointer
|
// setPointers set the http response value to pointer
|
||||||
func (c *Client) setPointers(resp *http.Response) {
|
func (c *Client) setPointers(resp *http.Response) {
|
||||||
if c.pointer == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.pointer.response != nil {
|
if c.pointer.response != nil {
|
||||||
*c.pointer.response = resp
|
*c.pointer.response = resp
|
||||||
}
|
}
|
||||||
@ -156,37 +115,13 @@ func (c *Client) setPointers(resp *http.Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// initRequest will apply all the client setting, common option and request option
|
func (c *Client) customReq(req *BeegoHTTPRequest, opts []BeegoHttpRequestOption) {
|
||||||
func (c *Client) newRequest(method, path string, opts []BeegoHttpRequestOption) (*BeegoHTTPRequest, error) {
|
req.Setting(c.Setting)
|
||||||
var req *BeegoHTTPRequest
|
opts = append(c.CommonOpts, opts...)
|
||||||
switch method {
|
|
||||||
case http.MethodGet:
|
|
||||||
req = Get(c.Endpoint + path)
|
|
||||||
case http.MethodPost:
|
|
||||||
req = Post(c.Endpoint + path)
|
|
||||||
case http.MethodPut:
|
|
||||||
req = Put(c.Endpoint + path)
|
|
||||||
case http.MethodDelete:
|
|
||||||
req = Delete(c.Endpoint + path)
|
|
||||||
case http.MethodHead:
|
|
||||||
req = Head(c.Endpoint + path)
|
|
||||||
}
|
|
||||||
|
|
||||||
req = req.Setting(*c.Setting)
|
|
||||||
for _, o := range c.CommonOpts {
|
|
||||||
err := o(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
err := o(req)
|
o(req)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handleResponse try to parse body to meaningful value
|
// handleResponse try to parse body to meaningful value
|
||||||
func (c *Client) handleResponse(value interface{}, req *BeegoHTTPRequest) error {
|
func (c *Client) handleResponse(value interface{}, req *BeegoHTTPRequest) error {
|
||||||
@ -196,69 +131,20 @@ func (c *Client) handleResponse(value interface{}, req *BeegoHTTPRequest) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.setPointers(resp)
|
c.setPointers(resp)
|
||||||
|
return req.ResponseForValue(value)
|
||||||
if value == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle basic type
|
|
||||||
switch v := value.(type) {
|
|
||||||
case **string:
|
|
||||||
s, err := req.String()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*v = &s
|
|
||||||
return nil
|
|
||||||
case **[]byte:
|
|
||||||
bs, err := req.Bytes()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*v = &bs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to parse it as content type
|
|
||||||
switch strings.Split(resp.Header.Get("Content-Type"), ";")[0] {
|
|
||||||
case "application/json":
|
|
||||||
return req.ToJSON(value)
|
|
||||||
case "text/xml", "application/xml":
|
|
||||||
return req.ToXML(value)
|
|
||||||
case "text/yaml", "application/x-yaml":
|
|
||||||
return req.ToYAML(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to parse it anyway
|
|
||||||
if err := req.ToJSON(value); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := req.ToYAML(value); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := req.ToXML(value); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO add new error type about can't parse body
|
|
||||||
return berror.Error(UnsupportedBodyType, "unsupported body data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Send a GET request and try to give its result value
|
// Get Send a GET request and try to give its result value
|
||||||
func (c *Client) Get(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
func (c *Client) Get(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
||||||
req, err := c.newRequest(http.MethodGet, path, opts)
|
req := Get(c.Endpoint + path)
|
||||||
if err != nil {
|
c.customReq(req, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.handleResponse(value, req)
|
return c.handleResponse(value, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post Send a POST request and try to give its result value
|
// Post Send a POST request and try to give its result value
|
||||||
func (c *Client) Post(value interface{}, path string, body interface{}, opts ...BeegoHttpRequestOption) error {
|
func (c *Client) Post(value interface{}, path string, body interface{}, opts ...BeegoHttpRequestOption) error {
|
||||||
req, err := c.newRequest(http.MethodPost, path, opts)
|
req := Post(c.Endpoint + path)
|
||||||
if err != nil {
|
c.customReq(req, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
if body != nil {
|
if body != nil {
|
||||||
req = req.Body(body)
|
req = req.Body(body)
|
||||||
}
|
}
|
||||||
@ -267,10 +153,8 @@ func (c *Client) Post(value interface{}, path string, body interface{}, opts ...
|
|||||||
|
|
||||||
// Put Send a Put request and try to give its result value
|
// Put Send a Put request and try to give its result value
|
||||||
func (c *Client) Put(value interface{}, path string, body interface{}, opts ...BeegoHttpRequestOption) error {
|
func (c *Client) Put(value interface{}, path string, body interface{}, opts ...BeegoHttpRequestOption) error {
|
||||||
req, err := c.newRequest(http.MethodPut, path, opts)
|
req := Put(c.Endpoint + path)
|
||||||
if err != nil {
|
c.customReq(req, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
if body != nil {
|
if body != nil {
|
||||||
req = req.Body(body)
|
req = req.Body(body)
|
||||||
}
|
}
|
||||||
@ -279,18 +163,14 @@ func (c *Client) Put(value interface{}, path string, body interface{}, opts ...B
|
|||||||
|
|
||||||
// Delete Send a Delete request and try to give its result value
|
// Delete Send a Delete request and try to give its result value
|
||||||
func (c *Client) Delete(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
func (c *Client) Delete(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
||||||
req, err := c.newRequest(http.MethodDelete, path, opts)
|
req := Delete(c.Endpoint + path)
|
||||||
if err != nil {
|
c.customReq(req, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.handleResponse(value, req)
|
return c.handleResponse(value, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Head Send a Head request and try to give its result value
|
// Head Send a Head request and try to give its result value
|
||||||
func (c *Client) Head(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
func (c *Client) Head(value interface{}, path string, opts ...BeegoHttpRequestOption) error {
|
||||||
req, err := c.newRequest(http.MethodHead, path, opts)
|
req := Head(c.Endpoint + path)
|
||||||
if err != nil {
|
c.customReq(req, opts)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return c.handleResponse(value, req)
|
return c.handleResponse(value, req)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const contentTypeKey = "Content-Type"
|
const contentTypeKey = "Content-Type"
|
||||||
|
|
||||||
// it will be the last filter and execute request.Do
|
// it will be the last filter and execute request.Do
|
||||||
var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
|
var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
|
||||||
return req.doRequest(ctx)
|
return req.doRequest(ctx)
|
||||||
@ -660,6 +661,64 @@ func (b *BeegoHTTPRequest) Response() (*http.Response, error) {
|
|||||||
return b.getResponse()
|
return b.getResponse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResponseForValue attempts to resolve the response body to value using an existing method.
|
||||||
|
// Calls Response inner.
|
||||||
|
// If value type is **string or **[]byte, the func directly passes response body into the pointer.
|
||||||
|
// Else if response header contain Content-Type, func will call ToJSON\ToXML\ToYAML.
|
||||||
|
// Finally it will try to parse body as json\yaml\xml, If all attempts fail, an error will be returned
|
||||||
|
func (b *BeegoHTTPRequest) ResponseForValue(value interface{}) error {
|
||||||
|
if value == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// handle basic type
|
||||||
|
switch v := value.(type) {
|
||||||
|
case **string:
|
||||||
|
s, err := b.String()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*v = &s
|
||||||
|
return nil
|
||||||
|
case **[]byte:
|
||||||
|
bs, err := b.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*v = &bs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := b.Response()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
contentType := strings.Split(resp.Header.Get(contentTypeKey), ";")[0]
|
||||||
|
|
||||||
|
// try to parse it as content type
|
||||||
|
switch contentType {
|
||||||
|
case "application/json":
|
||||||
|
return b.ToJSON(value)
|
||||||
|
case "text/xml", "application/xml":
|
||||||
|
return b.ToXML(value)
|
||||||
|
case "text/yaml", "application/x-yaml", "application/x+yaml":
|
||||||
|
return b.ToYAML(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to parse it anyway
|
||||||
|
if err := b.ToJSON(value); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := b.ToYAML(value); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := b.ToXML(value); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add new error type about can't parse body
|
||||||
|
return berror.Error(UnsupportedBodyType, "unsupported body data")
|
||||||
|
}
|
||||||
|
|
||||||
// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field.
|
// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field.
|
||||||
// Deprecated
|
// Deprecated
|
||||||
// we will move this at the end of 2021
|
// we will move this at the end of 2021
|
||||||
|
|||||||
@ -433,3 +433,7 @@ func TestBeegoHTTPRequest_XMLBody(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotNil(t, req.req.GetBody)
|
assert.NotNil(t, req.req.GetBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
func TestBeegoHTTPRequest_ResponseForValue(t *testing.T) {
|
||||||
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@ func SetDefaultSetting(setting BeegoHTTPSettings) {
|
|||||||
defaultSetting = setting
|
defaultSetting = setting
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaultSetting return current default setting
|
// GetDefaultSetting return current default setting
|
||||||
func GetDefaultSetting() BeegoHTTPSettings {
|
func GetDefaultSetting() BeegoHTTPSettings {
|
||||||
return defaultSetting
|
return defaultSetting
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user