httpx

package module
v0.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2023 License: MIT Imports: 16 Imported by: 1

README

httpx

Retryable http client with some helper functions.

go get github.com/worldline-go/utility/httpx

Documentation

Overview

Example
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/worldline-go/utility/httpx"
)

type Client struct {
	httpx *httpx.Client
}

func (c *Client) CreateX(ctx context.Context, r CreateXRequest) (*CreateXResponse, error) {
	var v CreateXResponse
	if err := c.httpx.DoWithFunc(ctx, r, func(r *http.Response) error {
		if r.StatusCode != http.StatusOK {
			return httpx.UnexpectedResponseError(r)
		}

		if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
			return err
		}

		return nil
	}); err != nil {
		return nil, err
	}

	return &v, nil
}

// ----

type CreateXRequest struct {
	ID string `json:"id"`
}

func (CreateXRequest) Method() string {
	return http.MethodPost
}

func (CreateXRequest) Path() string {
	return "/api/v1/x"
}

func (r CreateXRequest) BodyJSON() interface{} {
	return r
}

func (r CreateXRequest) Validate() error {
	if r.ID == "" {
		return fmt.Errorf("id is required")
	}

	return nil
}

func (r CreateXRequest) Header() http.Header {
	v := http.Header{}
	v.Set("X-Info", "example")

	return v
}

type CreateXResponse struct {
	RequestID string `json:"request_id"`
}

// ---

func main() {
	httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// check request method
		if r.Method != http.MethodPost {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{"error": "invalid request method"}`))
			return
		}

		// check request path
		if r.URL.Path != "/api/v1/x" {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{"error": "invalid request path"}`))
			return
		}

		// check request header
		if r.Header.Get("X-Info") != "example" {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{"error": "invalid request header"}`))
			return
		}

		// get request body
		var m map[string]interface{}
		if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{"error": "invalid request body"}`))
			return
		}

		// check request body
		if m["id"] != "123" {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte(`{"error": "invalid id"}`))
			return
		}

		// write response
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"request_id": "123+"}`))
	}))

	defer httpServer.Close()

	httpxClient, err := httpx.NewClient(
		httpx.WithBaseURL(httpServer.URL),
	)
	if err != nil {
		fmt.Println(err)
		return
	}

	c := &Client{
		httpx: httpxClient,
	}

	v, err := c.CreateX(context.Background(), CreateXRequest{
		ID: "123",
	})
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(v.RequestID)
}
Output:

123+

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrValidating      = fmt.Errorf("failed to validate request")
	ErrMarshal         = fmt.Errorf("failed to marshal request body")
	ErrRequest         = fmt.Errorf("failed to do request")
	ErrResponseFuncNil = fmt.Errorf("response function is nil")
)
View Source
var ResponseErrLimit int64 = 1 << 20 // 1MB

Functions

func RequestCtx added in v0.2.1

func RequestCtx(ctx context.Context, opts ...OptionContext) context.Context

RequestCtx adds the request options to the context.

func RetryPolicy

func RetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error)

RetryPolicy provides a default callback for Client.CheckRetry, which will retry on connection errors and server errors.

func UnexpectedResponse added in v0.2.5

func UnexpectedResponse(resp *http.Response) error

func UnexpectedResponseError

func UnexpectedResponseError(resp *http.Response) error

Types

type Body added in v0.2.0

type Body interface {
	// Body returns the body to be sent.
	Body() io.Reader
}

type BodyJSON added in v0.2.0

type BodyJSON interface {
	// BodyJSON can return any type that can be marshaled to JSON.
	// Automatically sets Content-Type to application/json.
	BodyJSON() interface{}
}

type Client

type Client struct {
	HttpClient *http.Client
	BaseURL    *url.URL
}

func NewClient

func NewClient(opts ...OptionClient) (*Client, error)

func (*Client) Do

func (c *Client) Do(ctx context.Context, req Request, resp interface{}) error

Do sends an HTTP request and json unmarshals the response body to data.

Do work same as DoWithFunc with defaultResponseFunc.

func (*Client) DoWithFunc

func (c *Client) DoWithFunc(ctx context.Context, req Request, fn func(*http.Response) error) error

DoWithFunc sends an HTTP request and calls the response function.

Request additional implements RequestValidator, QueryStringGenerator, Header, Body, BodyJSON

func (*Client) Request added in v0.2.0

func (c *Client) Request(ctx context.Context, method, path string, body io.Reader, header http.Header, fn func(*http.Response) error) error

Request sends an HTTP request and calls the response function.

func (*Client) RequestWithURL added in v0.2.3

func (c *Client) RequestWithURL(ctx context.Context, method, URL string, body io.Reader, header http.Header, fn func(*http.Response) error) error

RequestWithURL sends an HTTP request and calls the response function.

type Header interface {
	// Header returns the header to be sent.
	Header() http.Header
}

type OptionClient added in v0.2.1

type OptionClient func(*optionClient)

OptionClient is a function that configures the client.

func WithBackoff

func WithBackoff(backoff retryablehttp.Backoff) OptionClient

WithBackoff configures the client to use the provided backoff.

func WithBaseURL

func WithBaseURL(baseURL string) OptionClient

WithBaseURL configures the client to use the provided base URL.

func WithCtx

func WithCtx(ctx context.Context) OptionClient

WithCtx configures the client to use the provided context.

func WithDisableBaseURLCheck added in v0.2.3

func WithDisableBaseURLCheck(baseURLCheck bool) OptionClient

WithDisableBaseURLCheck configures the client to disable base URL check.

func WithDisableRetry

func WithDisableRetry(disableRetry bool) OptionClient

WithDisableRetry configures the client to disable retry.

func WithHttpClient

func WithHttpClient(httpClient *http.Client) OptionClient

WithHttpClient configures the client to use the provided http client.

func WithInsecureSkipVerify

func WithInsecureSkipVerify(insecureSkipVerify bool) OptionClient

WithInsecureSkipVerify configures the client to skip TLS verification.

func WithLogger

func WithLogger(logger interface{}) OptionClient

WithLogger configures the client to use the provided logger.

func WithMaxConnections

func WithMaxConnections(maxConnections int) OptionClient

WithMaxConnections configures the client to use the provided maximum number of idle connections.

func WithPooledClient

func WithPooledClient(pooledClient bool) OptionClient

func WithRetryMax

func WithRetryMax(retryMax int) OptionClient

WithRetryMax configures the client to use the provided maximum number of retry.

func WithRetryPolicy

func WithRetryPolicy(retryPolicy retryablehttp.CheckRetry) OptionClient

WithRetryPolicy configures the client to use the provided retry policy.

func WithRetryWaitMax

func WithRetryWaitMax(retryWaitMax time.Duration) OptionClient

WithRetryWaitMax configures the client to use the provided maximum wait time.

func WithRetryWaitMin

func WithRetryWaitMin(retryWaitMin time.Duration) OptionClient

WithRetryWaitMin configures the client to use the provided minimum wait time.

func WithTransportWrapper

func WithTransportWrapper(f func(context.Context, http.RoundTripper) (http.RoundTripper, error)) OptionClient

WithTransportWrapper configures the client to wrap the default transport.

func WithZerologLogger

func WithZerologLogger(logger zerolog.Logger) OptionClient

WithZerologLogger configures the client to use the provided logger.

type OptionContext added in v0.2.1

type OptionContext func(*optionContext)

func CtxWithBaseURL added in v0.2.3

func CtxWithBaseURL(baseURL *url.URL) OptionContext

func CtxWithHeader added in v0.2.1

func CtxWithHeader(key, value string) OptionContext

WithHeader sets the header to be sent.

func CtxWithRetry added in v0.2.1

func CtxWithRetry(retry Retry) OptionContext

WithRetry sets the retry to be sent.

Just work with our RetryPolicy.

type QueryStringGenerator

type QueryStringGenerator interface {
	// ToQuery returns the query string to be sent.
	ToQuery() url.Values
}

type Request

type Request interface {
	// Method returns the HTTP method.
	Method() string
	// Path returns the path to be sent.
	Path() string
}

type RequestValidator

type RequestValidator interface {
	// Validate returns error if request is invalid.
	Validate() error
}

type Retry

type Retry struct {
	DisableRetry        bool
	DisabledStatusCodes []int
	EnabledStatusCodes  []int
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL