httpcli

package
v1.67.0 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 13 Imported by: 3

README

Package httpcli

Пакет httpcli предоставляет расширенный HTTP-клиент с поддержкой middleware, ретраев, различных типов запросов и обработки ошибок. Интегрируется с системами логирования, метриками и политиками повторов.

Types

Client

Основная структура для выполнения HTTP-запросов. Управляет настройками транспорта, middleware и глобальными параметрами.

Methods:

New(opts ...Option) *Client

Конструктор клиента с настройками по умолчанию. Принимает опции:

  • WithMiddlewares(mws ...Middleware) Option – добавляет цепочку middleware к запросам клиента.
NewWithClient(cli *http.Client, opts ...Option) *Client

Конструктор клиента на основе базового клиента из стандартной библиотеки net/http.

(c *Client) GlobalRequestConfig() *GlobalRequestConfig

Получить глобальную конфигурацию запросов (таймауты, базовый URL, заголовки и т.д.).

(c *Client) Post(url string) *RequestBuilder

Создать билдер для POST-запроса. Аналогичные методы: Get(), Put(), Delete(), Patch().

(c *Client) Execute(ctx context.Context, builder *RequestBuilder) (*Response, error)

Выполнить HTTP-запрос из переданного билдера.

RequestBuilder

Структура для построения HTTP-запросов с цепочкой методов.

Methods:

(b *RequestBuilder) Header(name string, value string) *RequestBuilder

Добавить заголовок к запросу.

(b *RequestBuilder) BaseUrl(baseUrl string) *RequestBuilder

Установить базовый url в запросе на переданный.

(b *RequestBuilder) Url(url string) *RequestBuilder

Установить url запроса на переданный.

(b *RequestBuilder) Method(method string) *RequestBuilder

Изменить HTTP-метод запроса на указанный.

Добавить cookie к запросу.

(b *RequestBuilder) RequestBody(body []byte) *RequestBuilder

Добавить тело запроса.

(b *RequestBuilder) JsonRequestBody(value any) *RequestBuilder

Добавить тело запроса в формате JSON. Использует пакет json, поэтому может маршалить без тэгов в camelCase.

(b *RequestBuilder) JsonResponseBody(responsePtr any) *RequestBuilder

Записать JSON-ответ на запрос по переданному указателю. Операция выполнится только при статус кодах от 200 до 299.

(b *RequestBuilder) FormDataRequestBody(data map[string][]string) *RequestBuilder

Добавить тело запроса в формате формы.

(b *RequestBuilder) BasicAuth(ba BasicAuth) *RequestBuilder

Добавить базую аутентификацию в запрос.

(b *RequestBuilder) QueryParams(queryParams map[string]any) *RequestBuilder

Добавить query-параметры в запрос.

(b *RequestBuilder) Retry(cond RetryCondition, retryer Retryer) *RequestBuilder

Задать политику ретраев по заданному условию. Пример условия: httpcli.IfErrorOr5XXStatus()

(b *RequestBuilder) MultipartRequestBody(data *MultipartData) *RequestBuilder

Устанавить multipart/form-data тело запроса (для передачи файлов). Не поддерживает Request.Body в middleware и игнорирует ретраи.

(b *RequestBuilder) StatusCodeToError() *RequestBuilder

Возвращает ErrorResponse как ошибку при Response.IsSuccess = true.

(b *RequestBuilder) Timeout(timeout time.Duration) *RequestBuilder

Установить тайм-аут для каждой попытки запроса, тайм-аут по умолчанию 15 секунд.

(b *RequestBuilder) Middlewares(middlewares ...Middleware) *RequestBuilder

Добавить middleware в цепочку запроса.

(b *RequestBuilder) Do(ctx context.Context) (*Response, error)

Выполнить запрос собранный билдером.

(b *RequestBuilder) DoWithoutResponse(ctx context.Context) error

То же самое, что и Do, но записывает ответ по переданному раннее в билдере указателю.

(b *RequestBuilder) DoWithoutResponse(ctx context.Context) error

То же самое, что и Do, но не возвращает объект Response. Записывает тело ответа по переданному в метод JsonResponseBody указателю.

(b *RequestBuilder) DoAndReadBody(ctx context.Context) ([]byte, int, error)

То же самое, что и Do, но считывает из ответа только тело и статус код, а затем возвращает их.

Usage

Default
package main

import (
	"context"
	"log"

	"github.com/txix-open/isp-kit/http/httpcli"
)

type user struct {
	Id   string
	Name string
}

func main() {
	cli := httpcli.New()
	u := new(user)

	resp, err := cli.Get("https://api.example.com/users/1").
		JsonResponseBody(u).
		Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Close()

	if !resp.IsSuccess() {
		log.Fatalf("invalid status code: %d", resp.StatusCode())
	}
	log.Println(u.Name) /* result decoded from JSON */
}

Without response
package main

import (
	"context"
	"log"

	"github.com/txix-open/isp-kit/http/httpcli"
)

type user struct {
	Id   string
	Name string
}

func main() {
	cli := httpcli.New()
	u := new(user)

	err := cli.Get("https://api.example.com/users/1").
		JsonResponseBody(u).
		StatusCodeToError().
		DoWithoutResponse(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	log.Println(u.Name) /* result decoded from JSON */
}

Exponential retries
package main

import (
	"context"
	"log"
	"time"

	"github.com/txix-open/isp-kit/http/httpcli"
	"github.com/txix-open/isp-kit/retry"
)

type user struct {
	Id   string
	Name string
}

const (
	maxRetryElapsedTime = 5 * time.Second
)

func main() {
	cli := httpcli.New()
	u := user{
		Id:   "x.x",
		Name: "Mark",
	}

	err := cli.Post("https://api.example.com/users").
		JsonRequestBody(u).
		Retry(httpcli.IfErrorOr5XXStatus(), retry.NewExponentialBackoff(maxRetryElapsedTime)).
		StatusCodeToError().
		DoWithoutResponse(context.Background())
	if err != nil {
		log.Fatal(err)
	}
}

Documentation

Overview

Package httpcli provides a high-level HTTP client with support for middleware, retries, and flexible request/response handling.

The package offers a builder pattern API for constructing HTTP requests with various options including headers, cookies, authentication, and request bodies.

Index

Constants

This section is empty.

Variables

View Source
var (
	ReadingResponseMetricHookKey = ReadingResponseMetricHook{}
)

nolint:gochecknoglobals

View Source
var (
	StdClient = &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: defaultTransportDialContext(&net.Dialer{
				Timeout:   3 * time.Second,
				KeepAlive: 30 * time.Second,
			}),
			ForceAttemptHTTP2:     true,
			MaxIdleConns:          512,
			MaxIdleConnsPerHost:   32,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   5 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
			ReadBufferSize:        8 * 1024,
			WriteBufferSize:       8 * 1024,
		},
	}
)

StdClient is the default http.Client used by New() with optimized connection pooling and HTTP/2 support.

nolint:mnd,gochecknoglobals

Functions

func CreateFormFile added in v1.41.3

func CreateFormFile(
	w *multipart.Writer,
	header map[string]string,
	fieldname string,
	filename string,
) (io.Writer, error)

CreateFormFile creates a form file part in the multipart writer with custom headers.

Sets the Content-Disposition header with the field name and filename.

func NoRetries

func NoRetries() (RetryCondition, Retryer)

NoRetries returns a retry condition and retryer that disable retry behavior.

nolint:ireturn

Types

type BasicAuth

type BasicAuth struct {
	Username string
	Password string
}

BasicAuth holds HTTP basic authentication credentials.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a high-level HTTP client with support for middleware, retries, and flexible request/response handling.

func New

func New(opts ...Option) *Client

New creates a new Client with default configuration. It uses StdClient as the underlying http.Client.

Options are applied in the order they are passed.

func NewWithClient

func NewWithClient(cli *http.Client, opts ...Option) *Client

NewWithClient creates a new Client with a custom http.Client. This allows customization of the underlying transport and connection pooling.

Options are applied in the order they are passed.

func (*Client) Delete

func (c *Client) Delete(url string) *RequestBuilder

Delete creates a new DELETE request builder for the given URL.

func (*Client) Execute added in v1.41.2

func (c *Client) Execute(ctx context.Context, builder *RequestBuilder) (*Response, error)

Execute sends an HTTP request using the provided builder and returns the response. It handles request construction, middleware execution, and response processing.

If a responseBody is set on the builder and the response is successful, the response body will be automatically unmarshalled into the target.

nolint:cyclop

func (*Client) Get

func (c *Client) Get(url string) *RequestBuilder

Get creates a new GET request builder for the given URL.

func (*Client) GlobalRequestConfig

func (c *Client) GlobalRequestConfig() *GlobalRequestConfig

GlobalRequestConfig returns the global request configuration for this client. Settings here apply to all requests made by this client.

func (*Client) Patch

func (c *Client) Patch(url string) *RequestBuilder

Patch creates a new PATCH request builder for the given URL.

func (*Client) Post

func (c *Client) Post(url string) *RequestBuilder

Post creates a new POST request builder for the given URL.

func (*Client) Put

func (c *Client) Put(url string) *RequestBuilder

Put creates a new PUT request builder for the given URL.

type ErrorResponse

type ErrorResponse struct {
	Url        *url.URL
	StatusCode int
	Body       []byte
}

ErrorResponse represents an HTTP error response with status code and body.

nolint:errname

func (ErrorResponse) Error

func (e ErrorResponse) Error() string

Error returns a formatted error message containing the URL, status code, and body.

type GlobalRequestConfig

type GlobalRequestConfig struct {
	Timeout   time.Duration
	BaseUrl   string
	BasicAuth *BasicAuth
	Cookies   []*http.Cookie
	Headers   map[string]string
}

GlobalRequestConfig holds default settings that apply to all requests created by a Client.

func NewGlobalRequestConfig

func NewGlobalRequestConfig() *GlobalRequestConfig

NewGlobalRequestConfig creates a new GlobalRequestConfig with default values.

Default timeout is 15 seconds.

type Middleware

type Middleware func(next RoundTripper) RoundTripper

Middleware is a function that wraps a RoundTripper with additional functionality. Middlewares are executed in the order they are added.

func SetContentLength added in v1.39.0

func SetContentLength() Middleware

SetContentLength is a middleware that sets the Content-Length header for requests with a known body size.

Skips setting Content-Length for multipart requests where the size is unknown.

type MultipartData

type MultipartData struct {
	Files  map[string]MultipartFieldFile
	Values map[string]string
}

MultipartData holds multipart/form-data request content including files and values.

type MultipartFieldFile

type MultipartFieldFile struct {
	Headers  map[string]string
	Filename string
	Reader   io.ReadCloser
}

MultipartFieldFile represents a single file in a multipart form.

type Option

type Option func(c *Client)

Option is a function that configures a Client.

func WithMiddlewares

func WithMiddlewares(mws ...Middleware) Option

WithMiddlewares adds one or more middlewares to the client. Middlewares are executed in the order they are provided.

type ReadingResponseMetricHook added in v1.38.0

type ReadingResponseMetricHook struct{}

ReadingResponseMetricHook is a context key for hooks that are called when the response body is fully read. Used for metrics collection.

type Request

type Request struct {
	Raw *http.Request
	// contains filtered or unexported fields
}

Request wraps an http.Request with additional metadata for middleware processing.

func (*Request) Body

func (r *Request) Body() []byte

Body returns the request body as bytes.

Returns an empty slice if MultipartRequestBody was used, as multipart data is streamed directly and not buffered.

type RequestBodyWriter

type RequestBodyWriter interface {
	Write(req *http.Request, w io.Writer) error
}

RequestBodyWriter defines the interface for writing request bodies.

type RequestBuilder

type RequestBuilder struct {
	// contains filtered or unexported fields
}

RequestBuilder provides a fluent API for constructing HTTP requests. It supports method chaining for setting various request options.

func NewRequestBuilder

func NewRequestBuilder(
	method string,
	url string,
	cfg *GlobalRequestConfig,
	execute func(ctx context.Context, req *RequestBuilder) (*Response, error),
) *RequestBuilder

NewRequestBuilder creates a new RequestBuilder with the given HTTP method, URL, global configuration, and execute function.

func (*RequestBuilder) BaseUrl added in v1.41.2

func (b *RequestBuilder) BaseUrl(baseUrl string) *RequestBuilder

BaseUrl sets the base URL that will be prepended to the request URL. Useful for API clients with a fixed base path.

func (*RequestBuilder) BasicAuth

func (b *RequestBuilder) BasicAuth(ba BasicAuth) *RequestBuilder

BasicAuth sets HTTP basic authentication credentials for the request.

func (*RequestBuilder) Cookie

func (b *RequestBuilder) Cookie(cookie *http.Cookie) *RequestBuilder

Cookie adds a cookie to the request.

func (*RequestBuilder) Do

func (b *RequestBuilder) Do(ctx context.Context) (*Response, error)

Do executes the request and returns the response.

Returns the response and any error that occurred during execution. If StatusCodeToError was called and the response is not successful, returns ErrorResponse as the error.

func (*RequestBuilder) DoAndReadBody

func (b *RequestBuilder) DoAndReadBody(ctx context.Context) ([]byte, int, error)

DoAndReadBody executes the request and returns the response body.

Returns the response body, status code, and any error. Automatically closes the response to release resources.

func (*RequestBuilder) DoWithoutResponse

func (b *RequestBuilder) DoWithoutResponse(ctx context.Context) error

DoWithoutResponse executes the request and discards the response.

Returns any error that occurred during execution. Automatically closes the response to release resources.

func (*RequestBuilder) FormDataRequestBody

func (b *RequestBuilder) FormDataRequestBody(data map[string][]string) *RequestBuilder

FormDataRequestBody sets the request body as form-encoded data. Sets Content-Type to application/x-www-form-urlencoded.

func (*RequestBuilder) Header

func (b *RequestBuilder) Header(name string, value string) *RequestBuilder

Header sets a request header with the given name and value.

func (*RequestBuilder) JsonRequestBody

func (b *RequestBuilder) JsonRequestBody(value any) *RequestBuilder

JsonRequestBody sets the request body as JSON from the given value. Sets Content-Type to application/json.

func (*RequestBuilder) JsonResponseBody

func (b *RequestBuilder) JsonResponseBody(responsePtr any) *RequestBuilder

JsonResponseBody configures the builder to unmarshal the JSON response body into the provided pointer if the status code is in the 2xx range.

func (*RequestBuilder) Method added in v1.41.2

func (b *RequestBuilder) Method(method string) *RequestBuilder

Method sets the HTTP method for the request.

func (*RequestBuilder) Middlewares added in v1.39.0

func (b *RequestBuilder) Middlewares(middlewares ...Middleware) *RequestBuilder

Middlewares adds one or more middlewares to be executed for this specific request. These are executed after the client's global middlewares.

func (*RequestBuilder) MultipartRequestBody

func (b *RequestBuilder) MultipartRequestBody(data *MultipartData) *RequestBuilder

MultipartRequestBody sets up multipart/form-data request with files and values.

This is useful for uploading large files as data is streamed and not buffered in memory.

Note: This disables retry support and request body access in middlewares.

func (*RequestBuilder) QueryParams

func (b *RequestBuilder) QueryParams(queryParams map[string]any) *RequestBuilder

QueryParams sets query parameters for the request URL. Values are converted to strings using fmt.Sprintf.

func (*RequestBuilder) RequestBody

func (b *RequestBuilder) RequestBody(body []byte) *RequestBuilder

RequestBody sets the request body from a byte slice.

func (*RequestBuilder) Retry

func (b *RequestBuilder) Retry(cond RetryCondition, retryer Retryer) *RequestBuilder

Retry configures retry behavior for the request. The condition determines when to retry, and the retryer controls the retry logic.

func (*RequestBuilder) StatusCodeToError

func (b *RequestBuilder) StatusCodeToError() *RequestBuilder

StatusCodeToError enables automatic error conversion for non-success status codes.

When enabled and the response status is not in the 2xx range, Do() returns an ErrorResponse containing the status code and body.

func (*RequestBuilder) Timeout

func (b *RequestBuilder) Timeout(timeout time.Duration) *RequestBuilder

Timeout sets the timeout duration for the request attempt.

Defaults to 15 seconds if not specified.

func (*RequestBuilder) Url added in v1.41.2

func (b *RequestBuilder) Url(url string) *RequestBuilder

Url sets the request URL, overriding any previously set URL.

type Response

type Response struct {
	Raw *http.Response
	// contains filtered or unexported fields
}

Response wraps an http.Response with buffering and lifecycle management.

func (*Response) BodyCopy

func (r *Response) BodyCopy() ([]byte, error)

BodyCopy returns a copy of the response body as bytes.

The returned slice remains valid even after calling Close().

func (*Response) Close

func (r *Response) Close()

Close releases all resources associated with the Response, including buffers, TCP connections, and context.

After calling Close(), any bytes slice returned by UnsafeBody() or BodyCopy() should not be accessed.

func (*Response) IsSuccess

func (r *Response) IsSuccess() bool

IsSuccess returns true if the response status code is in the 2xx range.

func (*Response) StatusCode

func (r *Response) StatusCode() int

StatusCode returns the HTTP status code of the response.

func (*Response) UnsafeBody added in v1.51.0

func (r *Response) UnsafeBody() ([]byte, error)

UnsafeBody reads and returns the full response body as bytes.

After calling Close(), the returned data is no longer valid. Use BodyCopy() if you need the data after calling Close().

Do not call Close() or modify the returned slice if you want to use the data outside the current scope.

type ResponseBodyReader

type ResponseBodyReader interface {
	Read(r io.Reader) error
}

ResponseBodyReader defines the interface for reading response bodies.

type RetryCondition

type RetryCondition func(err error, response *Response) error

RetryCondition is a function that determines whether to retry based on the error and response. Returns nil if no retry is needed.

func IfErrorOr5XXStatus

func IfErrorOr5XXStatus() RetryCondition

IfErrorOr5XXStatus returns a retry condition that retries on network errors or 5xx status codes.

type Retryer

type Retryer interface {
	Do(ctx context.Context, f func() error) error
}

Retryer defines the interface for retry logic. Implementations control when and how many times to retry failed operations.

type RoundTripper

type RoundTripper interface {
	RoundTrip(ctx context.Context, request *Request) (*Response, error)
}

RoundTripper defines the interface for executing HTTP requests. Implementations can wrap requests with middleware functionality.

type RoundTripperFunc

type RoundTripperFunc func(ctx context.Context, request *Request) (*Response, error)

RoundTripperFunc is a function type that implements the RoundTripper interface.

func (RoundTripperFunc) RoundTrip

func (f RoundTripperFunc) RoundTrip(ctx context.Context, request *Request) (*Response, error)

RoundTrip executes an HTTP request using the function.

Jump to

Keyboard shortcuts

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