gotcha

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2022 License: MIT Imports: 14 Imported by: 8

README

gotcha

Go Reference

Gotcha is an alternative to Go's http client, with an API inspired by got. It can interface with other HTTP packages through an adapter.

Aadapter implementations for fhttp, cclient & fasthttp can be found in the adapters directory.

Usage

Top-Level API

Gotcha exposes a top-level API to make quick and simple requests:

package main

import (
	"fmt"
	"github.com/sleeyax/gotcha"
	"log"
)

func main() {
	res, err := gotcha.Get("https://sleeyax.dev")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(res.Text())
	// Output: <!DOCTYPE html>...
}

Configuration options

When you require further customization of the request, you can do so by specifying configuration Options:

package main

import (
	"fmt"
	"github.com/sleeyax/gotcha"
	"log"
)

func main() {
	res, _ := gotcha.Post("https://httpbin.org/anything", &gotcha.Options{
		Json: gotcha.JSON{
			"hello": "world",
		},
		FollowRedirect: false,
	})
	body, _ := res.Json()
	defer res.Close()
    fmt.Println(body["data"])
	// Output: {"hello": "world"}
}

Client

For advanced requests, create a client instance. Clients are configurable, extendable & reusable. This gives you fine-grained control over the request:

package main

import (
	"fmt"
	"github.com/sleeyax/gotcha"
	"io"
	"log"
	"net/http"
	"strings"
)

func main() {
	client, _ := gotcha.NewClient(&gotcha.Options{
		PrefixURL: "https://httpbin.org/",
		Headers: http.Header{
			"user-agent": {"gotcha by Sleeyax (https://github.com/sleeyax/gotcha)"},
		},
	})

	logClient, _ := client.Extend(&gotcha.Options{
		Hooks: gotcha.Hooks{
			Init: []gotcha.InitHook{
				func(o *gotcha.Options) {
					fmt.Println(fmt.Sprintf("about to send a request to %s with method %s", o.FullUrl.String(), o.Method))
				},
			},
		},
	})

	res, _ := logClient.DoRequest("PUT", "anything", &gotcha.Options{
		Body: io.NopCloser(strings.NewReader("hello world!")),
	})
	defer res.Close()
	// Output: "about to send a request to https://httpbin.org/anything with method PUT"
}

See examples for more adapter-specific examples.

Documentation

Overview

Package gotcha is an advanced HTTP client with a got-like API. It can interface with other HTTP packages through an adapter.

Index

Examples

Constants

This section is empty.

Variables

View Source
var MaxRetriesExceededError = errors.New("Maximum amount of retries exceeded.")
View Source
var RedirectStatusCodes = []int{300, 301, 302, 303, 304, 307, 308}

Functions

This section is empty.

Types

type Adapter

type Adapter interface {
	// DoRequest is a custom function that will be used by gotcha to make the actual request.
	DoRequest(options *Options) (*Response, error)
}

type AfterResponseHook

type AfterResponseHook func(response *Response, retry RetryFunc) (*Response, error)

type BeforeRedirectHook

type BeforeRedirectHook func(*Options, *Response)

type BeforeRequestHook

type BeforeRequestHook func(*Options)

type BeforeRetryHook

type BeforeRetryHook func(options *Options, error error, retryCount int)

type Client

type Client struct {
	// Instance-specific configuration options.
	Options *Options
}

func NewClient

func NewClient(options *Options) (*Client, error)

NewClient creates a new HTTP client based on default Options which can be extended.

Example
client, err := NewClient(&Options{
	PrefixURL: "https://httpbin.org/",
	Headers: http.Header{
		"user-agent": {"gotcha"},
	},
})
if err != nil {
	fmt.Sprintln("error:", err)
}

res, err := client.Do(http.MethodGet, "https://httpbin.org/get")
if err != nil {
	fmt.Sprintln("error:", err)
}

j, _ := res.Json()
headers := j["headers"].(map[string]interface{})

fmt.Println(res.StatusCode)
fmt.Println(headers["User-Agent"])
Output:

func (*Client) CloseBody

func (c *Client) CloseBody(o *Options)

CloseBody clears the Body, Form and Json fields.

func (*Client) Delete

func (c *Client) Delete(url string, options ...*Options) (*Response, error)

func (*Client) Do

func (c *Client) Do(method string, url string, options ...*Options) (*Response, error)

Do is an alias of DoRequest.

func (*Client) DoRequest

func (c *Client) DoRequest(method string, url string, options ...*Options) (*Response, error)

func (*Client) Extend

func (c *Client) Extend(options *Options) (*Client, error)

Extend returns a new Client with merged Options.

func (*Client) Get

func (c *Client) Get(url string, options ...*Options) (*Response, error)

func (*Client) Head

func (c *Client) Head(url string, options ...*Options) (*Response, error)

func (*Client) ParseBody

func (c *Client) ParseBody(o *Options) error

ParseBody parses Form or Json (in that order) into Body.

func (*Client) Patch

func (c *Client) Patch(url string, options ...*Options) (*Response, error)

func (*Client) Post

func (c *Client) Post(url string, options ...*Options) (*Response, error)

func (*Client) Put added in v0.1.5

func (c *Client) Put(url string, options ...*Options) (*Response, error)

type Hooks

type Hooks struct {
	// Called with plain Options, right before their normalization.
	Init []InitHook

	// Called with normalized Options.
	// Gotcha will make no further changes to the Options before it is sent to the Adapter.
	//
	// Note that changing Options.Json or Options.Form has no effect on the request,
	// you should change Options.Body instead and (if needed) update the Options.headers accordingly.
	BeforeRequest []BeforeRequestHook

	// Called with normalized request Options and the redirect response.
	// Gotcha will make no further changes to the request.
	BeforeRedirect []BeforeRedirectHook

	// Called with normalized request Options, the error and the retry count.
	// Gotcha will make no further changes to the request.
	BeforeRetry []BeforeRetryHook

	// Called with response and a retry function.
	// Calling the retry function will trigger BeforeRetry hooks.
	//
	// Each function should return the (modified) response.
	AfterResponse []AfterResponseHook
}

type InitHook

type InitHook func(*Options)

type JSON

type JSON map[string]interface{}

type MarshalJsonFunc

type MarshalJsonFunc = func(json JSON) ([]byte, error)

type Options

type Options struct {
	// Adapter is an adapter that will be used by gotcha to make the actual request.
	// Implement your own Adapter or use the RequestAdapter to get started.
	Adapter Adapter

	// Request URI.
	// Can be relative or absolute.
	URI string

	// FullUrl is the URI that was computed form PrefixURL and URI.
	// You shouldn't need to modify this in most cases.
	FullUrl *url.URL

	// Proxy URL.
	// If this is an authenticated Proxy, make sure Username and Password are set.
	Proxy *url.URL

	// Retry on failure.
	Retry bool

	// Additional configuration Options for Retry.
	RetryOptions *RetryOptions

	// The HTTP method used to make the request.
	Method string

	// When specified, prefixUrl will be prepended to the url.
	// The prefix can be any valid URI, either relative or absolute.
	// A trailing slash / is optional - one will be added automatically.
	PrefixURL string

	// Request headers.
	Headers http.Header

	// Request Body.
	//
	// Body will be set in the following order,
	// whichever value is found to be of non-zero value first: Form -> Json -> Body.
	// Raw body content.
	Body io.ReadCloser

	// JSON data.
	Json JSON

	// Form data that will be converted to a query string.
	Form urlValues.Values

	// A function used to parse JSON responses.
	UnmarshalJson UnmarshalJsonFunc

	// A function used to stringify the body of JSON requests.
	MarshalJson MarshalJsonFunc

	// Can contain custom user data.
	// This can be  useful for storing authentication tokens for example.
	Context interface{}

	// CokieJar automatically stores & parses cookies.
	//
	// The CookieJar is used to insert relevant cookies into every
	// outbound Request and is updated with the cookie values
	// of every inbound Response. The CookieJar is also consulted for every
	// redirect that the Client follows.
	//
	// If CookieJar is nil, cookies are only sent if they are explicitly set on the Request.
	CookieJar http.CookieJar

	// Query string that will be added to the request URI.
	// This will override the query string in URI.
	SearchParams urlValues.Values

	// Duration to wait for the server to end the response before aborting the request.
	Timeout time.Duration

	// Defines if redirect responses should be followed automatically.
	FollowRedirect bool

	// Additional configuration Options for FollowRedirect.
	RedirectOptions RedirectOptions

	// Hooks allow modifications during the request lifecycle.
	Hooks Hooks
	// contains filtered or unexported fields
}

func NewDefaultOptions

func NewDefaultOptions() *Options

func (*Options) Extend

func (o *Options) Extend(options *Options) (*Options, error)

Extend extends the current Options by the provided Options. The value returned is a pointer to a newly allocated Options value.

type RedirectOptions

type RedirectOptions struct {
	// Specifies if redirects should be rewritten as GET.
	//
	// If false, when sending a POST request and receiving a 302,
	// it will resend the body to the new location using the same HTTP method (POST in this case).
	//
	// Note that if a 303 is sent by the server in response to any request type (POST, DELETE, etc.),
	// gotcha will automatically request the resource pointed to in the location header via GET.
	// This is in accordance with the spec https://tools.ietf.org/html/rfc7231#section-6.4.4.
	RewriteMethods bool

	// Maximum amount of redirects to follow.
	// Follows an unlimited amount of redirects when set to 0.
	Limit int
}

type RequestAdapter

type RequestAdapter struct {
	// RoundTripper is a http.RoundTripper that will be used to do the request.
	//
	// Defaults to http.DefaultTransport.
	RoundTripper http.RoundTripper

	// Request is a function that builds the http.Request to send.
	//
	// Defaults to a function that derives the Request from the specified Options.
	Request func(*Options) *http.Request
	// contains filtered or unexported fields
}

RequestAdapter is a default implementation of Adapter. Gotcha will use this adapter when no other is specified.

func (*RequestAdapter) DoRequest

func (ra *RequestAdapter) DoRequest(options *Options) (*Response, error)

type Response

type Response struct {
	*http.Response
	UnmarshalJsonFunc
}

func Delete

func Delete(url string, options ...*Options) (*Response, error)

func DoRequest

func DoRequest(url string, method string, options ...*Options) (*Response, error)

func Get

func Get(url string, options ...*Options) (*Response, error)

func NewResponse

func NewResponse(response *http.Response) *Response

func Patch

func Patch(url string, options ...*Options) (*Response, error)

func Post

func Post(url string, options ...*Options) (*Response, error)

func Put

func Put(url string, options ...*Options) (*Response, error)

func (*Response) Close

func (r *Response) Close() error

Close closes the response body.

func (*Response) Json

func (r *Response) Json() (JSON, error)

Json parses the Response Body as JSON.

func (*Response) Raw

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

Raw reads the Response Body as a byte array.

func (*Response) Text

func (r *Response) Text() (string, error)

Text reads the Response Body as a string.

type RetryFunc

type RetryFunc func(updatedOptions *Options) (*Response, error)

type RetryOptions

type RetryOptions struct {
	// Max number of times to retry.
	Limit int

	// Only retry when the request HTTP method equals one of these Methods.
	Methods []string

	// Only retry when the response HTTP status code equals one of these StatusCodes.
	StatusCodes []int

	// Only retry on error when the error message contains one of these ErrorCodes.
	ErrorCodes []string

	// Respect the response 'Retry-After' header, if set.
	//
	// If RetryAfter is false or the response headers don't contain this header,
	// it will default to 0. You can specify a custom timeout with CalculateTimeout.
	//
	// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
	RetryAfter bool

	// CalculateTimeout is a function that computes the timeout to use between retries.
	// By default, `computedTimeout` will be used as timeout value.
	CalculateTimeout func(retries int, retryOptions *RetryOptions, computedTimeout time.Duration, error error) time.Duration
}

func NewDefaultRetryOptions

func NewDefaultRetryOptions() *RetryOptions

type UnmarshalJsonFunc

type UnmarshalJsonFunc = func(data []byte) (JSON, error)

Directories

Path Synopsis
adapters
cclient Module
fasthttp Module
fhttp Module
examples
cclient Module
default-http Module
fhttp Module
internal

Jump to

Keyboard shortcuts

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