resty Documentation

Simple HTTP, REST, and SSE client library for Go

RAW Doc

1. Project Overview & Quickstart (go-resty/resty)

Documentation

Go to https://resty.dev and refer to godoc.

Minimum Go Version

Use go1.23 and above.

Support & Donate

Versioning

Resty releases versions according to Semantic Versioning

  • Resty v3 provides Go Vanity URL resty.dev/v3.
  • Resty v2 migrated away from gopkg.in service, github.com/go-resty/resty/v2.
  • Resty fully adapted to go mod capabilities since v1.10.0 release.
  • Resty v1 series was using gopkg.in to provide versioning. gopkg.in/resty.vX points to appropriate tagged versions; X denotes version series number and it's a stable release for production use. For e.g. gopkg.in/resty.v0.

Contribution

I would welcome your contribution!

  • If you find any improvement or issue you want to fix, feel free to send a pull request.
  • The pull requests must include test cases for feature/fix/enhancement with patch coverage of 100%.
  • I have done my best to bring pretty good coverage. I would request contributors to do the same for their contribution.

I always look forward to hearing feedback, appreciation, and real-world usage stories from Resty users on GitHub Discussions. It means a lot to me.

Creator

Jeevanandam M. ([email protected])

Contributors

Have a look on Contributors page.

License Info

Resty released under MIT LICENSE.

Resty Documentation and website released under Apache-2.0 LICENSE.

2. Official Technical Reference & Guides (go-resty/docs)

File: README.md

Documentation

Go to https://resty.dev and refer to godoc.

Contribution

I would welcome your contribution! If you find any improvement, correction, or want to add new documentation pages, feel free to send a pull request.

Run Documentation Website Locally

Resty uses the Hugo static site generator. It requires v0.146 and above.

shell
hugo server --minify

Go to http://localhost:1313/ to see the documentation website.

Contributors

Have a look on Contributors page.

License Info

Resty Documentation and website released under Apache-2.0 LICENSE.


File: content/docs/example/custom-dns-resolver.md

Custom DNS Resolver

Resty v3 introduces additional methods for creating client instances, including the [NewWithDialer]({{% godoc v3 %}}NewWithDialer) function.

go
package main

import (
	"context"
	"fmt"
	"net"
	"time"

	"resty.dev/v3"
)

func main() {
	dialer := &net.Dialer{
		Resolver: &net.Resolver{
			PreferGo: true,
			Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
				d := net.Dialer{
					Timeout: time.Duration(20) * time.Second,
				}
				return d.DialContext(ctx, "udp", "9.9.9.9:53") // Quad9 DNS
			},
		},
	}

	c := resty.NewWithDialer(dialer)
	defer c.Close()

	res, err := c.R().Get("https://httpbin.org/get")
	fmt.Println(err, res)
}

File: content/docs/example/decompress-brotli.md

Brotli Decompress

Resty v3 allows users to add decompression logic for HTTP responses using their favorite package.

[!NOTE]
Using sync.Pool can reuse the reader and reduce allocation if the package supports Reset.

Example 1

Package: github.com/andybalholm/brotli

go
c := resty.New()
defer c.Close()

// Add decompresser into Resty
client.AddContentDecompresser("br", decompressBrotli)

// Create Brotli decompress logic
func decompressBrotli(r io.ReadCloser) (io.ReadCloser, error) {
	br := &brotliReader{s: r, r: brotli.NewReader(r)}
	return br, nil
}

type brotliReader struct {
	s io.ReadCloser
	r *brotli.Reader
}

func (b *brotliReader) Read(p []byte) (n int, err error) {
	return b.r.Read(p)
}

func (b *brotliReader) Close() error {
	return b.s.Close()
}

Example 2

Package: github.com/dsnet/compress

go
c := resty.New()
defer c.Close()

// Add decompresser into Resty
client.AddContentDecompresser("br", decompressBrotli)

// Create Brotli decompress logic
func decompressBrotli(r io.ReadCloser) (io.ReadCloser, error) {
	br, err := brotli.NewReader(r, nil)
	if err != nil {
		return nil, err
	}
	b := &brotliReader{s: r, r: br}
	return b, nil
}

type brotliReader struct {
	s io.ReadCloser
	r *brotli.Reader
}

func (b *brotliReader) Read(p []byte) (n int, err error) {
	return b.r.Read(p)
}

func (b *brotliReader) Close() error {
	_ = b.r.Close()
	return b.s.Close()
}

File: content/docs/example/decompress-zstandard.md

Zstandard Decompress

Resty v3 allows users to add decompression logic for HTTP responses using their favorite package.

[!NOTE]
Using sync.Pool can reuse the reader and reduce allocation if the package supports Reset.

Example

Package: github.com/klauspost/compress/zstd

go
c := resty.New()
defer c.Close()

// Add decompresser into Resty
client.AddContentDecompresser("zstd", decompressZstd)

// Create Zstandard decompress logic
func decompressZstd(r io.ReadCloser) (io.ReadCloser, error) {
	zr, err := zstd.NewReader(r)
	if err != nil {
		return nil, err
	}
	z := &zstdReader{s: r, r: zr}
	return z, nil
}

type zstdReader struct {
	s io.ReadCloser
	r *zstd.Decoder
}

func (b *zstdReader) Read(p []byte) (n int, err error) {
	return b.r.Read(p)
}

func (b *zstdReader) Close() error {
	b.r.Close()
	return b.s.Close()
}

File: content/docs/example/delete-request.md


title: DELETE Request weight: 2

DELETE Request

This page discusses simple DELETE requests. Resty features can be used across nearly all HTTP methods.

[!NOTE]

  • Explore the documentation for additional use cases.
  • Examples use request-level methods; however, Resty also includes client-level methods to configure settings for all requests.

Examples

See [Request Body Types]({{% relref "request-body-types" %}}), [Allow Payload On]({{% relref "allow-payload-on" %}})

go
// create a Resty client
client := resty.New()
defer client.Close()

Simple

go
res, err := client.R().
    SetAuthToken("bc594900518b4f7eac75bd37f019e08fbc594900518b4f7eac75bd37f019e08f").
    SetResultError(&Error{}). // or SetResultError(Error{}).
    Delete("https://myapp.com/articles/123456")

fmt.Println(err, res)
fmt.Println(res.ResultError().(*Error))

With Payload

See [Allow Payload On]({{% relref "allow-payload-on" %}})

go
res, err := client.R().
    SetAuthToken("bc594900518b4f7eac75bd37f019e08fbc594900518b4f7eac75bd37f019e08f").
    SetBody(map[string]any{
        "article_ids": []int{1002, 1006, 1007, 87683, 45432},
    }). // default request content type is JSON
    SetResultError(&Error{}). // or SetResultError(Error{}).
    Delete("https://myapp.com/articles")

fmt.Println(err, res)
fmt.Println(res.ResultError().(*Error))

File: content/docs/example/enable-http3.md


title: Enable HTTP3

Enable HTTP3

HTTP3 is not yet included in the Go standard packages. However, the HTTP3 package is available from the community.

Package: github.com/quic-go/quic-go

Documentation: https://quic-go.net/docs/

Example

go
// Refer to quic-go docs to customize configuration
// https://quic-go.net/docs/
http3Transport := &http3.Transport{
    TLSClientConfig: &tls.Config{}, // set a TLS client config, if desired
    QUICConfig: &quic.Config{ // QUIC connection options
        MaxIdleTimeout:  45 * time.Second,
        KeepAlivePeriod: 30 * time.Second,
    },
}
defer http3Transport.Close()

c := resty.New().
    SetTransport(http3Transport)
defer c.Close()

// You're ready to use HTTP3 with Resty

File: content/docs/example/get-request.md


title: GET Request weight: 1

GET Request

This page discusses simple GET requests. Resty features can be used across nearly all HTTP methods.

[!NOTE]

  • Explore the documentation for additional use cases.
  • Examples use request-level methods; however, Resty also includes client-level methods to configure settings for all requests.

Examples

See [Request Body Types]({{% relref "request-body-types" %}}), [Allow Payload On]({{% relref "allow-payload-on" %}})

go
// create a Resty client
client := resty.New()
defer client.Close()

Simple

go
res, err := client.R().
    Get("https://httpbin.org/get")

fmt.Println(err, res)

With Query Params

See [Request Query Params]({{% relref "request-query-params" %}})

go
res, err := client.R().
    SetQueryParams(map[string]string{
        "page_no": "1",
        "limit":   "20",
        "sort":    "name",
        "order":   "asc",
        "random":  strconv.FormatInt(time.Now().Unix(), 10),
    }).
    SetHeader("Accept", "application/json").
    SetAuthToken("bc594900518b4f7eac75bd37f019e08fbc594900518b4f7eac75bd37f019e08f").
    Get("/search_result")

fmt.Println(err, res)

With Path Params

See [Request Path Params]({{% relref "request-path-params" %}})

go
res, err := client.R().
    SetPathParams(map[string]string{
		"userId":       "[email protected]",
		"subAccountId": "100002",
	}).
    SetAuthToken("bc594900518b4f7eac75bd37f019e08fbc594900518b4f7eac75bd37f019e08f").
    Get("/v1/users/{userId}/{subAccountId}/details")

fmt.Println(err, res)

With Payload

See [Allow Payload On]({{% relref "allow-payload-on" %}})

go
res, err := client.R().
    SetMethodGetAllowPayload(true). // client-level option is available
    SetContentType("application/json").
    SetBody(`{
        "query": {
            "simple_query_string" : {
                "query": "\"fried eggs\" +(eggplant | potato) -frittata",
                "fields": ["title^5", "body"],
                "default_operator": "and"
            }
        }
    }`). // this is string value as request body
    SetAuthToken("bc594900518b4f7eac75bd37f019e08fbc594900518b4f7eac75bd37f019e08f").
    Get("/_search")

fmt.Println(err, res)

File: content/docs/example/how-to-do-dry-run.md


title: How to do Dry-Run?

How to do Dry-Run?

The appropriate way to do Dry-Run implementation with Resty is to implement custom transport using the http.RoundTripper interface.

With custom transport, the user could perform any use case handling for Dry-Run.

go
type DryRunTransport struct {
    http.RoundTripper
}

func (dr *DryRunTransport) RoundTrip(r *http.Request) (*http.Response, error) {
    // implement Dry-Run logic here ...

    return resp, err
}

c := resty.New().
    SetTransport(&DryRunTransport{
        // initialize dry-run fields
    })

defer c.Close()

// start using the Resty client with dry-run ...

File: content/docs/example/oauth2-client-credentials.md


title: OAuth2 Client Credentials

OAuth2 Client Credentials

Without Modifying

[!NOTE]
As per the GoDoc of clientcredentials#Config.Client

  • The returned Client and its Transport should not be modified.
go
clientCredCfg := &clientcredentials.Config{
    /* initialize values ... */
}

// create a client
credClient := clientCredCfg.Client(context.Background())

// create a Resty client
c := resty.NewWithClient(credClient)
defer c.Close()

// start using a resty client

Modifying

This scenario applies to any client and transport-related configurations, such as adding Root CA, Client Root CA, Client SSL certificates, transport timeouts, and so on.

[!NOTE]

  • As per the GoDoc of clientcredentials#Config.Client
    • The returned Client and its Transport should not be modified.
  • To use the oauth2 client credentials package and make modifications to it, a minor adjustment is necessary.
go
clientCredCfg := &clientcredentials.Config{
    /* initialize values ... */
}

// create a Resty client
c := resty.New()
defer c.Close()

// configure required Root CA, Client Root CA, or Client SSL certs
// c.SetRootCertificates("/path/to/root/pemFile.pem")
// c.SetClientRootCertificates("/path/to/client-root/pemFile.pem")
// c.SetCertificateFromFile("/path/to/certs/client.pem", "/path/to/certs/client.key")

// add custom auth request middleware
c.AddRequestMiddleware(func(c *resty.Client, req *resty.Request) error {
    // get the token from client credentials
    token, err := clientCredCfg.Token(req.Context())
    if err != nil {
        return err
    }

    // set it on the request
    req.SetAuthScheme(token.Type()). // if it is "Bearer", you can skip this line
        SetAuthToken(token.AccessToken)

    return nil
})

// start using a resty client