rest

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Mar 3, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Overview

Package rest provides a simple and flexible Go HTTP client for making RESTful API requests.

It supports various HTTP methods, content types (JSON, XML, FORM), and advanced features like caching, authentication, compression, and tracing.

Basic Usage

The package provides package-level functions for quick requests using a default client:

response := rest.Get("https://api.example.com/users")
if response.IsOk() {
    var users []User
    err := response.FillUp(&users)
    // ...
}

Advanced Configuration

For more control, create and configure a Client:

client := &rest.Client{
    BaseURL: "https://api.example.com",
    Timeout: 5 * time.Second,
    ContentType: rest.JSON,
    EnableCache: true,
}
response := client.Post("/users", newUser)

Features

  • Synchronous and Asynchronous requests.
  • Built-in support for JSON, XML, and Form data.
  • Response caching with TTL and ETag support.
  • Authentication: Basic Auth and OAuth2.
  • Observability: OpenTelemetry tracing and Prometheus metrics.
  • Testing: Built-in mockup server for unit testing.

Index

Examples

Constants

View Source
const (
	// UserAgentHeader is the header name for the User-Agent.
	UserAgentHeader = "User-Agent"

	// ConnectionHeader is the header name for the Connection.
	ConnectionHeader = "Connection"

	// CacheControlHeader is the header name for Cache-Control directives.
	CacheControlHeader = "Cache-Control"

	// XOriginalURLHeader is a custom header used to track the original URL when using a mockup server.
	XOriginalURLHeader = "X-Original-Url"

	// ETagHeader is the header name for the ETag value.
	ETagHeader = "ETag"

	// LastModifiedHeader is the header name for the Last-Modified timestamp.
	LastModifiedHeader = "Last-Modified"

	// ExpiresHeader is the header name for the Expires timestamp.
	ExpiresHeader = "Expires"

	// AcceptEncodingHeader is the header name for the Accept-Encoding value.
	AcceptEncodingHeader = "Accept-Encoding"

	// ContentEncodingHeader is the header name for the Content-Encoding value.
	ContentEncodingHeader = "Content-Encoding"

	// IfModifiedSinceHeader is the header name for the If-Modified-Since timestamp.
	IfModifiedSinceHeader = "If-Modified-Since"

	// IfNoneMatchHeader is the header name for the If-None-Match value.
	IfNoneMatchHeader = "If-None-Match"
)

HTTP header constants used throughout the package.

View Source
const (
	// MIMETextXML is the MIME type for XML content in text format.
	MIMETextXML = "text/xml"

	// MIMETextPlain is the MIME type for plain text content.
	MIMETextPlain = "text/plain"

	// MIMEApplicationXML is the MIME type for XML content in application format.
	MIMEApplicationXML = "application/xml"

	// MIMEApplicationJSON is the MIME type for JSON content.
	MIMEApplicationJSON = "application/json"

	// MIMEApplicationProblemJSON is the MIME type for RFC7807 problem details in JSON format.
	MIMEApplicationProblemJSON = "application/problem+json"

	// MIMEApplicationProblemXML is the MIME type for RFC7807 problem details in XML format.
	MIMEApplicationProblemXML = "application/problem+xml"

	// MIMEApplicationForm is the MIME type for form-urlencoded content.
	MIMEApplicationForm = "application/x-www-form-urlencoded"
)

MIME type constants for various content types used in HTTP requests and responses.

View Source
const (
	// CanonicalContentTypeHeader is the canonical name of the Content-Type header.
	CanonicalContentTypeHeader = "Content-Type"

	// CanonicalAcceptHeader is the canonical name of the Accept header.
	CanonicalAcceptHeader = "Accept"
)

HTTP header constants for content negotiation.

Variables

View Source
var (
	// NumCounters is the number of keys to track frequency of (100K).
	NumCounters = 1e5

	// BufferItems is the number of keys per Get buffer.
	BufferItems = 64
)
View Source
var (
	// DefaultTimeout is the default timeout for all clients.
	DefaultTimeout = 500 * time.Millisecond
	// DefaultConnectTimeout is the time it takes to make a connection
	// Type: time.Duration.
	DefaultConnectTimeout = 1500 * time.Millisecond
)
View Source
var ErrMockNotFound = errors.New("mockUp nil")
View Source
var MaxCacheSize = 256 * MB

MaxCacheSize is the maximum total size of the cache in bytes. Default is 256 MB.

View Source
var Version = "1.0.0"

Functions

func AddMockups

func AddMockups(mocks ...*Mock) error

AddMockups ...

func Deserialize

func Deserialize[T any](response *Response) (T, error)

Deserialize is a generic helper that deserializes the response body into a new value of type T.

Example usage:

users, err := rest.Deserialize[[]User](response)
Example
package main

import (
	"fmt"
	"net/http"

	"github.com/arielsrv/go-restclient/rest"
)

type ExampleUser struct {
	Name string `json:"name"`
	ID   int    `json:"id"`
}

func main() {
	// Start the mockup server for a reproducible example
	rest.StartMockupServer()
	defer rest.StopMockupServer()
	rest.FlushMockups()

	// Configure a mock
	_ = rest.AddMockups(&rest.Mock{
		URL:          "https://api.example.com/users/1",
		HTTPMethod:   "GET",
		RespHTTPCode: 200,
		RespBody:     `{"name": "Leanne Graham", "id": 1}`,
		RespHeaders:  http.Header{"Content-Type": []string{"application/json"}},
	})

	response := rest.Get("https://api.example.com/users/1")

	user, err := rest.Deserialize[ExampleUser](response)
	if err != nil {
		// handle error
	}
	fmt.Println(user.Name)
}
Output:

Leanne Graham

func FlushMockups

func FlushMockups()

FlushMockups ...

func StartMockupServer

func StartMockupServer()

StartMockupServer sets the environment to send all client requests to the mockup server.

func StopMockupServer

func StopMockupServer()

StopMockupServer stop sending requests to the mockup server.

Types

type AsyncHTTPClient

type AsyncHTTPClient interface {
	// AsyncGet issues a GET HTTP verb to the specified URL asynchronously.
	AsyncGet(url string, headers ...http.Header) <-chan *Response
	// AsyncGetWithContext issues a GET HTTP verb with context to the specified URL asynchronously.
	AsyncGetWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response
	// AsyncPost issues a POST HTTP verb to the specified URL asynchronously.
	AsyncPost(url string, body any, headers ...http.Header) <-chan *Response
	// AsyncPostWithContext issues a POST HTTP verb with context to the specified URL asynchronously.
	AsyncPostWithContext(ctx context.Context, url string, body any, headers ...http.Header) <-chan *Response
	// AsyncPutWithContext issues a PUT HTTP verb with context to the specified URL asynchronously.
	AsyncPutWithContext(ctx context.Context, url string, body any, headers ...http.Header) <-chan *Response
	// AsyncPut issues a PUT HTTP verb to the specified URL asynchronously.
	AsyncPut(url string, body any, headers ...http.Header) <-chan *Response
	// AsyncPatch issues a PATCH HTTP verb to the specified URL asynchronously.
	AsyncPatch(url string, body any, headers ...http.Header) <-chan *Response
	// AsyncPatchWithContext issues a PATCH HTTP verb with context to the specified URL asynchronously.
	AsyncPatchWithContext(ctx context.Context, url string, body any, headers ...http.Header) <-chan *Response
	// AsyncDelete issues a DELETE HTTP verb to the specified URL asynchronously.
	AsyncDelete(url string, headers ...http.Header) <-chan *Response
	// AsyncDeleteWithContext issues a DELETE HTTP verb with context to the specified URL asynchronously.
	AsyncDeleteWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response
	// AsyncHead issues a HEAD HTTP verb to the specified URL asynchronously.
	AsyncHead(url string, headers ...http.Header) <-chan *Response
	// AsyncHeadWithContext issues a HEAD HTTP verb with context to the specified URL asynchronously.
	AsyncHeadWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response
	// AsyncOptions issues an OPTIONS HTTP verb to the specified URL asynchronously.
	AsyncOptions(url string, headers ...http.Header) <-chan *Response
	// AsyncOptionsWithContext issues an OPTIONS HTTP verb with context to the specified URL asynchronously.
	AsyncOptionsWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response
}

AsyncHTTPClient defines the interface for making asynchronous HTTP requests. It returns a channel that will eventually receive the *Response.

type AuthStyle

type AuthStyle int
const (
	// AuthStyleAutoDetect means to auto-detect which authentication
	// style the provider wants by trying both ways and caching
	// the successful way for the future.
	AuthStyleAutoDetect AuthStyle = iota

	// AuthStyleInParams sends the "client_id" and "client_secret"
	// in the POST body as application/x-www-form-urlencoded parameters.
	AuthStyleInParams

	// AuthStyleInHeader sends the client_id and client_password
	// using HTTP Basic Authorization. This is an optional style
	// described in the OAuth2 RFC 6749 section 2.3.1.
	AuthStyleInHeader
)

type BasicAuth

type BasicAuth struct {
	Username string
	Password string
}

BasicAuth gives the possibility to set Username and Password for a given RESTClient. Basic Auth is used by some APIs.

type ByteSize

type ByteSize int64

ByteSize is a helper type for configuring cache sizes in bytes. It provides constants for common size units (KB, MB, GB).

const (

	// KB represents a kilobyte (1024 bytes).
	KB ByteSize = 1 << (10 * iota)

	// MB represents a megabyte (1024 kilobytes).
	MB

	// GB represents a gigabyte (1024 megabytes).
	GB
)

type Cache

type Cache[K Key, V any] interface {
	// Get retrieves a value from the cache by its key.
	// Returns the value and a boolean indicating whether the key was found.
	Get(key K) (V, bool)

	// Set adds a value to the cache with the specified key and cost.
	// The cost can be the size of the value in bytes or any other metric.
	// Returns true if the value was added successfully.
	Set(key K, value V, cost int64) bool

	// SetWithTTL adds a value to the cache with the specified key, cost, and time-to-live.
	// Returns true if the value was added successfully.
	SetWithTTL(key K, value V, cost int64, ttl time.Duration) bool
}

Cache is an interface for cache implementations. It provides methods for getting, setting, and setting with TTL values.

type Client

type Client struct {
	// CustomPool defines a separate internal transport and connection pooling.
	// If nil, the default transport is used.
	CustomPool *CustomPool

	// BasicAuth sets the username and password for Basic Authentication.
	BasicAuth *BasicAuth

	// Client is the underlying http.Client. If not provided, one will be created.
	Client *http.Client

	// OAuth credentials for OAuth2 authentication.
	OAuth *OAuth

	// DefaultHeaders are headers included in every request.
	DefaultHeaders http.Header

	// BaseURL is the prefix for all request URLs. Final URL = BaseURL + path.
	BaseURL string

	// UserAgent is the User-Agent header value for all requests.
	UserAgent string

	// Name is a label for the client, used in metrics.
	Name string

	// Timeout is the maximum time for the entire request/response cycle.
	Timeout time.Duration

	// ConnectTimeout is the maximum time allowed to establish a connection.
	ConnectTimeout time.Duration

	// ContentType specifies the default media type (JSON, XML, Form).
	ContentType ContentType

	// EnableCache enables internal response caching.
	EnableCache bool

	// DisableTimeout disables any timeout for the requests.
	DisableTimeout bool

	// FollowRedirect enables following HTTP redirects (3xx).
	FollowRedirect bool

	// EnableGzip enables Gzip compression for requests and responses.
	EnableGzip bool

	// EnableTrace enables OpenTelemetry tracing.
	EnableTrace bool
	// contains filtered or unexported fields
}

Client is the main structure for making REST requests. It is thread-safe and should be reused. Use the package-level functions (Get, Post, etc.) for quick requests using a default client, or create a new Client instance for custom configuration.

Example
package main

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

	"github.com/arielsrv/go-restclient/rest"
)

func main() {
	// Start the mockup server for a reproducible example
	rest.StartMockupServer()
	defer rest.StopMockupServer()
	rest.FlushMockups()

	// Configure a mock for the specific URL
	_ = rest.AddMockups(&rest.Mock{
		URL:          "https://api.example.com/users/1",
		HTTPMethod:   "GET",
		RespHTTPCode: 200,
		RespBody:     `{"name": "Leanne Graham", "id": 1}`,
		RespHeaders:  http.Header{"Content-Type": []string{"application/json"}},
	})

	// Create a custom client
	client := &rest.Client{
		BaseURL: "https://api.example.com",
		Timeout: 5 * time.Second,
		Name:    "example-client",
	}

	// Make a request
	response := client.Get("/users/1")
	if response.IsOk() {
		fmt.Println("Success!")
	} else {
		fmt.Printf("Error: %v\n", response.Err)
		if response.Response != nil {
			fmt.Printf("Status: %d\n", response.StatusCode)
		}
	}
}
Output:

Success!

func (*Client) AsyncDelete

func (r *Client) AsyncDelete(url string, headers ...http.Header) <-chan *Response

AsyncDelete issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request).

func (*Client) AsyncDeleteWithContext

func (r *Client) AsyncDeleteWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response

AsyncDeleteWithContext issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request).

func (*Client) AsyncGet

func (r *Client) AsyncGet(url string, headers ...http.Header) <-chan *Response

AsyncGet issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncGetWithContext

func (r *Client) AsyncGetWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response

AsyncGetWithContext issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncHead

func (r *Client) AsyncHead(url string, headers ...http.Header) <-chan *Response

AsyncHead issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncHeadWithContext

func (r *Client) AsyncHeadWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response

AsyncHeadWithContext issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncOptions

func (r *Client) AsyncOptions(url string, headers ...http.Header) <-chan *Response

AsyncOptions issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncOptionsWithContext

func (r *Client) AsyncOptionsWithContext(ctx context.Context, url string, headers ...http.Header) <-chan *Response

AsyncOptionsWithContext issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) AsyncPatch

func (r *Client) AsyncPatch(url string, body any, headers ...http.Header) <-chan *Response

AsyncPatch issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) AsyncPatchWithContext

func (r *Client) AsyncPatchWithContext(
	ctx context.Context,
	url string,
	body any,
	headers ...http.Header,
) <-chan *Response

AsyncPatchWithContext issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) AsyncPost

func (r *Client) AsyncPost(url string, body any, headers ...http.Header) <-chan *Response

AsyncPost issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*Client) AsyncPostWithContext

func (r *Client) AsyncPostWithContext(
	ctx context.Context,
	url string,
	body any,
	headers ...http.Header,
) <-chan *Response

AsyncPostWithContext issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*Client) AsyncPut

func (r *Client) AsyncPut(url string, body any, headers ...http.Header) <-chan *Response

AsyncPut issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) AsyncPutWithContext

func (r *Client) AsyncPutWithContext(
	ctx context.Context,
	url string,
	body any,
	headers ...http.Header,
) <-chan *Response

AsyncPutWithContext issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) Delete

func (r *Client) Delete(url string, headers ...http.Header) *Response

Delete issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request).

func (*Client) DeleteWithContext

func (r *Client) DeleteWithContext(ctx context.Context, url string, headers ...http.Header) *Response

DeleteWithContext issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request).

func (*Client) Do

func (r *Client) Do(req *http.Request) (*http.Response, error)

Do execute a REST request.

func (*Client) Get

func (r *Client) Get(url string, headers ...http.Header) *Response

Get issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) GetWithContext

func (r *Client) GetWithContext(ctx context.Context, url string, headers ...http.Header) *Response

GetWithContext issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) Head

func (r *Client) Head(url string, headers ...http.Header) *Response

Head issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) HeadWithContext

func (r *Client) HeadWithContext(ctx context.Context, url string, headers ...http.Header) *Response

HeadWithContext issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) Options

func (r *Client) Options(url string, headers ...http.Header) *Response

Options issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) OptionsWithContext

func (r *Client) OptionsWithContext(ctx context.Context, url string, headers ...http.Header) *Response

OptionsWithContext issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Client) Patch

func (r *Client) Patch(url string, body any, headers ...http.Header) *Response

Patch issues a PATCH HTTP verb to the specified URL.

In Restful, PATCH is used for "partially updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) PatchWithContext

func (r *Client) PatchWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response

PatchWithContext issues a PATCH HTTP verb to the specified URL.

In Restful, PATCH is used for "partially updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) Post

func (r *Client) Post(url string, body any, headers ...http.Header) *Response

Post issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*Client) PostWithContext

func (r *Client) PostWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response

PostWithContext issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*Client) Put

func (r *Client) Put(url string, body any, headers ...http.Header) *Response

Put issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) PutWithContext

func (r *Client) PutWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response

PutWithContext issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Client) RawClient

func (r *Client) RawClient(ctx context.Context) *http.Client

RawClient returns the underlying http.Client used by the RESTClient.

type ContentType

type ContentType int

ContentType represents the content type for the body of HTTP verbs like POST, PUT, and PATCH. It's used to determine how to marshal and unmarshal request and response bodies.

const (
	// JSON represents a JSON content type.
	JSON ContentType = iota

	// XML represents an XML content type.
	XML

	// FORM represents a form-urlencoded content type.
	FORM
)

ContentType constants for supported content types.

type CustomPool

type CustomPool struct {
	// Public for custom fine-tuning
	Transport http.RoundTripper
	Proxy     string

	MaxIdleConnsPerHost int
}

CustomPool defines a separate internal *dfltTransport* and connection pooling.

type FormMedia

type FormMedia struct {
	// ContentType is the MIME type for this media, typically "application/x-www-form-urlencoded".
	ContentType string
}

FormMedia implements the Media and MediaMarshaler interfaces for form-urlencoded content type.

func (FormMedia) DefaultHeaders

func (r FormMedia) DefaultHeaders() http.Header

DefaultHeaders returns the default HTTP headers for form-urlencoded content type. It sets the Content-Type header to the configured ContentType and the Accept header to accept JSON, XML, and plain text responses.

func (FormMedia) Marshal

func (r FormMedia) Marshal(body any) (io.Reader, error)

Marshal converts the given body into form-urlencoded format and returns an io.Reader containing the marshaled data. The body must be of type url.Values.

type HTTPClient

type HTTPClient interface {
	// Get issues a GET HTTP verb to the specified URL.
	Get(url string, headers ...http.Header) *Response
	// GetWithContext issues a GET HTTP verb with context to the specified URL.
	GetWithContext(ctx context.Context, url string, headers ...http.Header) *Response
	// Post issues a POST HTTP verb to the specified URL.
	Post(url string, body any, headers ...http.Header) *Response
	// PostWithContext issues a POST HTTP verb with context to the specified URL.
	PostWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response
	// PutWithContext issues a PUT HTTP verb with context to the specified URL.
	PutWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response
	// Put issues a PUT HTTP verb to the specified URL.
	Put(url string, body any, headers ...http.Header) *Response
	// Patch issues a PATCH HTTP verb to the specified URL.
	Patch(url string, body any, headers ...http.Header) *Response
	// PatchWithContext issues a PATCH HTTP verb with context to the specified URL.
	PatchWithContext(ctx context.Context, url string, body any, headers ...http.Header) *Response
	// Delete issues a DELETE HTTP verb to the specified URL.
	Delete(url string, headers ...http.Header) *Response
	// DeleteWithContext issues a DELETE HTTP verb with context to the specified URL.
	DeleteWithContext(ctx context.Context, url string, headers ...http.Header) *Response
	// Head issues a HEAD HTTP verb to the specified URL.
	Head(url string, headers ...http.Header) *Response
	// HeadWithContext issues a HEAD HTTP verb with context to the specified URL.
	HeadWithContext(ctx context.Context, url string, headers ...http.Header) *Response
	// Options issues an OPTIONS HTTP verb to the specified URL.
	Options(url string, headers ...http.Header) *Response
	// OptionsWithContext issues an OPTIONS HTTP verb with context to the specified URL.
	OptionsWithContext(ctx context.Context, url string, headers ...http.Header) *Response
}

HTTPClient defines the interface for making synchronous HTTP requests.

type HTTPExporter

type HTTPExporter interface {
	// RawClient returns the underlying http.Client.
	RawClient(ctx context.Context) *http.Client
	// Do executes a standard http.Request.
	Do(*http.Request) (*http.Response, error)
}

HTTPExporter provides access to the underlying http.Client and the Do method.

type JSONMedia

type JSONMedia struct {
	// ContentType is the MIME type for this media, typically "application/json".
	ContentType string
}

JSONMedia implements the Media, MediaMarshaler, and MediaUnmarshaler interfaces for JSON content type.

func (JSONMedia) DefaultHeaders

func (r JSONMedia) DefaultHeaders() http.Header

DefaultHeaders returns the default HTTP headers for JSON content type. It sets the Content-Type header to the configured ContentType and the Accept header to accept JSON and JSON problem responses.

func (JSONMedia) Marshal

func (r JSONMedia) Marshal(body any) (io.Reader, error)

Marshal converts the given body into JSON format and returns an io.Reader containing the marshaled data. It supports strings, byte slices, structs, and maps.

func (JSONMedia) Unmarshal

func (r JSONMedia) Unmarshal(data []byte, v any) error

Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.

type Key

type Key interface {
	uint64 | string | []byte | byte | int | int32 | uint32 | int64
}

Key is an interface for types that can be used as cache keys. It supports various primitive types that can be used as keys.

type Media

type Media interface {
	// DefaultHeaders returns the default HTTP headers for this media type.
	DefaultHeaders() http.Header
}

Media is an interface for types that can provide default HTTP headers for content negotiation.

type MediaMarshaler

type MediaMarshaler interface {
	Media
	// Marshal converts the given body into the appropriate format and returns
	// an io.Reader containing the marshaled data.
	Marshal(body any) (io.Reader, error)
}

MediaMarshaler is an interface for types that can marshal data into a specific content type format.

type MediaUnmarshaler

type MediaUnmarshaler interface {
	Media
	// Unmarshal parses the data and stores the result in the value pointed to by v.
	Unmarshal(data []byte, v any) error
}

MediaUnmarshaler is an interface for types that can unmarshal data from a specific content type format.

type Mock

type Mock struct {
	// Request array Headers
	ReqHeaders http.Header

	// Response Array Headers
	RespHeaders http.Header

	// Request URL
	URL string

	// Request HTTP Method (GET, POST, PUT, PATCH, HEAD, DELETE, OPTIONS)
	// As a good practice use the constants in http package (http.MethodGet, etc.)
	HTTPMethod string

	// Request Body, used with POST, PUT & PATCH
	ReqBody string

	// Response Body
	RespBody string

	// Response HTTP Code
	RespHTTPCode int

	// Transport error
	Timeout time.Duration
}

Mock serves the purpose of creating Mockups. All requests will be sent to the mockup server if mockup is activated. To activate the mockup *environment* you have two ways: using the flag -mock

go test -mock

Or by programmatically starting the mockup server

StartMockupServer()

type OAuth

type OAuth struct {
	EndpointParams url.Values
	ClientID       string
	ClientSecret   string
	TokenURL       string
	Scopes         []string
	AuthStyle      AuthStyle
}

type Problem

type Problem struct {
	XMLName xml.Name `json:"-" xml:"problem,omitempty"`
	XMLNS   xml.Name `json:"-" xml:"xmlns,attr,omitempty"`

	// Type is a URI reference that identifies the problem type.
	Type string `json:"type,omitempty" xml:"type,omitempty"`

	// Title is a short, human-readable summary of the problem type.
	Title string `json:"title,omitempty" xml:"title,omitempty"`

	// Detail is a human-readable explanation specific to this occurrence of the problem.
	Detail string `json:"detail,omitempty" xml:"detail,omitempty"`

	// Instance is a URI reference that identifies the specific occurrence of the problem.
	Instance string `json:"instance,omitempty" xml:"instance,omitempty"`

	// Status is the HTTP status code generated by the origin server.
	Status int `json:"status,omitempty" xml:"status,omitempty"`
}

Problem represents an RFC7807 API problem response. It follows the standard defined in https://datatracker.ietf.org/doc/html/rfc7807 and can be serialized to/from both JSON and XML formats.

type Response

type Response struct {
	// Response is the underlying HTTP response.
	*http.Response

	// Err contains any error that occurred during the request.
	Err error

	// Problem contains RFC7807 problem details if the response is an error.
	Problem *Problem
	// contains filtered or unexported fields
}

Response represents an HTTP response from a REST API call. It wraps the standard http.Response and provides additional functionality for handling REST API responses, including caching, error handling, and content deserialization.

func Delete

func Delete(url string) *Response

Delete issues a DELETE HTTP verb to the specified URL using the default client.

In RESTful design, DELETE is used to "delete" a resource. Client should expect a response status code of 200 (OK), 404 (Not Found), or 400 (Bad Request).

func Get

func Get(url string) *Response

Get issues a GET HTTP verb to the specified URL using the default client.

In RESTful design, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200 (OK) if the resource exists, 404 (Not Found) if it doesn't, or 400 (Bad Request).

Example
package main

import (
	"fmt"
	"net/http"

	"github.com/arielsrv/go-restclient/rest"
)

type ExampleUser struct {
	Name string `json:"name"`
	ID   int    `json:"id"`
}

func main() {
	// Start the mockup server for a reproducible example
	rest.StartMockupServer()
	defer rest.StopMockupServer()
	rest.FlushMockups()

	// Configure a mock for the specific URL
	_ = rest.AddMockups(&rest.Mock{
		URL:          "https://api.example.com/users/1",
		HTTPMethod:   "GET",
		RespHTTPCode: 200,
		RespBody:     `{"name": "Leanne Graham", "id": 1}`,
		RespHeaders:  http.Header{"Content-Type": []string{"application/json"}},
	})

	// Simple GET request using the default client
	response := rest.Get("https://api.example.com/users/1")
	if !response.IsOk() {
		fmt.Printf("Error: %v\n", response.Err)
		return
	}

	var user ExampleUser
	if err := response.FillUp(&user); err != nil {
		fmt.Printf("Error deserializing: %v\n", err)
		return
	}

	fmt.Printf("User: %s\n", user.Name)
}
Output:

User: Leanne Graham
func Head(url string) *Response

Head issues a HEAD HTTP verb to the specified URL using the default client.

In RESTful design, HEAD is used to "read" resource headers only. Client should expect a response status code of 200 (OK) if the resource exists, 404 (Not Found) if it doesn't, or 400 (Bad Request).

func Options

func Options(url string) *Response

Options issues an OPTIONS HTTP verb to the specified URL using the default client.

In RESTful design, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200 (OK) if the resource exists, 404 (Not Found) if it doesn't, or 400 (Bad Request).

func Patch

func Patch(url string, body any) *Response

Patch issues a PATCH HTTP verb to the specified URL using the default client.

In RESTful design, PATCH is used for "partially updating" a resource. Client should expect a response status code of 200 (OK), 404 (Not Found), or 400 (Bad Request). 200 (OK) could also be 204 (No Content).

Body could be any of the following: string, []byte, struct or map.

func Post

func Post(url string, body any) *Response

Post issues a POST HTTP verb to the specified URL using the default client.

In RESTful design, POST is used for "creating" a resource. Client should expect a response status code of 201 (Created), 400 (Bad Request), 404 (Not Found), or 409 (Conflict) if the resource already exists.

Body could be any of the following: string, []byte, struct or map.

func Put

func Put(url string, body any) *Response

Put issues a PUT HTTP verb to the specified URL using the default client.

In RESTful design, PUT is used for "updating" a resource. Client should expect a response status code of 200 (OK), 404 (Not Found), or 400 (Bad Request). 200 (OK) could also be 204 (No Content).

Body could be any of the following: string, []byte, struct or map.

func (*Response) Cached

func (r *Response) Cached() bool

Cached returns true if the response was served from the local cache.

func (*Response) Debug

func (r *Response) Debug() string

Debug returns a string representation of both the HTTP request and response. This is useful for logging and debugging purposes.

func (*Response) FillUp

func (r *Response) FillUp(fill any) error

FillUp deserializes the response body into the provided value 'fill'. 'fill' must be a pointer to the type where you want to store the data. It automatically detects the content type (JSON, XML) from the response headers.

Example
package main

import (
	"fmt"
	"net/http"

	"github.com/arielsrv/go-restclient/rest"
)

type ExampleUser struct {
	Name string `json:"name"`
	ID   int    `json:"id"`
}

func main() {
	// Start the mockup server for a reproducible example
	rest.StartMockupServer()
	defer rest.StopMockupServer()
	rest.FlushMockups()

	// Configure a mock
	_ = rest.AddMockups(&rest.Mock{
		URL:          "https://api.example.com/users/1",
		HTTPMethod:   "GET",
		RespHTTPCode: 200,
		RespBody:     `{"name": "Leanne Graham", "id": 1}`,
		RespHeaders:  http.Header{"Content-Type": []string{"application/json"}},
	})

	response := rest.Get("https://api.example.com/users/1")

	var user ExampleUser
	err := response.FillUp(&user)
	if err != nil {
		// handle error
	}
	fmt.Println(user.Name)
}
Output:

Leanne Graham

func (*Response) Hit

func (r *Response) Hit()

Hit marks the response as a hit in the cache. This is used internally by the caching system.

func (*Response) IsOk

func (r *Response) IsOk() bool

IsOk checks if the response status code is within the 200-399 range. Returns true if the status code indicates success, false otherwise.

func (*Response) Raw

func (r *Response) Raw() string

Raw returns the Response Body as a string. This is an alias for String() for backward compatibility.

func (*Response) String

func (r *Response) String() string

String returns the Response Body as a string. This is useful for accessing the raw response content.

func (*Response) VerifyIsOkOrError

func (r *Response) VerifyIsOkOrError() error

VerifyIsOkOrError checks if the response is OK or if an error occurred. Returns nil if the response is OK, otherwise returns an error with details. If r.Err is not nil, it returns that error. If the status code is not in the success range, it returns an error with the status code and response body.

type XMLMedia

type XMLMedia struct {
	// ContentType is the MIME type for this media, typically "application/xml".
	ContentType string
}

XMLMedia implements the Media, MediaMarshaler, and MediaUnmarshaler interfaces for XML content type.

func (XMLMedia) DefaultHeaders

func (r XMLMedia) DefaultHeaders() http.Header

DefaultHeaders returns the default HTTP headers for XML content type. It sets the Content-Type header to the configured ContentType and the Accept header to accept various XML formats.

func (XMLMedia) Marshal

func (r XMLMedia) Marshal(body any) (io.Reader, error)

Marshal converts the given body into XML format and returns an io.Reader containing the marshaled data.

func (XMLMedia) Unmarshal

func (r XMLMedia) Unmarshal(data []byte, v any) error

Unmarshal parses the XML-encoded data and stores the result in the value pointed to by v.

Jump to

Keyboard shortcuts

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