Goreq - Minimal and simple request library for Go language

Build Status GoDoc

GoReq

Simple and sane HTTP request library for Go language.

Table of Contents

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?

go get github.com/franela/goreq

What can I do with it?

Making requests with different methods

GET

res, err := goreq.Request{ Uri: "http://www.google.com" }.Do()

GoReq default method is GET.

You can also set value to GET method easily

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

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

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

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

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.

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.

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.

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

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 in the CookieJar request field or you can use goreq's one-liner WithCookie method as shown below

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:

goreq.SetConnectTimeout(100 * time.Millisecond)

And specify the request timeout doing:

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:

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:

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.

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.

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:
res, err := goreq.Request{
    Method: "POST",
    Uri: "http://www.google.com",
    Body: item,
    Compression: goreq.Gzip(),
}.Do()
Using deflate/zlib compression:
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:

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

res, err := goreq.Request{
    Method: "GET",
    Proxy: "http://myproxy:myproxyport",
    Uri: "http://www.google.com",
}.Do()

Proxy basic auth is also supported

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.

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:

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:

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 pending we'll be addressing soon. But feel free to contribute and send us PRs (with tests please 😄 ).

Comments
  • 301 302 go func(){}() error

    301 302 go func(){}() error

    func main() { s := []string{"http://www.120ask.com", "http://www.120ask.com/question/72742256.htm"} for _, uri := range s { //go curl(uri) // BUG: keyword go Error redirecting. MaxRedirects reached curl(uri) // right } time.Sleep(10 * time.Second) } func curl(uri string) { goreq.SetConnectTimeout(60 * time.Second) res, err := goreq.Request{ Uri: uri, Timeout: 60 * time.Second, }.Do() if err != nil { log.Println("request err", err, res) return } _, err = res.Body.ToString() if res.Body != nil { res.Body.Close() } log.Println(res.StatusCode, err) }

  • Possible for a tag/release of the

    Possible for a tag/release of the "stable"

    My company is using this library in a few of our projects and we'd like to freeze our vendor library to isolate from any potentially breaking changes on master. While I know we could just pick a random commit and do it ourselves it would be nice if there was some sort of accepted "release" version.

    Thanks

  • unknown http.Transport field 'ProxyConnectHeader' in struct literal

    unknown http.Transport field 'ProxyConnectHeader' in struct literal

    The latest version of project does not work. When we run the tests we see this error.

    github.com/franela/goreq ./goreq.go:324: unknown http.Transport field 'ProxyConnectHeader' in struct literal ./goreq.go:329: proxyTransport.ProxyConnectHeader undefined (type *http.Transport has no field or method ProxyConnectHeader)

  • Timeout unit tests fail

    Timeout unit tests fail

    3 tests failed:

    1. Connection timeouts Should connect timeout after a default of 1000 ms:
    Expected
    <time.Duration>: 240200
    

    to be >= <time.Duration>: 1000000000 /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:42 +0x76 /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:69 +0x1ef /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:27 +0xae /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:754 +0x34e /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x27 /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x460 2) Connection timeouts Should connect timeout after a custom amount of time:

    Expected
    <time.Duration>: 157638
    

    to be >= <time.Duration>: 100000000 /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:42 +0x76 /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:69 +0x1ef /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:27 +0xae /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:765 +0x35c /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x27 /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x460 3) Connection timeouts Should connect timeout after a custom amount of time even with method set:

    Expected
    <time.Duration>: 153784
    

    to be >= <time.Duration>: 100000000 /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:42 +0x76 /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:69 +0x1ef /usr/share/gocode/src/github.com/onsi/gomega/internal/assertion/assertion.go:27 +0xae /builddir/build/BUILD/goreq-b5b0f5eb2d16f20345cce0a544a75163579c0b00/_build/src/github.com/franela/goreq/goreq_test.go:780 +0x3c2 /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x27 /usr/share/gocode/src/github.com/franela/goblin/goblin.go:216 +0x460 --- FAIL: TestRequest (1.56s)

    with:

    golang-github-franela-goblin-devel.noarch 0.0.2-0.1.gitb962efd.fc28.llt
    golang-github-onsi-gomega-devel.noarch 1.0-0.4.git2152b45.fc27 golang-googlecode-goprotobuf-devel.noarch 0-0.30.git24f28ae.fc28

  • Empty URI in response

    Empty URI in response

    I have a weird glitch. The following is returning nil for me:

    		resp, err := goreq.Request{Uri: "http://www.americanas.com.br/produto/19193988/pneu-pirelli-cinturato-p1-plus-195-55r15-85v?chave=prf_hm_0_oh_2_txar_00"}.Do()
    		fmt.Printf("%+v %s", resp.Uri, err)
    ``
    
    Shouldn't resp.Uri always be not empty?
Related tags
Timeout handler for http request in Gin framework

Middleware to Handle Request Timeout in Gin Installation Installation go get github.com/s-wijaya/gin-timeout Import it in your code: import ( // o

Dec 14, 2021
Compost-go - Post pull request comments to multiple VCSs
Compost-go - Post pull request comments to multiple VCSs

Compost Compost is for tools that run in CI pipelines and want to post results a

Feb 15, 2022
Go-app is a package to build progressive web apps with Go programming language and WebAssembly.
Go-app is a package to build progressive web apps with Go programming language and WebAssembly.

Go-app is a package to build progressive web apps with Go programming language and WebAssembly.

Dec 30, 2022
Rest-and-go-master - A basic online store API written to learn Go Programming Language
Rest-and-go-master - A basic online store API written to learn Go Programming Language

rest-and-go(Not maintained actively) A basic online store API written to learn G

Jan 12, 2022
This library provides a simple framework of microservice, which includes a configurator, a logger, metrics, and of course the handler

Microservice The framework for the creation of microservices, written in Golang. (note: http microservice) Architecture microservice includes: handle

Dec 30, 2022
beego is an open-source, high-performance web framework for the Go programming language.
beego is an open-source, high-performance web framework for the Go programming language.

Beego Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend services. It is inspired by To

Jan 1, 2023
A high productivity, full-stack web framework for the Go language.

Revel Framework A high productivity, full-stack web framework for the Go language. Current Version: 1.0.0 (2020-07-11) Supports go.mod package managem

Jan 7, 2023
Goal is a toolkit for high productivity web development in Go language in the spirit of Revel Framework that is built around the concept of code generation.

Goal Goal is a set of tools for high productivity web development in Go language. Goal, being mostly inspired by Revel Framework and its discussions,

Sep 27, 2021
beego is an open-source, high-performance web framework for the Go programming language.
beego is an open-source, high-performance web framework for the Go programming language.

Beego Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend services. It is inspired by To

Jan 8, 2023
Go Language Facilitator
Go Language Facilitator

golf The Go Language Facilitator tool is used to process in-file code while copying a source to a destination file. It is basically helpful when diffe

May 6, 2021
letgo is an open-source, high-performance web framework for the Go programming language.

high-performance Lightweight web framework for the Go programming language. golang web framework,高可用golang web框架,go语言 web框架 ,go web

Sep 23, 2022
Short basic introduction to Go programming language.
Short basic introduction to Go programming language.

Go, Go! Short basic introduction to Go v1.17.6 programming language Go Logo is Copyright 2018 The Go Authors. All rights reserved. About This work was

May 30, 2022
Superlint is an experimental, language-agnostic framework for lint rules written in Go.

superlint superlint is an experimental, language-agnostic framework for lint rules written in Go. superlint is designed to be a superset of all possib

Feb 8, 2022
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Jan 5, 2023
Best simple, lightweight, powerful and really fast Api with Golang (Fiber, REL, Dbmate) PostgreSqL Database and Clean Architecture

GOLANG FIBER API (CLEAN ARCHITECTURE) Best simple, lightweight, powerful and really fast Api with Golang (Fiber, REL, Dbmate) PostgreSqLDatabase using

Sep 2, 2022
⚡ Rux is an simple and fast web framework. support middleware, compatible http.Handler interface. 简单且快速的 Go web 框架,支持中间件,兼容 http.Handler 接口

Rux Simple and fast web framework for build golang HTTP applications. NOTICE: v1.3.x is not fully compatible with v1.2.x version Fast route match, sup

Dec 8, 2022
Simple and lightweight Go web framework inspired by koa
Simple and lightweight Go web framework inspired by koa

VOX A golang web framework for humans, inspired by Koa heavily. Getting started Installation Using the go get power: $ go get -u github.com/aisk/vox B

Dec 14, 2022
A simple blog framework built with GO. Uses HTML files and a JSON dict to give you more control over your content.

Go-Blog A simple template based blog framework. Instructions Built for GO version: 1 See the Documentation or Getting Started pages in the wiki. Notes

Sep 10, 2022