ghttp

package module
v0.0.0-...-50e3427 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2021 License: MIT Imports: 34 Imported by: 19

README

ghttp

ghttp is a simple, user-friendly and concurrent safe HTTP request library for Go.

Build codecov Go Report Card GoDoc License

Features

ghttp wraps net/http and provides convenient APIs and advanced features to simplify your jobs.

  • Requests-style APIs.
  • GET, POST, PUT, PATCH, DELETE, etc.
  • Easy set query params, headers and cookies.
  • Easy send form, JSON or multipart payload.
  • Automatic cookies management.
  • Backoff retry mechanism.
  • Before request and after response callbacks.
  • Rate limiting for outbound requests.
  • Easy decode the response body to bytes, string or unmarshal the JSON-encoded data.
  • Friendly debugging.
  • Concurrent safe.

Install

go get -u github.com/winterssy/ghttp

Usage

import "github.com/winterssy/ghttp"

Quick Start

The usages of ghttp are very similar to net/http .

  • ghttp.Client
client := ghttp.New()
// Now you can manipulate client like net/http
client.CheckRedirect = ghttp.NoRedirect
client.Timeout = 300 * time.Second
  • ghttp.Request
req, err := ghttp.NewRequest("GET", "https://httpbin.org/get")
if err != nil {
    log.Fatal(err)
}
// Now you can manipulate req like net/http
req.Close = true
  • ghttp.Response
resp, err := ghttp.Get("https://www.google.com")
if err != nil {
    log.Fatal(err)
}
// Now you can access resp like net/http
fmt.Println(resp.StatusCode)

Documentation is available at go.dev .

License

MIT

Documentation

Overview

Example (GoStyleAPI)
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	req, err := ghttp.NewRequest(ghttp.MethodPost, "https://httpbin.org/post")
	if err != nil {
		log.Fatal(err)
	}

	req.SetQuery(ghttp.Params{
		"k1": "v1",
		"k2": "v2",
	})
	req.SetHeaders(ghttp.Headers{
		"k3": "v3",
		"k4": "v4",
	})
	req.SetForm(ghttp.Form{
		"k5": "v5",
		"k6": "v6",
	})

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

Example (RequestsStyleAPI)
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.Post("https://httpbin.org/post",
		ghttp.WithQuery(ghttp.Params{
			"k1": "v1",
			"k2": "v2",
		}),
		ghttp.WithHeaders(ghttp.Headers{
			"k3": "v3",
			"k4": "v4",
		}),
		ghttp.WithForm(ghttp.Form{
			"k5": "v5",
			"k6": "v6",
		}),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

Index

Examples

Constants

View Source
const (
	MethodGet     = "GET"
	MethodHead    = "HEAD"
	MethodPost    = "POST"
	MethodPut     = "PUT"
	MethodPatch   = "PATCH"
	MethodDelete  = "DELETE"
	MethodOptions = "OPTIONS"
	MethodConnect = "CONNECT"
	MethodTrace   = "TRACE"
)

Common HTTP methods.

Variables

View Source
var (
	// DefaultClient is a global Client used by the global methods such as Get, Post, etc.
	DefaultClient = New()

	// ProxyFromEnvironment is an alias of http.ProxyFromEnvironment.
	ProxyFromEnvironment = http.ProxyFromEnvironment
)
View Source
var (
	Get     = DefaultClient.Get
	Head    = DefaultClient.Head
	Post    = DefaultClient.Post
	Put     = DefaultClient.Put
	Patch   = DefaultClient.Patch
	Delete  = DefaultClient.Delete
	Options = DefaultClient.Options
	Send    = DefaultClient.Send
)

HTTP verbs via the global Client.

Functions

func DefaultTransport

func DefaultTransport() *http.Transport

DefaultTransport returns a preset HTTP transport. It's a clone of http.DefaultTransport indeed.

func MaxRedirects

func MaxRedirects(n int) func(req *http.Request, via []*http.Request) error

MaxRedirects returns a redirect policy for limiting maximum redirects followed up by n.

Example
package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/winterssy/ghttp"
)

func main() {
	var counter int
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.URL.String(), http.StatusFound)
		counter++
	}))
	defer ts.Close()

	client := ghttp.New()
	client.CheckRedirect = ghttp.MaxRedirects(3)

	resp, err := client.Get(ts.URL)
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(counter)
	fmt.Println(resp.StatusCode)
}
Output:

3
302

func NoRedirect

func NoRedirect(*http.Request, []*http.Request) error

NoRedirect is a redirect policy that makes the Client not follow redirects.

Example
package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/winterssy/ghttp"
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "https://www.google.com", http.StatusFound)
	}))
	defer ts.Close()

	client := ghttp.New()
	client.CheckRedirect = ghttp.NoRedirect

	resp, err := client.
		Get(ts.URL)
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(resp.StatusCode)
}
Output:

302

func ProxyURL

func ProxyURL(url string) func(*http.Request) (*neturl.URL, error)

ProxyURL returns a proxy function (for use in an http.Transport) given a URL.

Types

type AfterResponseCallback

type AfterResponseCallback interface {
	// Exit is called when a request ends.
	Exit(resp *Response, err error)
}

AfterResponseCallback is the interface that defines the manipulations after receiving a response.

type Backoff

type Backoff interface {
	// Wait returns the duration to wait before retrying a request.
	Wait(attemptNum int, resp *Response, err error) time.Duration
}

Backoff is the interface defines a backoff for a retrier. It is called after a failing request to determine the amount of time that should pass before trying again.

func NewConstantBackoff

func NewConstantBackoff(interval time.Duration, jitter bool) Backoff

NewConstantBackoff provides a callback for the retry policy which will perform constant backoff with jitter based on interval.

func NewExponentialBackoff

func NewExponentialBackoff(baseInterval, maxInterval time.Duration, jitter bool) Backoff

NewExponentialBackoff provides a callback for the retry policy which will perform exponential backoff with jitter based on the attempt number and limited by baseInterval and maxInterval. See: https://aws.amazon.com/cn/blogs/architecture/exponential-backoff-and-jitter/

func NewFibonacciBackoff

func NewFibonacciBackoff(maxValue int, interval time.Duration) Backoff

NewFibonacciBackoff provides a callback for the retry policy which will perform fibonacci backoff based on the attempt number and limited by maxValue. If maxValue less than or equal to zero, it means no limit.

type BeforeRequestCallback

type BeforeRequestCallback interface {
	// Enter is called when a request is about to begin.
	// If a non-nil error is returned, ghttp will cancel the request.
	Enter(req *Request) error
}

BeforeRequestCallback is the interface that defines the manipulations before sending a request.

type Client

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

Client is a wrapper around an http.Client.

func New

func New() *Client

New returns a new Client.

func (*Client) AddClientCerts

func (c *Client) AddClientCerts(certs ...tls.Certificate)

AddClientCerts adds client certificates to c.

Example
package main

import (
	"crypto/tls"
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	cert, err := tls.LoadX509KeyPair("/path/client.cert", "/path/client.key")
	if err != nil {
		log.Fatal(err)
	}

	client.AddClientCerts(cert)
	resp, err := client.Get("https://self-signed.badssl.com")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

func (*Client) AddCookies

func (c *Client) AddCookies(url string, cookies ...*http.Cookie)

AddCookies adds cookies to send in a request for the given URL to cookie jar.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	cookies := ghttp.Cookies{
		"n1": "v1",
		"n2": "v2",
	}
	client.AddCookies("https://httpbin.org", cookies.Decode()...)

	resp, err := client.Get("https://httpbin.org/cookies")
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("cookies", "n1"))
	fmt.Println(result.GetString("cookies", "n2"))
}
Output:

v1
v2

func (*Client) AddRootCerts

func (c *Client) AddRootCerts(pemCerts []byte) bool

AddRootCerts attempts to add root certificates to c from a series of PEM encoded certificates and reports whether any certificates were successfully added.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	pemCerts, err := ioutil.ReadFile("/path/root-ca.pem")
	if err != nil {
		log.Fatal(err)
	}

	client := ghttp.New()
	client.AddRootCerts(pemCerts)

	resp, err := client.Get("https://self-signed.badssl.com")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

func (*Client) Cookie

func (c *Client) Cookie(url string, name string) (*http.Cookie, error)

Cookie returns the named cookie to send in a request for the given URL from cookie jar. If multiple cookies match the given name, only one cookie will be returned.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	_, err := client.Get("https://httpbin.org/cookies/set/uid/10086")
	if err != nil {
		log.Print(err)
		return
	}

	c, err := client.Cookie("https://httpbin.org", "uid")
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(c.Name)
	fmt.Println(c.Value)
}
Output:

uid
10086

func (*Client) Cookies

func (c *Client) Cookies(url string) (cookies []*http.Cookie)

Cookies returns the cookies to send in a request for the given URL from cookie jar.

func (*Client) Delete

func (c *Client) Delete(url string, hooks ...RequestHook) (*Response, error)

Delete makes a DELETE HTTP request.

func (*Client) DisableTLSVerify

func (c *Client) DisableTLSVerify()

DisableTLSVerify makes c not verify the server's TLS certificate.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()
	client.DisableTLSVerify()

	resp, err := client.Get("https://self-signed.badssl.com")
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(resp.StatusCode)
}
Output:

200

func (*Client) Do

func (c *Client) Do(req *Request) (resp *Response, err error)

Do sends a request and returns its response.

func (*Client) EnableDebugging

func (c *Client) EnableDebugging(w io.Writer, body bool)

EnableDebugging adds a callback to c for debugging. ghttp will dump the request and response details to w, like "curl -v".

Example
package main

import (
	"os"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()
	client.EnableDebugging(os.Stdout, true)

	_, _ = client.Post("https://httpbin.org/post",
		ghttp.WithForm(ghttp.Form{
			"k1": "v1",
			"k2": "v2",
		}),
	)
}
Output:

func (*Client) EnableRateLimiting

func (c *Client) EnableRateLimiting(limiter *rate.Limiter)

EnableRateLimiting adds a callback to c for limiting outbound requests given a rate.Limiter (provided by golang.org/x/time/rate package).

Example
package main

import (
	"sync"

	"github.com/winterssy/ghttp"
	"golang.org/x/time/rate"
)

func main() {
	client := ghttp.New()
	client.EnableRateLimiting(rate.NewLimiter(1, 10))

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, _ = client.Get("https://www.example.com")
		}()
	}
	wg.Wait()
}
Output:

func (*Client) Get

func (c *Client) Get(url string, hooks ...RequestHook) (*Response, error)

Get makes a GET HTTP request.

func (*Client) Head

func (c *Client) Head(url string, hooks ...RequestHook) (*Response, error)

Head makes a HEAD HTTP request.

func (*Client) Options

func (c *Client) Options(url string, hooks ...RequestHook) (*Response, error)

Options makes a OPTIONS HTTP request.

func (*Client) Patch

func (c *Client) Patch(url string, hooks ...RequestHook) (*Response, error)

Patch makes a PATCH HTTP request.

func (*Client) Post

func (c *Client) Post(url string, hooks ...RequestHook) (*Response, error)

Post makes a POST HTTP request.

func (*Client) Put

func (c *Client) Put(url string, hooks ...RequestHook) (*Response, error)

Put makes a PUT HTTP request.

func (*Client) RegisterAfterResponseCallbacks

func (c *Client) RegisterAfterResponseCallbacks(callbacks ...AfterResponseCallback)

RegisterAfterResponseCallbacks appends c's after response callbacks.

func (*Client) RegisterBeforeRequestCallbacks

func (c *Client) RegisterBeforeRequestCallbacks(callbacks ...BeforeRequestCallback)

RegisterBeforeRequestCallbacks appends c's before request callbacks.

Example
package main

import (
	"fmt"

	neturl "net/url"

	"github.com/winterssy/ghttp"
)

func main() {
	withReverseProxy := func(target string) ghttp.RequestHook {
		return func(req *ghttp.Request) error {
			u, err := neturl.Parse(target)
			if err != nil {
				return err
			}

			req.URL.Scheme = u.Scheme
			req.URL.Host = u.Host
			req.Host = u.Host
			req.SetOrigin(u.Host)
			return nil
		}
	}

	client := ghttp.New()
	client.RegisterBeforeRequestCallbacks(withReverseProxy("https://httpbin.org"))

	resp, err := client.Get("/get")
	if err == nil {
		fmt.Println(resp.StatusCode)
	}
	resp, err = client.Post("/post")
	if err == nil {
		fmt.Println(resp.StatusCode)
	}
}
Output:

200
200

func (*Client) Send

func (c *Client) Send(method string, url string, hooks ...RequestHook) (*Response, error)

Send makes an HTTP request using a particular method.

func (*Client) SetMaxConcurrency

func (c *Client) SetMaxConcurrency(n int)

SetMaxConcurrency adds a callback to c for limiting the concurrent outbound requests up by n.

Example
package main

import (
	"sync"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()
	client.SetMaxConcurrency(32)

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			_, _ = client.Get("https://www.example.com")
		}()
	}
	wg.Wait()
}
Output:

func (*Client) SetProxy

func (c *Client) SetProxy(proxy func(*http.Request) (*neturl.URL, error))

SetProxy specifies a function to return a proxy for a given Request while nil indicates no proxy. By default is ProxyFromEnvironment.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()
	client.SetProxy(ghttp.ProxyURL("socks5://127.0.0.1:1080"))

	resp, err := client.Get("https://www.google.com")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

func (*Client) SetTLSClientConfig

func (c *Client) SetTLSClientConfig(config *tls.Config)

SetTLSClientConfig specifies the TLS configuration to use with tls.Client.

type Cookies

type Cookies map[string]string

Cookies is a shortcut for map[string]string, used for request cookies.

func (Cookies) Decode

func (c Cookies) Decode() []*http.Cookie

Decode translates c and returns the equivalent request cookies.

type File

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

File is a struct defines a file of a multipart section to upload.

func FileFromReader

func FileFromReader(body io.Reader) *File

FileFromReader constructors a new File from a reader.

func MustOpen

func MustOpen(filename string) *File

MustOpen is like Open, but if there is an error, it will panic.

func Open

func Open(filename string) (*File, error)

Open opens the named file and returns a File with filename specified.

func (*File) Close

func (f *File) Close() error

Close implements io.Closer interface.

func (*File) Read

func (f *File) Read(b []byte) (int, error)

Read implements io.Reader interface.

func (*File) WithFilename

func (f *File) WithFilename(filename string) *File

WithFilename specifies f's filename.

Example
package main

import (
	"encoding/base64"
	"strings"

	"github.com/winterssy/ghttp"
)

const picData = `
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6
JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACfFBMVEUAAABVVVU3TlI4T1Q4T1Q4TlQ4
TlQ4TlQ4TlQ3TlQ2T1QAgIA5T1Q4TlU4TlUAAAA5TVM4TlM4TlM4TVMAAAA4TlQ4TlQ4TlQ4TVQ5TFQ4
TlQ4T1Q5TlU4TlQ4T1U3TlU4TVM4T1Q4TlQ4TlU4TlU5UFc5TlQ5Ulc4TlQ5T1Q3T1U4TlQ4TlQ4TlM4
TlQ4TlQ7V19PhJJbobRnvdRtzedx1vF03vpHcn5boLJNfow/X2hfrMB03Pl24f503Pg/X2c7VV1VkqNX
mao+XWVAYmt13flis8lOg5J52/W07/7d9//l+f/S9f+g6v534f6j6/7H8//M9P+z7v6A4/5z2fVUkaFu
z+lz2/dw0u1pw9tJdoJz2PNTjZ1Sjp1z2vaE4/3q+v/////L9P+B4/7g+P/2/f+a6f524P5nvtZRiZhZ
n7Fmu9J23/x24P3Z9//4/f+G5f5UkaJOgZBsyeKX6P719fVfXFsqJiV5d3bx+/6T5/7S0tFAPTsxLiyy
sLDC8v9owNhFbXhjtcqYlpYXExHBwMCH5f6x7v5TUE8kIB7c9Ptv0OuamJfDwsFUUVAlIR/d9fxv0OqV
6P729vZjYV8uKih/fXvv+/6R5/7V1NREQUA2MjG1tLPB8f/e+P92l6A0R0w1S1GarbP3/f+F5P6E5P7o
+v////69yswjIB8qKCfX3t30/f+Y6P574v7j+f/P9f+1qaDDjHSFYlNJOTNMPDWQalmytLDD8v/J8/+v
7v5/4/553PjAjXa3j3x13vtgmql8k5S3n5TBpprCp5uwnJN6k5Zfn7Bz3PhrzObq8PH//PvX5elqyuTN
4ea82uJlwdpcsMZoxt8AAAA/l2hnAAAAL3RSTlMAA0GSvN7u8eOPPQK5ymkCWd/cVgFbw8BJQ/zj3P5X
wdbg9bvQ/lX0+GevsdrZ88Z1oBsAAAABYktHRACIBR1IAAAAB3RJTUUH5AIcDgA5dJXtcQAAAZ9JREFU
OMtjYCAWMDIxs7Cysenrs7NxsHBycSNkuHhYefn4BQT1UYCQsIiomKC4BAODpBSIL62vb2BoZGxiamZm
amJsZGigry8DEpeVY5DXN7ew1Ne3sraxRQJ21vb6Do5OzvoKDIouZq62bu4enl7ePr5gST//gMCg4JDQ
sPCISH0lBuWo6JjYuPiERBBI8rO1TU4BsVLT0jMys0L0VRgkVbMjcnLBgkAQZGubB2HlF9jahhfqyzEw
qKkXFZeAhErLyisq/apAzOqa2rp624ZGDU2QP7X0mzxBos0tLS2tbe0gZkdLS2eXrZu+NjggdPS7g0Ci
PUAFvQVgBX0tLf0TbCfq64IV6OnbTQKJTp4yddp0vxkg5sxZs+fMtbXT1wMr0Ne3tZ0HdeT8BQsXQViL
l9ja6uvDFSxdBhJcvmLlypWrVoOYa9baoiiwXdeet37Dxk2bt2zdtmn7jp27dtuiKQCBPXs3gcE+WICj
K9h/4OChw0eOHjuOS4HtiZOnTp8+c/YETgW2tudOnz6P4GFRcOHixUt4FaCCUQV0VQAAe4oDXnKi80AA
AAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDItMjhUMTQ6MDA6NTcrMDA6MDAP9tSBAAAAJXRFWHRkYXRl
Om1vZGlmeQAyMDIwLTAyLTI4VDE0OjAwOjU3KzAwOjAwfqtsPQAAAABJRU5ErkJggg==
`

func main() {
	file := ghttp.FileFromReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(picData))).WithFilename("image.jpg")
	_ = ghttp.Files{
		"field": file,
	}
	// Content-Disposition: form-data; name="field"; filename="image.jpg"
}
Output:

func (*File) WithMIME

func (f *File) WithMIME(mime string) *File

WithMIME specifies f's Content-Type. By default ghttp detects automatically using http.DetectContentType.

Example
package main

import (
	"github.com/winterssy/ghttp"
)

func main() {
	_ = ghttp.MustOpen("/path/image.png").WithMIME("image/png")
	// Content-Type: image/png
}
Output:

type Files

type Files map[string]*File

Files maps a string key to a *File type value, used for files of multipart payload.

type Form

type Form = KV

Form is an alias of KV, used for request form data.

type FormData

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

FormData is a multipart container that uses io.Pipe to reduce memory used while uploading files.

func NewMultipart

func NewMultipart(files Files) *FormData

NewMultipart returns a new multipart container.

func (*FormData) ContentType

func (fd *FormData) ContentType() string

ContentType returns the Content-Type for an HTTP multipart/form-data with this multipart Container's Boundary.

func (*FormData) Read

func (fd *FormData) Read(b []byte) (int, error)

Read implements io.Reader interface.

func (*FormData) WithForm

func (fd *FormData) WithForm(form Form) *FormData

WithForm specifies form for fd. If you only want to send form payload, use Request.SetForm or ghttp.WithForm instead.

type H

type H = gjson.Object

H is an alias of gjson.Object. Visit https://github.com/winterssy/gjson for more details.

type Headers

type Headers = KV

Headers is an alias of KV, used for request headers.

type KV

type KV map[string]interface{}

KV maps a string key to an interface{} type value, It's typically used for request query parameters, form data or headers.

func (KV) Decode

func (kv KV) Decode() map[string][]string

Decode translates kv and returns the equivalent request query parameters, form data or headers. It ignores any unexpected key-value pair.

func (KV) EncodeToJSON

func (kv KV) EncodeToJSON(opts ...func(enc *gjson.Encoder)) string

EncodeToJSON returns the JSON encoding of kv. If there is an error, it returns "{}".

func (KV) EncodeToURL

func (kv KV) EncodeToURL(escape bool) string

EncodeToURL encodes kv into URL form sorted by key if kv is considered as request query parameters or form data.

type Params

type Params = KV

Params is an alias of KV, used for for request query parameters.

type Request

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

Request is a wrapper around an http.Request.

func NewRequest

func NewRequest(method string, url string) (*Request, error)

NewRequest returns a new Request given a method, URL.

func (*Request) AddCookies

func (req *Request) AddCookies(cookies Cookies)

AddCookies adds cookies to req.

func (*Request) Dump

func (req *Request) Dump(withBody bool) ([]byte, error)

Dump returns the HTTP/1.x wire representation of req.

func (*Request) EnableClientTrace

func (req *Request) EnableClientTrace()

WithClientTrace enables client trace for req using httptrace.ClientTrace.

func (*Request) EnableRetrier

func (req *Request) EnableRetrier(opts ...RetryOption)

EnableRetrier enables retrier for req.

func (*Request) SetBearerToken

func (req *Request) SetBearerToken(token string)

SetBearerToken sets bearer token for req.

func (*Request) SetBody

func (req *Request) SetBody(body io.Reader)

SetBody sets body for req.

func (*Request) SetContent

func (req *Request) SetContent(content []byte)

SetContent sets bytes payload for req.

func (*Request) SetContentType

func (req *Request) SetContentType(contentType string)

SetContentType sets Content-Type header value for req.

func (*Request) SetContext

func (req *Request) SetContext(ctx context.Context)

SetContext sets context for req.

func (*Request) SetFiles

func (req *Request) SetFiles(files Files)

SetFiles sets files payload for req.

func (*Request) SetForm

func (req *Request) SetForm(form Form)

SetForm sets form payload for req.

func (*Request) SetHeaders

func (req *Request) SetHeaders(headers Headers)

SetHeaders sets headers for req. It replaces any existing values.

func (*Request) SetJSON

func (req *Request) SetJSON(data interface{}, opts ...func(enc *gjson.Encoder)) error

SetJSON sets JSON payload for req.

func (*Request) SetOrigin

func (req *Request) SetOrigin(origin string)

SetOrigin sets Origin header value for req.

func (*Request) SetQuery

func (req *Request) SetQuery(params Params)

SetQuery sets query parameters for req. It replaces any existing values.

func (*Request) SetReferer

func (req *Request) SetReferer(referer string)

SetReferer sets Referer header value for req.

func (*Request) SetText

func (req *Request) SetText(text string)

SetText sets plain text payload for req.

func (*Request) SetUserAgent

func (req *Request) SetUserAgent(userAgent string)

SetUserAgent sets User-Agent header value for req.

type RequestHook

type RequestHook func(req *Request) error

RequestHook is a function that implements BeforeRequestCallback interface. It provides a elegant way to configure a Request.

func WithBasicAuth

func WithBasicAuth(username string, password string) RequestHook

WithBasicAuth is a request hook to set basic authentication.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/basic-auth/admin/pass",
			ghttp.WithBasicAuth("admin", "pass"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetBoolean("authenticated"))
	fmt.Println(result.GetString("user"))
}
Output:

true
admin

func WithBearerToken

func WithBearerToken(token string) RequestHook

WithBearerToken is a request hook to set bearer token.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/bearer",
			ghttp.WithBearerToken("ghttp"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetBoolean("authenticated"))
	fmt.Println(result.GetString("token"))
}
Output:

true
ghttp

func WithBody

func WithBody(body io.Reader) RequestHook

WithBody is a request hook to set body.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	formData := ghttp.
		NewMultipart(ghttp.Files{
			"file1": ghttp.MustOpen("./testdata/testfile1.txt"),
			"file2": ghttp.MustOpen("./testdata/testfile2.txt"),
		}).
		WithForm(ghttp.Form{
			"k1": "v1",
			"k2": "v2",
		})

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithBody(formData),
			ghttp.WithContentType(formData.ContentType()),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("files", "file1"))
	fmt.Println(result.GetString("files", "file2"))
	fmt.Println(result.GetString("form", "k1"))
	fmt.Println(result.GetString("form", "k2"))
}
Output:

testfile1.txt
testfile2.txt
v1
v2

func WithClientTrace

func WithClientTrace() RequestHook

WithClientTrace is a request hook to enable client trace.

Example
package main

import (
	"fmt"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, _ := client.
		Get("https://httpbin.org/get",
			ghttp.WithClientTrace(),
		)
	fmt.Printf("%+v\n", resp.TraceInfo())
}
Output:

func WithContent

func WithContent(content []byte) RequestHook

WithContent is a request hook to set bytes payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithContent([]byte("hello world")),
			ghttp.WithContentType("text/plain; charset=utf-8"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("data"))
}
Output:

hello world

func WithContentType

func WithContentType(contentType string) RequestHook

WithContentType is a request hook to set Content-Type header value.

func WithContext

func WithContext(ctx context.Context) RequestHook

WithContext is a request hook to set context.

func WithCookies

func WithCookies(cookies Cookies) RequestHook

WithCookies is a request hook to add cookies.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/cookies",
			ghttp.WithCookies(ghttp.Cookies{
				"n1": "v1",
				"n2": "v2",
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("cookies", "n1"))
	fmt.Println(result.GetString("cookies", "n2"))
}
Output:

v1
v2

func WithFiles

func WithFiles(files Files) RequestHook

WithFiles is a request hook to set files payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithFiles(ghttp.Files{
				"file1": ghttp.MustOpen("./testdata/testfile1.txt"),
				"file2": ghttp.MustOpen("./testdata/testfile2.txt"),
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("files", "file1"))
	fmt.Println(result.GetString("files", "file2"))
}
Output:

testfile1.txt
testfile2.txt

func WithForm

func WithForm(form Form) RequestHook

WithForm is a request hook to set form payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithForm(ghttp.Form{
				"k1": "v1",
				"k2": "v2",
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("form", "k1"))
	fmt.Println(result.GetString("form", "k2"))
}
Output:

v1
v2

func WithHeaders

func WithHeaders(headers Headers) RequestHook

WithHeaders is a request hook to set headers. It replaces any existing values.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithHeaders(ghttp.Headers{
				"k1": "v1",
				"k2": "v2",
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("headers", "K1"))
	fmt.Println(result.GetString("headers", "K2"))
}
Output:

v1
v2

func WithJSON

func WithJSON(data interface{}, opts ...func(enc *gjson.Encoder)) RequestHook

WithJSON is a request hook to set JSON payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithJSON(map[string]interface{}{
				"msg": "hello world",
				"num": 2019,
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("json", "msg"))
	fmt.Println(result.GetNumber("json", "num"))
}
Output:

hello world
2019

func WithOrigin

func WithOrigin(origin string) RequestHook

WithOrigin is a request hook to set Origin header value.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/get",
			ghttp.WithOrigin("https://www.google.com"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("headers", "Origin"))
}
Output:

https://www.google.com

func WithQuery

func WithQuery(params Params) RequestHook

WithQuery is a request hook to set query parameters. It replaces any existing values.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithQuery(ghttp.Params{
				"k1": "v1",
				"k2": "v2",
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("args", "k1"))
	fmt.Println(result.GetString("args", "k2"))
}
Output:

v1
v2

func WithReferer

func WithReferer(referer string) RequestHook

WithReferer is a request hook to set Referer header value.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/get",
			ghttp.WithReferer("https://www.google.com"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("headers", "Referer"))
}
Output:

https://www.google.com

func WithRetrier

func WithRetrier(opts ...RetryOption) RequestHook

WithRetrier is a request hook to enable retrier.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.Post("https://api.example.com/login",
		ghttp.WithBasicAuth("user", "p@ssw$"),
		ghttp.WithRetrier(
			ghttp.WithRetryMaxAttempts(5),
		),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.StatusCode)
}
Output:

func WithText

func WithText(text string) RequestHook

WithText is a request hook to set plain text payload.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithText("hello world"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("data"))
}
Output:

hello world

func WithUserAgent

func WithUserAgent(userAgent string) RequestHook

WithUserAgent is a request hook to set User-Agent header value.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Get("https://httpbin.org/get",
			ghttp.WithUserAgent("ghttp"),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("headers", "User-Agent"))
}
Output:

ghttp

func (RequestHook) Enter

func (rh RequestHook) Enter(req *Request) error

Enter implements BeforeRequestCallback interface.

type Response

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

Response is a wrapper around an http.Response.

func (*Response) Content

func (resp *Response) Content() ([]byte, error)

Content reads from resp's body until an error or EOF and returns the data it read.

func (*Response) Cookie

func (resp *Response) Cookie(name string) (*http.Cookie, error)

Cookie returns the named cookie provided in resp. If multiple cookies match the given name, only one cookie will be returned.

func (*Response) Dump

func (resp *Response) Dump(body bool) ([]byte, error)

Dump returns the HTTP/1.x wire representation of resp.

func (*Response) H

func (resp *Response) H(opts ...func(dec *gjson.Decoder)) (H, error)

H is like JSON, but it unmarshals into an H instance. It provides a convenient way to read arbitrary JSON.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
)

func main() {
	client := ghttp.New()

	resp, err := client.
		Post("https://httpbin.org/post",
			ghttp.WithQuery(ghttp.Params{
				"k1": "v1",
				"k2": "v2",
			}),
			ghttp.WithHeaders(ghttp.Headers{
				"k3": "v3",
				"k4": "v4",
			}),
			ghttp.WithForm(ghttp.Form{
				"k5": "v5",
				"k6": "v6",
			}),
		)
	if err != nil {
		log.Print(err)
		return
	}

	result, err := resp.H()
	if err != nil {
		log.Print(err)
		return
	}

	fmt.Println(result.GetString("args", "k1"))
	fmt.Println(result.GetString("args", "k2"))
	fmt.Println(result.GetString("headers", "K3"))
	fmt.Println(result.GetString("headers", "K4"))
	fmt.Println(result.GetString("form", "k5"))
	fmt.Println(result.GetString("form", "k6"))
}
Output:

v1
v2
v3
v4
v5
v6

func (*Response) JSON

func (resp *Response) JSON(v interface{}, opts ...func(dec *gjson.Decoder)) error

JSON decodes resp's body and unmarshals its JSON-encoded data into v. v must be a pointer.

func (*Response) SaveFile

func (resp *Response) SaveFile(filename string, perm os.FileMode) (err error)

SaveFile saves resp's body into a file.

func (*Response) Text

func (resp *Response) Text(e ...encoding.Encoding) (string, error)

Text is like Content, but it decodes the data it read to a string given an optional charset encoding.

Example
package main

import (
	"fmt"
	"log"

	"github.com/winterssy/ghttp"
	"golang.org/x/text/encoding/simplifiedchinese"
)

func main() {
	client := ghttp.New()

	resp, err := client.Get("https://www.example.com")
	if err != nil {
		log.Fatal(err)
	}
	s, err := resp.Text()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(s)

	resp, err = client.Get("https://www.example.cn")
	if err != nil {
		log.Fatal(err)
	}
	s, err = resp.Text(simplifiedchinese.GBK)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(s)
}
Output:

func (*Response) TraceInfo

func (resp *Response) TraceInfo() (traceInfo *TraceInfo)

TraceInfo returns the trace info for the request if client trace is enabled.

type RetryOption

type RetryOption func(r *retrier)

RetryOption configures a retrier.

func WithRetryBackoff

func WithRetryBackoff(backoff Backoff) RetryOption

WithRetryBackoff is a retry option that specifies the backoff to a retrier. By default is an exponential backoff with jitter whose baseInterval is 1s and maxInterval is 30s.

func WithRetryMaxAttempts

func WithRetryMaxAttempts(n int) RetryOption

WithRetryMaxAttempts is a retry option that specifies the max attempts to a retrier while 0 means no retries. By default is 3.

func WithRetryTriggers

func WithRetryTriggers(triggers ...func(resp *Response, err error) bool) RetryOption

WithRetryTriggers is a retry option that specifies the triggers to a retrier for determining whether a request needs a retry. By default is the error isn't nil or the response status code is 429.

type TraceInfo

type TraceInfo struct {
	// DNSLookupTime is a duration that transport took to perform
	// DNS lookup.
	DNSLookupTime time.Duration `json:"dns_lookup_time"`

	// TCPConnTime is a duration that TCP connection took place.
	TCPConnTime time.Duration `json:"tcp_conn_time"`

	// TLSHandshakeTime is a duration that TLS handshake took place.
	TLSHandshakeTime time.Duration `json:"tls_handshake_time,omitempty"`

	// ConnTime is a duration that took to obtain a successful connection.
	ConnTime time.Duration `json:"conn_time"`

	// ServerTime is a duration that server took to respond first byte.
	ServerTime time.Duration `json:"server_time"`

	// ResponseTime is a duration since first response byte from server to
	// request completion.
	ResponseTime time.Duration `json:"response_time"`

	// TotalTime is a duration that total request took end-to-end.
	TotalTime time.Duration `json:"total_time"`

	// ConnReused reports whether this connection has been previously
	// used for another HTTP request.
	ConnReused bool `json:"conn_reused"`

	// ConnWasIdle reports whether this connection was obtained from an
	// idle pool.
	ConnWasIdle bool `json:"conn_was_idle"`

	// ConnIdleTime is a duration how long the connection was previously
	// idle, if ConnWasIdle is true.
	ConnIdleTime time.Duration `json:"conn_idle_time"`
}

TraceInfo is used to provide request trace info such as DNS lookup duration, Connection obtain duration, Server processing duration, etc.

Jump to

Keyboard shortcuts

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