requests

package module
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2024 License: Apache-2.0 Imports: 24 Imported by: 12

README

requests

high-level HTTP client for Go.


requests is a high-level, API-centric HTTP client for Go projects. It is meant to provide a more comfortable mechanism to perform requests to HTTP APIs (rather than making general requests), and to prevent common mistakes made when using net/http directly.

With requests, one must not need to remember to read HTTP responses in full (so Go can reuse TCP connections), nor to close response bodies. Handling of JSON data - be it in requests or responses - is made easier by way of built-in encoders/decoders. An automatic retry mechanism is also included.

The library allows a "DRY" (Dont Repeat Yourself) approach to REST API usage by introducing API-specific dependencies into the client object. For example, authorization headers and response handlers can be set in the client object, and all generated requests will automatically include them.

Install

go get -u github.com/ido50/requests

Usage

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/ido50/requests"
)

const apiURL = "https://my.api.com/v2"

type RequestBody struct {
	Title   string   `json:"title"`
	Tags    []string `json:"tags"`
	Publish bool     `json:"publish"`
}

type ResponseBody struct {
	ID   int64     `json:"id"`
	Date time.Time `json:"date"`
}

func main() {
	client := requests.
		NewClient(apiURL).
		Accept("application/json").
		BasicAuth("user", "pass").
		RetryLimit(3)

	var res ResponseBody

	err := client.
		NewRequest("POST", "/articles").
		JSONBody(RequestBody{
			Title:   "Test Title",
			Tags:    []string{"test", "stories"},
			Publish: true,
		}).
		ExpectedStatus(http.StatusCreated).
		Into(&res).
		Run()
	if err != nil {
		panic(err)
	}

	fmt.Printf("Created article %d on %s\n", res.ID, res.Date.Format(time.RFC3339))
}

Documentation

Overview

Package requests is a high-level, API-centric HTTP client for Go projects. It is meant to provide a more comfortable mechanism to perform requests to HTTP APIs (rather than making general requests), and to prevent common mistakes made when using net/http directly.

With requests, one must not need to remember to read HTTP responses in full (so Go can reuse TCP connections), nor to close response bodies. Handling of JSON data - be it in requests or responses - is made easier by way of built-in encoders/decoders. An automatic retry mechanism is also included.

The library allows a "DRY" (Dont Repeat Yourself) approach to REST API usage by introducing API-specific dependencies into the client object. For example, authorization headers and response handlers can be set in the client object, and all generated requests will automatically include them.

Usage

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/ido50/requests"
)

const apiURL = "https://my.api.com/v2"

type RequestBody struct {
	Title   string   `json:"title"`
	Tags    []string `json:"tags"`
	Publish bool     `json:"publish"`
}

type ResponseBody struct {
	ID   int64     `json:"id"`
	Date time.Time `json:"date"`
}

func main() {
	client := requests.
		NewClient(apiURL).
		Accept("application/json").
		BasicAuth("user", "pass").
		RetryLimit(3)

	var res ResponseBody

	err := client.
		NewRequest("POST", "/articles").
		JSONBody(RequestBody{
			Title:   "Test Title",
			Tags:    []string{"test", "stories"},
			Publish: true,
		}).
		ExpectedStatus(http.StatusCreated).
		Into(&res).
		Run()
	if err != nil {
		panic(err)
	}

	fmt.Printf(
		"Created article %d on %s\n",
		res.ID, res.Date.Format(time.RFC3339),
	)
}

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrSizeExceeded is the error returned when the size of an HTTP response
	// is larger than the set limit
	ErrSizeExceeded = errors.New("response size exceeded limit")

	// ErrTimeoutReached is the error returned when a request times out
	ErrTimeoutReached = errors.New("timeout reached")

	// ErrNotAPointer is an error returned when the target variable provided for
	// a request's Run method is not a pointer.
	ErrNotAPointer = errors.New("target variable is not a string pointer")

	// ErrUnsupportedCompression is an error returned when attempting to send
	// requests with a compression algorithm unsupported by the library
	ErrUnsupportedCompression = errors.New("unsupported compression algorithm")

	// ErrUnsupportedBody is an error returned when the value provided to the
	// request's Body method is unsupported, i.e. it is not a byte string, a
	// string, or a reader
	ErrUnsupportedBody = errors.New("unsupported body")
)
View Source
var BaseDelay = 2 * time.Second

BaseDelay is the base delay for retrying requests. The library uses a backoff strategy, multiplying the delay between each attempt.

View Source
var DefaultTimeout = 2 * time.Minute

DefaultTimeout is the default timeout for requests made by the library. This can be overridden on a per-client and per-request basis.

Functions

func MultipartFile added in v1.4.0

func MultipartFile(fieldname string, fsys fs.FS, filepath string) *multipartSrc

MultipartFile adds a new part to a multipart request from the provided file in a filesystem.

func MultipartPart added in v1.4.0

func MultipartPart(fieldname, filename string, body interface{}) *multipartSrc

MultipartPart adds a new part to a multipart request with the provided field name, file name, and body, which may be a []byte value, a string, or a reader.

Types

type BodyHandlerFunc

type BodyHandlerFunc func(
	httpStatus int,
	contentType string,
	body io.Reader,
	target interface{},
) error

BodyHandlerFunc is a function that processes the response body and reads it into the target variable. It receives the status and content type of the response (the latter taken from the Content-Type header), the body reader, and the target variable (which is whatever was provided to the Into() method). It is not necessary to close the body or read it to its entirety.

type BodyProcessorFunc added in v1.6.0

type BodyProcessorFunc func(r io.Reader, w io.Writer) error

BodyProcessorFunc is a function that reads a request's body as []byte from a provider reader, and writes it to a provided writer, potentially modifying it in the process. Such a function can be used to modify request bodies right before they are sent.

type CompressionAlgorithm added in v1.2.0

type CompressionAlgorithm string

CompressionAlgorithm denotes compression algorithms supported by the library for compressed request bodies.

const (
	// CompressionAlgorithmNone represents no compression
	CompressionAlgorithmNone CompressionAlgorithm = ""

	// CompressionAlgorithmGzip represents the gzip compression algorithm
	CompressionAlgorithmGzip CompressionAlgorithm = "gzip"

	// CompressionAlgorithmDeflate represents the deflate compression algorithm
	CompressionAlgorithmDeflate CompressionAlgorithm = "deflate"
)

type ErrorHandlerFunc

type ErrorHandlerFunc func(
	httpStatus int,
	contentType string,
	body io.Reader,
) error

ErrorHandlerFunc is similar to BodyHandler, but is called when requests generate an unsuccessful response (defined as anything that is not one of the expected statuses). It receives the same parameters except "target", and is expected to return a formatted error to the client

type HTTPClient

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

HTTPClient represents a client for making requests to a web service or website. The client includes default options that are relevant for all requests (but can be overridden per-request).

func NewClient

func NewClient(baseURL string) *HTTPClient

NewClient creates a new HTTP client for the API whose base URL is provided.

func (*HTTPClient) Accept

func (cli *HTTPClient) Accept(accept string) *HTTPClient

Accept sets the response MIME type accepted by the client. Defaults to "application/json".

func (*HTTPClient) BasicAuth

func (cli *HTTPClient) BasicAuth(
	user string,
	pass string,
	headerName ...string,
) *HTTPClient

BasicAuth sets basic authentication headers for all HTTP requests made by the client (requests can override this on an individual basis). If a header name is provided as the third argument, the authentication data will be set into that header instead of the standard "Authorization" header. This is mostly useful for Proxy-Authorization or custom headers.

func (*HTTPClient) BodyHandler

func (cli *HTTPClient) BodyHandler(handler BodyHandlerFunc) *HTTPClient

BodyHandler sets a customer handler function for all requests made by the client. If provided, the handler will be called with the response status, content type, and body reader. This allows customizing the way response bodies are parsed, for example if the API does not use JSON serialization. Usually, the library's internal handler is sufficient for API usage.

func (*HTTPClient) CompressWith added in v1.2.0

func (cli *HTTPClient) CompressWith(alg CompressionAlgorithm) *HTTPClient

CompressWith sets a compression algorithm to apply to all request bodies. Compression is optional, in that if it fails, for any reason, requests will not fail, but instead be sent without compression. Note that there is no need to use this to support decompression of responses, the library handles decompressions automatically.

func (*HTTPClient) CustomHTTPClient added in v1.3.0

func (cli *HTTPClient) CustomHTTPClient(cl *http.Client) *HTTPClient

CustomHTTPClient sets a custom HTTP client for the underlaying net layer

func (*HTTPClient) Do

func (cli *HTTPClient) Do(req *http.Request) (*http.Response, error)

Do performs an HTTP request represented as a net/http.Request object. This method was added so that an HTTPClient object will implement a common interface for HTTP clients. Generally, there is no need to use this method.

func (*HTTPClient) ErrorHandler

func (cli *HTTPClient) ErrorHandler(handler ErrorHandlerFunc) *HTTPClient

ErrorHandler sets a custom handler function for all requests made by the client. Whenever a request is answered with an error response (or optionally in an unexpected status), the handler is called. This allows parsing API error structures so more information can be returned in case of failure.

func (*HTTPClient) Header

func (cli *HTTPClient) Header(key, value string) *HTTPClient

Header sets a common header value for all requests made by the client.

func (*HTTPClient) Logger

func (cli *HTTPClient) Logger(logger *zap.Logger) *HTTPClient

Logger sets the logger used by the library. Currently, requests uses go.uber.org/zap for logging purposes. All log messages are in the DEBUG level.

func (*HTTPClient) NewRequest

func (cli *HTTPClient) NewRequest(method, path string) *HTTPRequest

NewRequest creates a new request object. Requests are progressively composed using a builder/method-chain pattern. The HTTP method and path within the API must be provided. Remember that the client already includes a base URL, so the request URL will be a concatenation of the base URL and the provided path. `path` can be empty.

func (*HTTPClient) NoTLSVerify

func (cli *HTTPClient) NoTLSVerify(enabled bool) *HTTPClient

NoTLSVerify allows ignoring invalid or self-signed TLS certificates presented by HTTPS servers.

func (*HTTPClient) RetryLimit

func (cli *HTTPClient) RetryLimit(limit uint8) *HTTPClient

RetryLimit sets the maximum amount of times requests that failed due to connection issues should be retried. Defaults to 0. Requests are retried with a backoff strategy, with the first retry attempt occurring two seconds after the original request, and the delay before each subsequent attempt is multiplied by two.

func (*HTTPClient) SetRenegotiation

func (cli *HTTPClient) SetRenegotiation(support tls.RenegotiationSupport) *HTTPClient

SetRenegotiation allows setting the TLS renegotiation level. See crypto/tls for more information.

func (*HTTPClient) SetTLS

func (cli *HTTPClient) SetTLS(
	certPEMBlock, keyPEMBlock, caCert []byte,
) *HTTPClient

SetTLS allows creating a custom TLS transport. Often combined with SetRenegotiation.

func (*HTTPClient) Timeout

func (cli *HTTPClient) Timeout(dur time.Duration) *HTTPClient

Timeout sets the total timeout for requests made by the client. The default timeout is 2 minutes.

type HTTPRequest

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

HTTPRequest represents a single HTTP request to the web service defined in the client.

func (*HTTPRequest) Accept

func (req *HTTPRequest) Accept(accept string) *HTTPRequest

Accept sets the accepted MIME type for the request. This takes precedence over the MIME type provided to the client object itself.

func (*HTTPRequest) BasicAuth

func (req *HTTPRequest) BasicAuth(
	user, pass string,
	headerName ...string,
) *HTTPRequest

BasicAuth allows setting basic authentication header for the request. Usually, this will be done on the client object rather than the request object, but this method allows overriding authentication for specific requests.

func (*HTTPRequest) Body

func (req *HTTPRequest) Body(body interface{}, contentType string) *HTTPRequest

ReaderBody sets a custom body for the request from an io.ReadCloser, io.Reader, []byte or string. The content type of the data must be provided.

func (*HTTPRequest) BodyHandler

func (req *HTTPRequest) BodyHandler(handler BodyHandlerFunc) *HTTPRequest

BodyHandler sets a custom body handler for the request.

func (*HTTPRequest) CompressWith added in v1.2.0

func (req *HTTPRequest) CompressWith(alg CompressionAlgorithm) *HTTPRequest

CompressWith sets a compression algorithm to apply to all request bodies. Compression is optional, in that if it fails, for any reason, requests will not fail, but instead be sent without compression. Note that there is no need to use this to support decompression of responses, the library handles decompressions automatically.

func (*HTTPRequest) Cookie

func (req *HTTPRequest) Cookie(cookie *http.Cookie) *HTTPRequest

Cookie sets a cookie for the request.

func (*HTTPRequest) CookiesInto

func (req *HTTPRequest) CookiesInto(into *[]*http.Cookie) *HTTPRequest

CookiesInto allows storing cookies in the response into a slice of cookies. The same comments as for HeaderInto apply here as well.

func (*HTTPRequest) ErrorHandler

func (req *HTTPRequest) ErrorHandler(handler ErrorHandlerFunc) *HTTPRequest

ErrorHandler sets a custom error handler for the request.

func (*HTTPRequest) ExpectedStatus

func (req *HTTPRequest) ExpectedStatus(status int) *HTTPRequest

ExpectedStatus sets the HTTP status that the application expects to receive for the request. If the status received is different than the expected status, the library will return an error, and the error handler will be executed.

func (*HTTPRequest) ExpectedStatuses

func (req *HTTPRequest) ExpectedStatuses(statuses ...int) *HTTPRequest

ExpectedStatuses is the same as ExpectedStatus, but allows setting multiple expected statuses.

func (*HTTPRequest) FileBody added in v1.4.0

func (req *HTTPRequest) FileBody(fsys fs.FS, filepath, contentType string) *HTTPRequest

FileBody sets the request body to be read from the provided filesystem and file path. The content type must be provided.

func (*HTTPRequest) Header

func (req *HTTPRequest) Header(key, value string) *HTTPRequest

Header sets the value of a header for the request.

func (*HTTPRequest) HeaderInto

func (req *HTTPRequest) HeaderInto(header string, into *string) *HTTPRequest

HeaderInto allows storing the value of a header from the response into a string variable. Since the requests library is made to quickly perform requests to REST APIs, and only a small number of response headers is usually read by application code (if at all), there is no response object that allows viewing headers. Therefore, any code that is interested in reading a response header must declare that in advance and provide a target variable.

func (*HTTPRequest) Into

func (req *HTTPRequest) Into(into interface{}) *HTTPRequest

Into sets the target variable to which the response body should be parsed. If the API returns JSON, then this should be a pointer to a struct that represents the expected format. If using a custom body handler, this variable will be provided to the handler.

func (*HTTPRequest) JSONBody

func (req *HTTPRequest) JSONBody(body interface{}) *HTTPRequest

JSONBody encodes the provided Go value into JSON and sets it as the request body.

func (*HTTPRequest) MultipartBody added in v1.4.0

func (req *HTTPRequest) MultipartBody(srcs ...*multipartSrc) *HTTPRequest

MultipartBody creates a multipart/form-data body from one or more sources, which may be file objects, bytes, strings or any reader.

func (*HTTPRequest) QueryParam

func (req *HTTPRequest) QueryParam(key, value string) *HTTPRequest

QueryParam adds a query parameter and value to the request.

func (*HTTPRequest) ReqBodyProcessor added in v1.6.0

func (req *HTTPRequest) ReqBodyProcessor(fn BodyProcessorFunc) *HTTPRequest

ReqBodyProcessor adds a BodyProcessorFunc to the request. This function will be called right before the request is issued and can be used to modify the request body. The processor function MUST read AND write the entire body, and should not close it.

func (*HTTPRequest) RetryLimit

func (req *HTTPRequest) RetryLimit(limit uint8) *HTTPRequest

RetryLimit sets the maximum amount of retries for the request. This takes precedence over the limit provided to the client object itself.

func (*HTTPRequest) Run

func (req *HTTPRequest) Run() error

Run finalizes the request and executes it. The returned error will be `nil` only if the request was successfully created, sent and a successful (or expected) status code was returned from the server.

func (*HTTPRequest) RunContext

func (req *HTTPRequest) RunContext(ctx context.Context) error

RunContext is the same as Run, but executes the request with the provided context value.

func (*HTTPRequest) SizeLimit

func (req *HTTPRequest) SizeLimit(limit int64) *HTTPRequest

SizeLimit allows limiting the size of response bodies accepted by the client. If the response size is larger than the limit, `ErrSizeExceeded` will be returned.

func (*HTTPRequest) StatusInto

func (req *HTTPRequest) StatusInto(into *int) *HTTPRequest

StatusInto allows storing the status of the response into a variable. The same comments as for HeaderInto apply here as well.

func (*HTTPRequest) Subscribe added in v1.5.0

func (req *HTTPRequest) Subscribe(ctx context.Context, messages chan []byte) error

Issue the request, expecting a text/event-stream response, and subscribe to that stream. Events (well, messages) from the server will be sent as-is to the provided channel. When all messages have been read, the channel is automatically closed.

func (*HTTPRequest) Timeout

func (req *HTTPRequest) Timeout(dur time.Duration) *HTTPRequest

Timeout sets the timeout for the request. This takes precedence over the timeout provided to the client object itself.

Jump to

Keyboard shortcuts

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