[![Build Status](https://img.shields.io/travis/franela/goreq/master.svg)](https://travis-ci.org/franela/goreq) [![GoDoc](https://godoc.org/github.com/franela/goreq?status.svg)](https://godoc.org/github.com/franela/goreq) GoReq ======= Simple and sane HTTP request library for Go language. **Table of Contents** - [Why GoReq?](#user-content-why-goreq) - [How do I install it?](#user-content-how-do-i-install-it) - [What can I do with it?](#user-content-what-can-i-do-with-it) - [Making requests with different methods](#user-content-making-requests-with-different-methods) - [GET](#user-content-get) - [Tags](#user-content-tags) - [POST](#user-content-post) - [Sending payloads in the Body](#user-content-sending-payloads-in-the-body) - [Specifiying request headers](#user-content-specifiying-request-headers) - [Sending Cookies](#cookie-support) - [Setting timeouts](#user-content-setting-timeouts) - [Using the Response and Error](#user-content-using-the-response-and-error) - [Receiving JSON](#user-content-receiving-json) - [Sending/Receiving Compressed Payloads](#user-content-sendingreceiving-compressed-payloads) - [Using gzip compression:](#user-content-using-gzip-compression) - [Using deflate compression:](#user-content-using-deflate-compression) - [Using compressed responses:](#user-content-using-compressed-responses) - [Proxy](#proxy) - [Debugging requests](#debug) - [Getting raw Request & Response](#getting-raw-request--response) - [TODO:](#user-content-todo) Why GoReq? ========== Go has very nice native libraries that allows you to do lots of cool things. But sometimes those libraries are too low level, which means that to do a simple thing, like an HTTP Request, it takes some time. And if you want to do something as simple as adding a timeout to a request, you will end up writing several lines of code. This is why we think GoReq is useful. Because you can do all your HTTP requests in a very simple and comprehensive way, while enabling you to do more advanced stuff by giving you access to the native API. How do I install it? ==================== ```bash go get github.com/franela/goreq ``` What can I do with it? ====================== ## Making requests with different methods #### GET ```go res, err := goreq.Request{ Uri: "http://www.google.com" }.Do() ``` GoReq default method is GET. You can also set value to GET method easily ```go type Item struct { Limit int Skip int Fields string } item := Item { Limit: 3, Skip: 5, Fields: "Value", } res, err := goreq.Request{ Uri: "http://localhost:3000/", QueryString: item, }.Do() ``` The sample above will send `http://localhost:3000/?limit=3&skip=5&fields=Value` Alternatively the `url` tag can be used in struct fields to customize encoding properties ```go type Item struct { TheLimit int `url:"the_limit"` TheSkip string `url:"the_skip,omitempty"` TheFields string `url:"-"` } item := Item { TheLimit: 3, TheSkip: "", TheFields: "Value", } res, err := goreq.Request{ Uri: "http://localhost:3000/", QueryString: item, }.Do() ``` The sample above will send `http://localhost:3000/?the_limit=3` QueryString also support url.Values ```go item := url.Values{} item.Set("Limit", 3) item.Add("Field", "somefield") item.Add("Field", "someotherfield") res, err := goreq.Request{ Uri: "http://localhost:3000/", QueryString: item, }.Do() ``` The sample above will send `http://localhost:3000/?limit=3&field=somefield&field=someotherfield` ### Tags Struct field `url` tag is mainly used as the request parameter name. Tags can be comma separated multiple values, 1st value is for naming and rest has special meanings. - special tag for 1st value - `-`: value is ignored if set this - special tag for rest 2nd value - `omitempty`: zero-value is ignored if set this - `squash`: the fields of embedded struct is used for parameter #### Tag Examples ```go type Place struct { Country string `url:"country"` City string `url:"city"` ZipCode string `url:"zipcode,omitempty"` } type Person struct { Place `url:",squash"` FirstName string `url:"first_name"` LastName string `url:"last_name"` Age string `url:"age,omitempty"` Password string `url:"-"` } johnbull := Person{ Place: Place{ // squash the embedded struct value Country: "UK", City: "London", ZipCode: "SW1", }, FirstName: "John", LastName: "Doe", Age: "35", Password: "my-secret", // ignored for parameter } goreq.Request{ Uri: "http://localhost/", QueryString: johnbull, }.Do() // => `http://localhost/?first_name=John&last_name=Doe&age=35&country=UK&city=London&zip_code=SW1` // age and zipcode will be ignored because of `omitempty` // but firstname isn't. samurai := Person{ Place: Place{ // squash the embedded struct value Country: "Japan", City: "Tokyo", }, LastName: "Yagyu", } goreq.Request{ Uri: "http://localhost/", QueryString: samurai, }.Do() // => `http://localhost/?first_name=&last_name=yagyu&country=Japan&city=Tokyo` ``` #### POST ```go res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com" }.Do() ``` ## Sending payloads in the Body You can send ```string```, ```Reader``` or ```interface{}``` in the body. The first two will be sent as text. The last one will be marshalled to JSON, if possible. ```go type Item struct { Id int Name string } item := Item{ Id: 1111, Name: "foobar" } res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com", Body: item, }.Do() ``` ## Specifiying request headers We think that most of the times the request headers that you use are: ```Host```, ```Content-Type```, ```Accept``` and ```User-Agent```. This is why we decided to make it very easy to set these headers. ```go res, err := goreq.Request{ Uri: "http://www.google.com", Host: "foobar.com", Accept: "application/json", ContentType: "application/json", UserAgent: "goreq", }.Do() ``` But sometimes you need to set other headers. You can still do it. ```go req := goreq.Request{ Uri: "http://www.google.com" } req.AddHeader("X-Custom", "somevalue") req.Do() ``` Alternatively you can use the `WithHeader` function to keep the syntax short ```go res, err = goreq.Request{ Uri: "http://www.google.com" }.WithHeader("X-Custom", "somevalue").Do() ``` ## Cookie support Cookies can be either set at the request level by sending a [CookieJar](http://golang.org/pkg/net/http/cookiejar/) in the `CookieJar` request field or you can use goreq's one-liner WithCookie method as shown below ```go res, err := goreq.Request{ Uri: "http://www.google.com", }. WithCookie(&http.Cookie{Name: "c1", Value: "v1"}). Do() ``` ## Setting timeouts GoReq supports 2 kind of timeouts. A general connection timeout and a request specific one. By default the connection timeout is of 1 second. There is no default for request timeout, which means it will wait forever. You can change the connection timeout doing: ```go goreq.SetConnectTimeout(100 * time.Millisecond) ``` And specify the request timeout doing: ```go res, err := goreq.Request{ Uri: "http://www.google.com", Timeout: 500 * time.Millisecond, }.Do() ``` ## Using the Response and Error GoReq will always return 2 values: a ```Response``` and an ```Error```. If ```Error``` is not ```nil``` it means that an error happened while doing the request and you shouldn't use the ```Response``` in any way. You can check what happened by getting the error message: ```go fmt.Println(err.Error()) ``` And to make it easy to know if it was a timeout error, you can ask the error or return it: ```go if serr, ok := err.(*goreq.Error); ok { if serr.Timeout() { ... } } return err ``` If you don't get an error, you can safely use the ```Response```. ```go res.Uri // return final URL location of the response (fulfilled after redirect was made) res.StatusCode // return the status code of the response res.Body // gives you access to the body res.Body.ToString() // will return the body as a string res.Header.Get("Content-Type") // gives you access to all the response headers ``` Remember that you should **always** close `res.Body` if it's not `nil` ## Receiving JSON GoReq will help you to receive and unmarshal JSON. ```go type Item struct { Id int Name string } var item Item res.Body.FromJsonTo(&item) ``` ## Sending/Receiving Compressed Payloads GoReq supports gzip, deflate and zlib compression of requests' body and transparent decompression of responses provided they have a correct `Content-Encoding` header. ##### Using gzip compression: ```go res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com", Body: item, Compression: goreq.Gzip(), }.Do() ``` ##### Using deflate/zlib compression: ```go res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com", Body: item, Compression: goreq.Deflate(), }.Do() ``` ##### Using compressed responses: If servers replies a correct and matching `Content-Encoding` header (gzip requires `Content-Encoding: gzip` and deflate `Content-Encoding: deflate`) goreq transparently decompresses the response so the previous example should always work: ```go type Item struct { Id int Name string } res, err := goreq.Request{ Method: "POST", Uri: "http://www.google.com", Body: item, Compression: goreq.Gzip(), }.Do() var item Item res.Body.FromJsonTo(&item) ``` If no `Content-Encoding` header is replied by the server GoReq will return the crude response. ## Proxy If you need to use a proxy for your requests GoReq supports the standard `http_proxy` env variable as well as manually setting the proxy for each request ```go res, err := goreq.Request{ Method: "GET", Proxy: "http://myproxy:myproxyport", Uri: "http://www.google.com", }.Do() ``` ### Proxy basic auth is also supported ```go res, err := goreq.Request{ Method: "GET", Proxy: "http://user:pass@myproxy:myproxyport", Uri: "http://www.google.com", }.Do() ``` ## Debug If you need to debug your http requests, it can print the http request detail. ```go res, err := goreq.Request{ Method: "GET", Uri: "http://www.google.com", Compression: goreq.Gzip(), ShowDebug: true, }.Do() fmt.Println(res, err) ``` and it will print the log: ``` GET / HTTP/1.1 Host: www.google.com Accept: Accept-Encoding: gzip Content-Encoding: gzip Content-Type: ``` ### Getting raw Request & Response To get the Request: ```go req := goreq.Request{ Host: "foobar.com", } //req.Request will return a new instance of an http.Request so you can safely use it for something else request, _ := req.NewRequest() ``` To get the Response: ```go res, err := goreq.Request{ Method: "GET", Uri: "http://www.google.com", Compression: goreq.Gzip(), ShowDebug: true, }.Do() // res.Response will contain the original http.Response structure fmt.Println(res.Response, err) ``` TODO: ----- We do have a couple of [issues](https://github.com/franela/goreq/issues) pending we'll be addressing soon. But feel free to contribute and send us PRs (with tests please :smile:).