Resty
Simple HTTP and REST client library for Go (inspired by Ruby rest-client)
Features section describes in detail about Resty capabilities
Resty Communication Channels
News
- v2.14.0 released and tagged on Aug 04, 2024.
- v2.0.0 released and tagged on Jul 16, 2019.
- v1.12.0 released and tagged on Feb 27, 2019.
- v1.0 released and tagged on Sep 25, 2017. - Resty's first version was released on Sep 15, 2015 then it grew gradually as a very handy and helpful library. Its been a two years since first release. I'm very thankful to Resty users and its contributors.
Features
- GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS, etc.
- Simple and chainable methods for settings and request
- Request Body can be
string
,[]byte
,struct
,map
,slice
andio.Reader
too- Auto detects
Content-Type
- Buffer less processing for
io.Reader
- Native
*http.Request
instance may be accessed during middleware and request execution viaRequest.RawRequest
- Request Body can be read multiple times via
Request.RawRequest.GetBody()
- Auto detects
- Response object gives you more possibility
- Access as
[]byte
array -response.Body()
OR Access asstring
-response.String()
- Know your
response.Time()
and when weresponse.ReceivedAt()
- Access as
- Automatic marshal and unmarshal for
JSON
andXML
content type- Default is
JSON
, if you supplystruct/map
without headerContent-Type
- For auto-unmarshal, refer to -
- Success scenario Request.SetResult() and Response.Result().
- Error scenario Request.SetError() and Response.Error().
- Supports RFC7807 -
application/problem+json
&application/problem+xml
- Resty provides an option to override JSON Marshal/Unmarshal and XML Marshal/Unmarshal
- Default is
- Easy to upload one or more file(s) via
multipart/form-data
- Auto detects file content type
- Request URL Path Params (aka URI Params)
- Backoff Retry Mechanism with retry condition function reference
- Resty client HTTP & REST Request and Response middlewares
Request.SetContext
supported- Authorization option of
BasicAuth
andBearer
token - Set request
ContentLength
value for all request or particular request - Custom Root Certificates and Client Certificates
- Download/Save HTTP response directly into File, like
curl -o
flag. See SetOutputDirectory & SetOutput. - Cookies for your request and CookieJar support
- SRV Record based request instead of Host URL
- Client settings like
Timeout
,RedirectPolicy
,Proxy
,TLSClientConfig
,Transport
, etc. - Optionally allows GET request with payload, see SetAllowGetMethodPayload
- Supports registering external JSON library into resty, see how to use
- Exposes Response reader without reading response (no auto-unmarshaling) if need be, see how to use
- Option to specify expected
Content-Type
when responseContent-Type
header missing. Refer to #92 - Resty design
- Have client level settings & options and also override at Request level if you want to
- Request and Response middleware
- Create Multiple clients if you want to
resty.New()
- Supports
http.RoundTripper
implementation, see SetTransport - goroutine concurrent safe
- Resty Client trace, see Client.EnableTrace and Request.EnableTrace
- Since v2.4.0, trace info contains a
RequestAttempt
value, and theRequest
object contains anAttempt
attribute
- Since v2.4.0, trace info contains a
- Supports
GenerateCurlCommand
(You should turn onEnableTrace
, otherwise the curl command will not contain the body) - Debug mode - clean and informative logging presentation
- Gzip - Go does it automatically also resty has fallback handling too
- Works fine with
HTTP/2
andHTTP/1.1
- Bazel support
- Easily mock Resty for testing, for e.g.
- Well tested client library
Included Batteries
- Redirect Policies - see how to use
- NoRedirectPolicy
- FlexibleRedirectPolicy
- DomainCheckRedirectPolicy
- etc. more info
- Retry Mechanism how to use
- SRV Record based request instead of Host URL how to use
- etc (upcoming - throw your idea's here).
Supported Go Versions
Recommended to use go1.16
and above.
Initially Resty started supporting go modules
since v1.10.0
release.
Starting Resty v2 and higher versions, it fully embraces go modules package release. It requires a Go version capable of understanding /vN
suffixed imports:
- 1.9.7+
- 1.10.3+
- 1.11+
It might be beneficial for your project :smile:
Resty author also published following projects for Go Community.
- aah framework - A secure, flexible, rapid Go web framework.
- THUMBAI - Go Mod Repository, Go Vanity Service and Simple Proxy Server.
- go-model - Robust & Easy to use model mapper and utility methods for Go
struct
.
Installation
# Go Modules
require github.com/go-resty/resty/v2 v2.11.0
Usage
The following samples will assist you to become as comfortable as possible with resty library.
// Import resty into your code and refer it as `resty`.
import "github.com/go-resty/resty/v2"
Simple POST
Refer: debug_curl_test.go
// Create a Resty Client
client := resty.New()
resp, err := client.R().
EnableTrace(). // You should turn on `EnableTrace`, otherwise the curl command will not contain the body
SetBody(map[string]string{"name": "Alex"}).
Post("https://httpbin.org/post")
curlCmdExecuted := resp.Request.GenerateCurlCommand()
// Explore curl command
fmt.Println("Curl Command:\n ", curlCmdExecuted+"\n")
// Explore response object
fmt.Println("Response Info:")
fmt.Println(" Error :", err)
fmt.Println(" Status Code:", resp.StatusCode())
fmt.Println(" Status :", resp.Status())
fmt.Println(" Proto :", resp.Proto())
fmt.Println(" Time :", resp.Time())
fmt.Println(" Received At:", resp.ReceivedAt())
fmt.Println(" Body :\n", resp)
fmt.Println()
// Explore trace info
fmt.Println("Request Trace Info:")
ti := resp.Request.TraceInfo()
fmt.Println(" DNSLookup :", ti.DNSLookup)
fmt.Println(" ConnTime :", ti.ConnTime)
fmt.Println(" TCPConnTime :", ti.TCPConnTime)
fmt.Println(" TLSHandshake :", ti.TLSHandshake)
fmt.Println(" ServerTime :", ti.ServerTime)
fmt.Println(" ResponseTime :", ti.ResponseTime)
fmt.Println(" TotalTime :", ti.TotalTime)
fmt.Println(" IsConnReused :", ti.IsConnReused)
fmt.Println(" IsConnWasIdle :", ti.IsConnWasIdle)
fmt.Println(" ConnIdleTime :", ti.ConnIdleTime)
fmt.Println(" RequestAttempt:", ti.RequestAttempt)
fmt.Println(" RemoteAddr :", ti.RemoteAddr.String())
/* Output
Curl Command:
curl -X POST -H 'Content-Type: application/json' -H 'User-Agent: go-resty/2.14.0 (https://github.com/go-resty/resty)' -d '{"name":"Alex"}' https://httpbin.org/post
Response Info:
Error : <nil>
Status Code: 200
Status : 200 OK
Proto : HTTP/2.0
Time : 457.034718ms
Received At: 2024-08-09 13:02:57.187544 +0800 CST m=+1.304888501
Body :
{
"args": {},
"data": "{\"name\":\"Alex\"}",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "gzip",
"Content-Length": "15",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "go-resty/2.14.0 (https://github.com/go-resty/resty)",
"X-Amzn-Trace-Id": "Root=1-66b5a301-567c83c86562abd3092f5e19"
},
"json": {
"name": "Alex"
},
"origin": "0.0.0.0",
"url": "https://httpbin.org/post"
}
Request Trace Info:
DNSLookup : 4.074657ms
ConnTime : 381.709936ms
TCPConnTime : 77.428048ms
TLSHandshake : 299.623597ms
ServerTime : 75.414703ms
ResponseTime : 79.337µs
TotalTime : 457.034718ms
IsConnReused : false
IsConnWasIdle : false
ConnIdleTime : 0s
RequestAttempt: 1
RemoteAddr : 3.221.81.55:443
*/
Enhanced GET
// Create a Resty Client
client := resty.New()
resp, 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")
// Sample of using Request.SetQueryString method
resp, err := client.R().
SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
SetHeader("Accept", "application/json").
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/show_product")
// If necessary, you can force response content type to tell Resty to parse a JSON response into your struct
resp, err := client.R().
SetResult(result).
ForceContentType("application/json").
Get("v2/alpine/manifests/latest")
Various POST method combinations
// Create a Resty Client
client := resty.New()
// POST JSON string
// No need to set content type, if you have client level setting
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(`{"username":"testuser", "password":"testpass"}`).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
Post("https://myapp.com/login")
// POST []byte array
// No need to set content type, if you have client level setting
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
Post("https://myapp.com/login")
// POST Struct, default is JSON content type. No need to set one
resp, err := client.R().
SetBody(User{Username: "testuser", Password: "testpass"}).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
SetError(&AuthError{}). // or SetError(AuthError{}).
Post("https://myapp.com/login")
// POST Map, default is JSON content type. No need to set one
resp, err := client.R().
SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}).
SetResult(&AuthSuccess{}). // or SetResult(AuthSuccess{}).
SetError(&AuthError{}). // or SetError(AuthError{}).
Post("https://myapp.com/login")
// POST of raw bytes for file upload. For example: upload file to Dropbox
fileBytes, _ :=