A Go "clone" of the great and famous Requests library

GRequests

A Go "clone" of the great and famous Requests library

Build Status GoDoc Coverage Status Join the chat at https://gitter.im/levigross/grequests

License

GRequests is licensed under the Apache License, Version 2.0. See LICENSE for the full license text

Features

  • Responses can be serialized into JSON and XML
  • Easy file uploads
  • Easy file downloads
  • Support for the following HTTP verbs GET, HEAD, POST, PUT, DELETE, PATCH, OPTIONS

Install

go get -u github.com/levigross/grequests

Usage

import "github.com/levigross/grequests"

Basic Examples

Basic GET request:

resp, err := grequests.Get("http://httpbin.org/get", nil)
// You can modify the request by passing an optional RequestOptions struct

if err != nil {
	log.Fatalln("Unable to make request: ", err)
}

fmt.Println(resp.String())
// {
//   "args": {},
//   "headers": {
//     "Accept": "*/*",
//     "Host": "httpbin.org",

If an error occurs all of the other properties and methods of a Response will be nil

Quirks

Request Quirks

When passing parameters to be added to a URL, if the URL has existing parameters that contradict with what has been passed within ParamsParams will be the "source of authority" and overwrite the contradicting URL parameter.

Lets see how it works...

ro := &RequestOptions{
	Params: map[string]string{"Hello": "Goodbye"},
}
Get("http://httpbin.org/get?Hello=World", ro)
// The URL is now http://httpbin.org/get?Hello=Goodbye

Response Quirks

Order matters! This is because grequests.Response is implemented as an io.ReadCloser which proxies the http.Response.Body io.ReadCloser interface. It also includes an internal buffer for use in Response.String() and Response.Bytes().

Here are a list of methods that consume the http.Response.Body io.ReadCloser interface.

  • Response.JSON
  • Response.XML
  • Response.DownloadToFile
  • Response.Close
  • Response.Read

The following methods make use of an internal byte buffer

  • Response.String
  • Response.Bytes

In the code below, once the file is downloaded – the Response struct no longer has access to the request bytes

response := Get("http://some-wonderful-file.txt", nil)

if err := response.DownloadToFile("randomFile"); err != nil {
	log.Println("Unable to download file: ", err)
}

// At this point the .String and .Bytes method will return empty responses

response.Bytes() == nil // true
response.String() == "" // true

But if we were to call response.Bytes() or response.String() first, every operation will succeed until the internal buffer is cleared:

response := Get("http://some-wonderful-file.txt", nil)

// This call to .Bytes caches the request bytes in an internal byte buffer – which can be used again and again until it is cleared
response.Bytes() == `file-bytes`
response.String() == "file-string"

// This will work because it will use the internal byte buffer
if err := resp.DownloadToFile("randomFile"); err != nil {
	log.Println("Unable to download file: ", err)
}

// Now if we clear the internal buffer....
response.ClearInternalBuffer()

// At this point the .String and .Bytes method will return empty responses

response.Bytes() == nil // true
response.String() == "" // true
Comments
  • Large response getting cut off.

    Large response getting cut off.

    simple_server.zip Reading the response of a GET request using .String() arbitrarily cuts off the full response when the response is quite large (+5MB). The issue appears to occur when reading the internal buffer from the response object; the full response string is not returned.

    Using http.Get() works fine:

    Attached is a standalone project that reproduces the issue. The attached project has a simple server that returns a hard coded json string:

    src/simple_server

    There are also two clients:

    src/grequests_client (reproduces the issue) src/http_client (works fine)

    The error occurs in grequests_client when trying to decode the json response: 'use of closed network connection'. But inspecting the json response using resp.String() or resp.Byte() shows that only part of the json response is returned.

  • fix json body extra newline

    fix json body extra newline

    POST json body now use json.Encoder#Encode()

    This will result a trailing newline. It's mostly for json stream. Not useful in HTTP and will cause some problem.

    Should use json.Marshal() instead.

  • `too many open files` error

    `too many open files` error

    resp, err := grequests.Post(url, options)
    if err != nil || resp.StatusCode != 200 {
        ...
        return
    }
    

    above is my code, and after about 2 weeks, I could get an error as socket: too many open files. I don't know whether it due to the response unclosed. resp only used to get StatusCode, no resp.JSON or any other usages.
    Should i must close the connection? like defer resp.Close(). Or what should I do to avoid this socket error?

  • how to set proxy after session created?

    how to set proxy after session created?

    session := grequests.NewSession(nil)        // session.HTTPClient.Transport initialized
    session.RequestOptions.Proxies = proxie  // here will not rebuild HTTPClient.Transport, so proxy does not work
    
  • UserAgent and other headers ignored after first redirect

    UserAgent and other headers ignored after first redirect

    Look like problem in doFollowingRedirects()

    ...
            if redirect != 0 {
                nreq := new(Request)
                nreq.Method = ireq.Method
                if ireq.Method == "POST" || ireq.Method == "PUT" {
                    nreq.Method = "GET"
                }
                nreq.Header = make(Header)
                nreq.URL, err = base.Parse(urlStr)
                if err != nil {
                    break
                }
                if len(via) > 0 {
                    // Add the Referer header.
                    lastReq := via[len(via)-1]
                    if ref := refererForURL(lastReq.URL, nreq.URL); ref != "" {
                        nreq.Header.Set("Referer", ref)
                    }
    ...
    

    There is only Referer header is set.

  • error handling

    error handling

    Is there a reason why this library doesn't provide the "go way" of error handling ?

    resp := grequests.Get("http://httpbin.org/xml", nil)
    
    if resp.Error != nil {
        log.Fatalln("Unable to make request", resp.Error)
    }
    

    VS

    resp, err := grequests.Get("http://httpbin.org/xml", nil)
    
    if err != nil {
        log.Fatalln("Unable to make request", err)
    }
    
  • http proxy setting does not work when try to access websites with https

    http proxy setting does not work when try to access websites with https

            proxyURL, err := url.Parse("http://127.0.0.1:8080") // Proxy URL
    	if err != nil {
    		log.Panicln(err)
    	}
    
    	resp, err := grequests.Get("http://www.google.com",
    		&grequests.RequestOptions{Proxies: map[string]*url.URL{proxyURL.Scheme: proxyURL}})
    
    	if err != nil {
    		log.Println(err)
    	}
    
    	if resp.Ok != true {
    		log.Println("Request did not return OK")
    	}
    
    	log.Println(resp)
    

    The code above will work as expected.

    But, if you replace http://www.google.com to https://www.google.com, it will not work, it access google directly without the proxy you set!

  • Grequests should not replace empty UserAgent with it's own

    Grequests should not replace empty UserAgent with it's own

    As much as I like Grequests and I truly want more people to find about it, forcing default User-Agent is not the way.

    https://github.com/levigross/grequests/blob/fd07961896a93d37e169271bb23ee423c42033d3/request.go#L558

    Many platform will change behavior based on the User-Agent. Some of their WAF (web application firewall) will try to single out requests originating from the same IP, User-Agent, etc. There are situation where an empty User-Agent needs to be sent, literally User-Agent: and Grequests is preventing that from happening.

    So I would suggest two solutions.

    1. Create custom struct that can be set to empty, e.g.
    // NullString represents a string that may be null.
    type NullString struct {
    	String string
    	Valid  bool // Valid is true if String is not NULL
    }
    

    and if Valid is true then use the String provided in the struct.

    1. Remove the check.
  • Make doRegularRequest public

    Make doRegularRequest public

    Requests allows you to create requests using the request function, instead of having to call the wrapper for the http method. I am trying to achieve the same functionality in grequests, but doRegularRequest is private.

  • proxy doesn't work as parameter in session request

    proxy doesn't work as parameter in session request

    working well as follow:

    var ourl = "http://baidu.com"
    prox,_ := url.Parse("http://219.135.164.245:3128")
    fmt.Println("prox:", prox)
    
    session := grequests.NewSession(&grequests.RequestOptions{
    	Proxies:map[string]*url.URL{prox.Scheme:prox},
    })
    rsp,err := session.Get(ourl, nil)
    
    fmt.Println(err, rsp.String())
    

    not working as follow:

    var ourl = "http://baidu.com"
    prox,_ := url.Parse("http://219.135.164.245:3128")
    fmt.Println("prox:", prox)
    
    session := grequests.NewSession(nil)
    rsp,err := session.Get(ourl, &grequests.RequestOptions{
    	Proxies:map[string]*url.URL{prox.Scheme:prox},
    })
    
    fmt.Println(err, rsp.String())
    
  • feature(custom-timeouts): user can configure Transport / Dial timeouts

    feature(custom-timeouts): user can configure Transport / Dial timeouts

    Since we can configure the timeouts, I think we don't need the http.DefaultClient anymore. I'd like to know what you think about that @levigross.

    BTW, now all tests are passing :)

  • Add SECURITY.md

    Add SECURITY.md

    Hey there!

    I belong to an open source security research community, and a member (@ranjit-git) has found an issue, but doesn’t know the best way to disclose it.

    If not a hassle, might you kindly add a SECURITY.md file with an email, or another contact method? GitHub recommends this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.

    Thank you for your consideration, and I look forward to hearing from you!

    (cc @huntr-helper)

  • proxy not working on adding to session at the time of request

    proxy not working on adding to session at the time of request

    Hi, So basically if Proxies are added at the time of creating Session it works but on sending request Like Get or Post it doesn't work

    Using Proxy while creating Request in Session

    proxyURL, _ := url.Parse("http://127.0.0.1:8080")
    session := grequests.NewSession(nil)
    
    res , _ := session.Get("https://api.ipify.org?format=json",&grequests.RequestOptions{
            Proxies: map[string]*url.URL{
    		"http": proxyURL,
    		"https": proxyURL,
    	},
    })
    fmt.Println(res.String())
    

    This above request gives my own IP

    Using Proxy while Creating Session

    proxyURL, _ := url.Parse("http://127.0.0.1:8080")
    session := grequests.NewSession(&grequests.RequestOptions{
    	Proxies: map[string]*url.URL{
    		"http": proxyURL,
    		"https": proxyURL,
    	},
    })
    res , _ := session.Get("https://api.ipify.org?format=json",nil)
    fmt.Println(res.String())
    

    This Above Request works

  • Export Response struct

    Export Response struct

    grequests is a great http client library. I like to use it to replace golang default http client. But in some case, I want to build Response from http.Response. I could not to find any way to do this. So, it is any way to export buildResponse function or create new function call BuildResponse?

  • Don't set a default filename when sending multipart form

    Don't set a default filename when sending multipart form

    Currently grequests always sets a filename when creating a multipart post request https://github.com/levigross/grequests/blob/master/request.go#L312 . This leads to inconsistent behaviors with python's requests.

    More specifically, lots of web servers (e.g., go's net/http, python's flask) rely on the existence of 'filename' when parsing a multipart form. If 'filename' exists, the field will be parsed as a file (and put in Request.FormFile, for example); otherwise it will be parsed as a normal value (and put in Request.FormValue, for example).

    As grequests always sets a filename, all fields will be parsed as files, while python's requests allows providing non-file fields using syntax like requests.post(xxx, files={'key': (None, json.dumps("{}"), "application/json")}).

httpreq is an http request library written with Golang to make requests and handle responses easily.

httpreq is an http request library written with Golang to make requests and handle responses easily. Install go get github.com/binalyze/http

Feb 10, 2022
This is a simple single-host reverse proxy that intercept and save HTTP requests and responses
This is a simple single-host reverse proxy that intercept and save HTTP requests and responses

HTTP Telescope Debug HTTP requests using a reverse proxy. Description This is a simple single-host reverse proxy that intercept and save HTTP requests

Mar 20, 2022
Replacement of ApacheBench(ab), support for transactional requests, support for command line and package references to HTTP stress testing tool.

stress stress is an HTTP stress testing tool. Through this tool, you can do a stress test on the HTTP service and get detailed test results. It is ins

Aug 23, 2022
A golang tool which makes http requests and prints the address of the request along with the MD5 hash of the response.

Golang Tool This repository is a golang tool which makes http requests to the external server and prints the address of the request along with the MD5

Oct 17, 2021
Gourl: Performs (multiple) HTTP requests and gathers stats

Gourl: Performs (multiple) HTTP requests and gathers stats

Mar 9, 2022
Nap is a file-based framework for automating the execution of config-driven HTTP requests and scripts.

Nap Nap is a file-based framework for automating the execution of config-driven HTTP requests and scripts. Installation Options Using go get $ go inst

Nov 17, 2022
go http api to handle phishing resources requests

go http api to handle phishing resources requests (auth check, prometheus metrics, pushing to rabbit, logging to elasticsearch)

Oct 8, 2021
This project aims for printing HTTP requests from outside simply

HTTP Debug Server This project aims for printing HTTP requests from outside simp

Jan 29, 2022
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Jan 1, 2023
Parcel - HTTP rendering and binding library for Go

parcel HTTP rendering/binding library for Go Getting Started Add to your project

Jan 1, 2022
Httpx - a fast and multi-purpose HTTP toolkit allow to run multiple probers using retryablehttp library
Httpx - a fast and multi-purpose HTTP toolkit allow to run multiple probers using retryablehttp library

httpx is a fast and multi-purpose HTTP toolkit allow to run multiple probers using retryablehttp library, it is designed to maintain the result reliability with increased threads.

Feb 3, 2022
An HTTP proxy library for Go

Introduction Package goproxy provides a customizable HTTP proxy library for Go (golang), It supports regular HTTP proxy, HTTPS through CONNECT, and "h

Jan 4, 2023
tiny Go library to normalize URLs

Purell Purell is a tiny Go library to normalize URLs. It returns a pure URL. Pure-ell. Sanitizer and all. Yeah, I know... Based on the wikipedia paper

Dec 7, 2022
Go library that makes it easy to add automatic retries to your projects, including support for context.Context.

go-retry Go library that makes it easy to add automatic retries to your projects, including support for context.Context. Example with context.Context

Aug 15, 2022
Cake is a lightweight HTTP client library for GO, inspired by Java Open-Feign.

Cake is a lightweight HTTP client library for GO, inspired by Java Open-Feign. Installation # With Go Modules, recommanded with go version > 1.16

Oct 6, 2022
Goget will send a http request, and show the request time, status, response, and save response to a file

Goget will send a http request, and show the request time, status, response, and save response to a file

Feb 9, 2022
Go (golang) http calls with retries and backoff

pester pester wraps Go's standard lib http client to provide several options to increase resiliency in your request. If you experience poor network co

Dec 28, 2022
HTTP Load Testing And Benchmarking Tool

GBench HTTP Load Testing And Benchmarking Tool inspired by Apache Benchmark and Siege. Requirements You need Golang installed and ready on your system

Jan 2, 2020
HTTP/HTTPS load testing and benchmarking tool

Introduction I wrote that code because: (the obvious reason::I love to write code in Go) We are working so hard to optimize our servers - why shouldn'

Dec 5, 2022