Code Monkey home page Code Monkey logo

gorequest's Introduction

GoRequest

GoRequest -- Simplified HTTP client ( inspired by famous SuperAgent lib in Node.js )

GopherGoRequest

"Shooting Requests like a Machine Gun" - Gopher

Sending request has never been as fun nor easier than this. It comes with lots of features:

  • Get/Post/Put/Head/Delete/Patch/Options
  • Set - simple header setting
  • JSON - made it simple with JSON string as a parameter
  • Multipart-Support - send data and files as multipart request
  • Proxy - sending request via proxy
  • Timeout - setting timeout for a request
  • TLSClientConfig - taking control over tls where at least you can disable security check for https
  • RedirectPolicy
  • Cookie - setting cookies for your request
  • CookieJar - automatic in-memory cookiejar
  • BasicAuth - setting basic authentication header
  • more to come..

Installation

$ go get github.com/parnurzeal/gorequest

Documentation

See Go Doc or Go Walker for usage and details.

Status

Drone Build Status Travis Build Status

Why should you use GoRequest?

GoRequest makes thing much more simple for you, making http client more awesome and fun like SuperAgent + golang style usage.

This is what you normally do for a simple GET without GoRequest:

resp, err := http.Get("http://example.com/")

With GoRequest:

request := gorequest.New()
resp, body, errs := request.Get("http://example.com/").End()

Or below if you don't want to reuse it for other requests.

resp, body, errs := gorequest.New().Get("http://example.com/").End()

How about getting control over HTTP client headers, redirect policy, and etc. Things can quickly get more complicated in golang. You need to create a Client, set headers in a different command, ... just to do only one GET

client := &http.Client{
  CheckRedirect: redirectPolicyFunc,
}

req, err := http.NewRequest("GET", "http://example.com", nil)

req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)

Why make things ugly while you can just do it as follows:

request := gorequest.New()
resp, body, errs := request.Get("http://example.com").
  RedirectPolicy(redirectPolicyFunc).
  Set("If-None-Match", `W/"wyzzy"`).
  End()

DELETE, HEAD, POST, PUT, PATCH are now supported and can be used in the same way as GET:

request := gorequest.New()
resp, body, errs := request.Post("http://example.com").End()
// PUT -> request.Put("http://example.com").End()
// DELETE -> request.Delete("http://example.com").End()
// HEAD -> request.Head("http://example.com").End()
// ANYTHING -> request.CustomMethod("TRACE", "http://example.com").End()

JSON

For a JSON POST with standard libraries, you might need to marshal map data structure to json format, set headers to 'application/json' (and other headers if you need to) and declare http.Client. So, your code becomes longer and harder to maintain:

m := map[string]interface{}{
  "name": "backy",
  "species": "dog",
}
mJson, _ := json.Marshal(m)
contentReader := bytes.NewReader(mJson)
req, _ := http.NewRequest("POST", "http://example.com", contentReader)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Notes","GoRequest is coming!")
client := &http.Client{}
resp, _ := client.Do(req)

Compared to our GoRequest version, JSON is for sure a default. So, it turns out to be just one simple line!:

request := gorequest.New()
resp, body, errs := request.Post("http://example.com").
  Set("Notes","gorequst is coming!").
  Send(`{"name":"backy", "species":"dog"}`).
  End()

Moreover, it also supports struct type. So, you can have a fun Mix & Match sending the different data types for your request:

type BrowserVersionSupport struct {
  Chrome string
  Firefox string
}
ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" }
request := gorequest.New()
resp, body, errs := request.Post("http://version.com/update").
  Send(ver).
  Send(`{"Safari":"5.1.10"}`).
  End()

Not only for Send() but Query() is also supported. Just give it a try! :)

Callback

Moreover, GoRequest also supports callback function. This gives you much more flexibility on using it. You can use it any way to match your own style! Let's see a bit of callback example:

func printStatus(resp gorequest.Response, body string, errs []error){
  fmt.Println(resp.Status)
}
gorequest.New().Get("http://example.com").End(printStatus)

Multipart/Form-Data

You can specify the content-type of the request to type multipart to send all data as multipart/form-data. This feature also allows you to send (multiple) files! Check the examples below!

gorequest.New().Post("http://example.com/").
  Type("multipart").
  Send(`{"query1":"test"}`).
  End()

The SendFile function accepts strings as path to a file, []byte slice or even a os.File! You can also combine them to send multiple files with either custom name and/or custom fieldname:

          f, _ := filepath.Abs("./file2.txt")
bytesOfFile, _ := ioutil.ReadFile(f)

gorequest.New().Post("http://example.com/").
  Type("multipart").
  SendFile("./file1.txt").
  SendFile(bytesOfFile, "file2.txt", "my_file_fieldname").
  End()

Check the docs for SendFile to get more information about the types of arguments.

Headers

When setting one header to the request, the Set method can be used:

gorequest.New().
      Post("/gamelist").
      Set("Accept", "application/json").
      End()

This will clear all headers currently attached to a request and add the specified header.

If there are multiple headers that must be appended to the request before sending, use AppendHeader. These can be chained together to add additional headers to the request:

gorequest.New().
      Post("/gamelist").
      AppendHeader("Accept", "application/json").
      AppendHeader("Accept", "text/plain").
      End()

See the docs for the Set and AppendHeader methods for information about parameter and return types.

Proxy

In the case when you are behind proxy, GoRequest can handle it easily with Proxy func:

request := gorequest.New().Proxy("http://proxy:999")
resp, body, errs := request.Get("http://example-proxy.com").End()
// To reuse same client with no_proxy, use empty string:
resp, body, errs = request.Proxy("").Get("http://example-no-proxy.com").End()

Basic Authentication

To add a basic authentication header:

request := gorequest.New().SetBasicAuth("username", "password")
resp, body, errs := request.Get("http://example-proxy.com").End()

Timeout

Timeout can be set in any time duration using time package:

request := gorequest.New().Timeout(2*time.Millisecond)
resp, body, errs:= request.Get("http://example.com").End()

Timeout func defines both dial + read/write timeout to the specified time parameter.

EndBytes

Thanks to @jaytaylor, we now have EndBytes to use when you want the body as bytes.

The callbacks work the same way as with End, except that a byte array is used instead of a string.

resp, bodyBytes, errs := gorequest.New().Get("http://example.com/").EndBytes()

EndStruct

We now have EndStruct to use when you want the body as struct.

The callbacks work the same way as with End, except that a struct is used instead of a string.

Supposing the URL http://example.com/ returns the body {"hey":"you"}

heyYou struct {
  Hey string `json:"hey"`
}

var heyYou heyYou

resp, _, errs := gorequest.New().Get("http://example.com/").EndStruct(&heyYou)

Retry

Supposing you need retry 3 times, with 5 seconds between each attempt when gets a BadRequest or a InternalServerError

request := gorequest.New()
resp, body, errs := request.Get("http://example.com/").
                    Retry(3, 5 * time.Second, http.StatusBadRequest, http.StatusInternalServerError).
                    End()

Handling Redirects

Redirects can be handled with RedirectPolicy which behaves similarly to net/http Client's CheckRedirect function. Simply specify a function which takes the Request about to be made and a slice of previous Requests in order of oldest first. When this function returns an error, the Request is not made.

For example to redirect only to https endpoints:

request := gorequest.New()
resp, body, errs := request.Get("http://example.com/").
                    RedirectPolicy(func(req Request, via []*Request) error {
                      if req.URL.Scheme != "https" {
                        return http.ErrUseLastResponse
                      }
                    }).
                    End()

Clone

You can reuse settings of a Request by cloning it before making any requests. This can be useful if you wish to re-use the SuperAgent across multiple requests without worrying about concurrency or having too many Transports being created.

Clones will copy the same settings (headers, query, etc..), but will only shallow copy any "Data" given to it. They will also share the same Transport and http.Client.

baseRequest := gorequest.New()
// apply anything you want to these settings. Eg:
baseRequest.Timeout(10 * time.Millisecond).
  BasicAuth("user", "password")

// then reuse the base request elsewhere, cloning before modifying or using it.
resp, body, errs := baseRequest.Clone().Get("http://exmaple.com/").End()

Debug

For debugging, GoRequest leverages httputil to dump details of every request/response. (Thanks to @dafang)

You can just use SetDebug or environment variable GOREQUEST_DEBUG=0|1 to enable/disable debug mode and SetLogger to set your own choice of logger.

Thanks to @QuentinPerez, we can see even how gorequest is compared to CURL by using SetCurlCommand.

Noted

As the underlying gorequest is based on http.Client in most use cases, gorequest.New() should be called once and reuse gorequest as much as possible.

Contributing to GoRequest:

If you find any improvement or issue you want to fix, feel free to send me a pull request with testing.

Thanks to all contributors thus far:

Contributors
https://github.com/alaingilbert
https://github.com/austinov
https://github.com/coderhaoxin
https://github.com/codegoalie
https://github.com/dafang
https://github.com/davyzhang
https://github.com/dickeyxxx
https://github.com/figlief
https://github.com/fraenky8
https://github.com/franciscocpg
https://github.com/heytitle
https://github.com/hownowstephen
https://github.com/kemadz
https://github.com/killix
https://github.com/jaytaylor
https://github.com/na-ga
https://github.com/piotrmiskiewicz
https://github.com/pencil001
https://github.com/pkopac
https://github.com/quangbuule
https://github.com/QuentinPerez
https://github.com/smallnest
https://github.com/WaveCutz
https://github.com/xild
https://github.com/yangmls
https://github.com/6david9

Also, co-maintainer is needed here. If anyone is interested, please email me (parnurzeal at gmail.com)

Credits

  • Renee French - the creator of Gopher mascot
  • Wisi Mongkhonsrisawat for providing an awesome GoRequest's Gopher image :)

License

GoRequest is MIT License.

gorequest's People

Contributors

asjdf avatar callensm avatar caojia avatar dafang avatar duguying avatar edentsai avatar ericyt avatar fraenky8 avatar franciscocpg avatar harsimranmaan avatar hownowstephen avatar iamwavecut avatar incisive avatar jaytaylor avatar kemadz avatar killix avatar macharmi avatar moul avatar na-ga avatar nightlyone avatar p16i avatar parnurzeal avatar pencil001 avatar piotrmiskiewicz avatar pkopac avatar quangbuule avatar quentinperez avatar roylou avatar smallnest avatar stefanoschrs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gorequest's Issues

unexpected panic

goroutine 598 [IO wait]:                                                                                                                                                              [46/1484]
net.runtime_pollWait(0x7ff76c32ab08, 0x77, 0x44fce0)
        /usr/local/go/src/runtime/netpoll.go:157 +0x60
net.(*pollDesc).Wait(0xc8205cc760, 0x77, 0x0, 0x0)
        /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitWrite(0xc8205cc760, 0x0, 0x0)
        /usr/local/go/src/net/fd_poll_runtime.go:82 +0x36
net.(*netFD).connect(0xc8205cc700, 0x0, 0x0, 0x7ff769cd20d8, 0xc82029a460, 0xecdf654be, 0x2514b38e, 0xa93e80, 0x0, 0x0)
        /usr/local/go/src/net/fd_unix.go:114 +0x1f6
net.(*netFD).dial(0xc8205cc700, 0x7ff769c920e8, 0x0, 0x7ff769c920e8, 0xc82027c300, 0xecdf654be, 0x2514b38e, 0xa93e80, 0x0, 0x0)
        /usr/local/go/src/net/sock_posix.go:137 +0x351
net.socket(0x861978, 0x3, 0x2, 0x1, 0x0, 0xc82027c300, 0x7ff769c920e8, 0x0, 0x7ff769c920e8, 0xc82027c300, ...)
        /usr/local/go/src/net/sock_posix.go:89 +0x411
net.internetSocket(0x861978, 0x3, 0x7ff769c920e8, 0x0, 0x7ff769c920e8, 0xc82027c300, 0xecdf654be, 0xc82514b38e, 0xa93e80, 0x1, ...)
        /usr/local/go/src/net/ipsock_posix.go:160 +0x141
net.dialTCP(0x861978, 0x3, 0x0, 0xc82027c300, 0xecdf654be, 0xc82514b38e, 0xa93e80, 0xc82042e590, 0x0, 0x0)
        /usr/local/go/src/net/tcpsock_posix.go:171 +0x11e
net.dialSingle(0xc8200b0380, 0x7ff769c92058, 0xc82027c300, 0xecdf654be, 0x2514b38e, 0xa93e80, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/dial.go:364 +0x3f5
net.dialSerial.func1(0xecdf654be, 0x2514b38e, 0xa93e80, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/dial.go:336 +0x75
net.dial(0x861978, 0x3, 0x7ff769c92058, 0xc82027c300, 0xc8203035e0, 0xecdf654be, 0x2514b38e, 0xa93e80, 0x0, 0x0, ...)
        /usr/local/go/src/net/fd_unix.go:40 +0x60
net.dialSerial(0xc8200b0380, 0xc82042e590, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/dial.go:338 +0x760
net.(*Dialer).Dial(0xc820303858, 0x861978, 0x3, 0xc82029a327, 0x13, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/dial.go:232 +0x50f
net.DialTimeout(0x861978, 0x3, 0xc82029a327, 0x13, 0x2540be400, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/dial.go:193 +0xa2
github.com/parnurzeal/gorequest.(*SuperAgent).Timeout.func1(0x861978, 0x3, 0xc82029a327, 0x13, 0x0, 0x0, 0x0, 0x0)
        /root/workspace/golang/src/github.com/parnurzeal/gorequest/main.go:337 +0x92
net/http.(*Transport).dial(0xc8202ac5a0, 0x861978, 0x3, 0xc82029a327, 0x13, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/http/transport.go:499 +0x79
net/http.(*Transport).dialConn(0xc8202ac5a0, 0xc8200b0280, 0xc82029a360, 0x4, 0xc82042e540, 0xd, 0xc8203e56e0, 0x0, 0x0)
        /usr/local/go/src/net/http/transport.go:596 +0x19a9
net/http.(*Transport).getConn.func4(0xc8202ac5a0, 0xc8200b0280, 0xc82029a360, 0x4, 0xc82042e540, 0xd, 0xc820478480)
        /usr/local/go/src/net/http/transport.go:549 +0x66
created by net/http.(*Transport).getConn
        /usr/local/go/src/net/http/transport.go:551 +0x265

this panic is appeared after some request successfully done

Support fasthttp as an alternative to net/http

Fasthttp client has the following advantages comparing to net/http client:

  • It is faster.
  • Its' API allows both request and response objects' recycling., thus reducing memory allocations => improving performance.
  • It limits the number of concurrent connections per host.
  • It automatically closes idle connections.
  • It supports per-request timeouts.

Text/plain

I can't use text/plain with this library. It URL encodes what I send.

Query with struct, omit null fields

Hello,

First of all really nice feature to set struct to Query() method. Current implementation gets all struct fields and convert them to query parameters, will be nice to omit null fields.

Currently it panics when field has null (field definition: something *string)

func (s *SuperAgent) queryStruct(content interface{}) *SuperAgent {
    if marshalContent, err := json.Marshal(content); err != nil {
        s.Errors = append(s.Errors, err)
    } else {
        var val map[string]interface{}
        if err := json.Unmarshal(marshalContent, &val); err != nil {
            s.Errors = append(s.Errors, err)
        } else {
            for k, v := range val {
                k = strings.ToLower(k)
                s.QueryData.Add(k, v.(string))
            }
        }
    }
    return s
}

line: 310 s.QueryData.Add(k, v.(string))

Cheers, Piotr

Question mark eaten from URL if no query parameters specified

  1. What version of Go are you using (go version)?

    go version go1.5.1 windows/amd64
    
  2. What operating system and processor architecture are you using?

    Windows 8.1 Pro (64-bit)

  3. What did you do?

    There is an (internal) API for which these two URLs identifie two different resources:
    A. http://server.com/api/item.json
    B. http://server.com/api/item.json?

    The second URL is indeed with question mark, but without query parameters.

    I make HTTP GET request using the resource B:

    _, body, _ := gorequest.New().Get("http://server.com/api/item.json?").End()
    fmt.Println(body)
    
  4. What did you expect to see?

    I expect to receive representation of the resource B.

  5. What did you see instead?

    I received representation of the resource A.

    So, net/http somewhat eats-or-skips the question mark if there are no query parameters.

    BTW, I'm seeing the same behaviour while using https://github.com/parnurzeal/gorequest package.


BTW, I have filed very similar reports to

I have also tested the requests using number of HTTP packages for different programming languages, here https://github.com/mloskot/http-url-test.
To summary, 4 of 14 packages eat-or-skip the trailing question mark, namely:

  • Go
    • net/http
    • gorequest
  • Python Requests
  • Node.js shred

panic: runtime error: invalid memory address or nil pointer dereference

If i set the Header-Field

httpClient = gorequest.New()
httpClient.Post(...)
....
httpClient.Set("Content-Type", "application/x-www-form-urlencoded")

i get an runtime error because of nil-pointer Reference in makeRequest Line 786 because of the last empty else-branch with the TODO Statement (Line 774). So the Request-Variable is not set in Line 786. Guess determining the TargetType is faulty.

Furthermore i make a Post-Request with calling the Method Send("param1=abc&param2=cde") and therefore if i omit the "faulty" Header above, it works, because the TargetType is determined correctly to form.

For completeness the full error:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x38 pc=0x5b6c8d]

goroutine 1 [running]:
panic(0x7aa740, 0xc0820020a0)
    D:/go/src/runtime/panic.go:464 +0x3f4
github.com/parnurzeal/gorequest.(*SuperAgent).MakeRequest(0xc08209c600, 0x21, 0x0, 0x0)
    D:/Eigene Dateien/Coding/go/src/github.com/parnurzeal/gorequest/main.go:786 +0x51d
github.com/parnurzeal/gorequest.(*SuperAgent).EndBytes(0xc08209c600, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    D:/Eigene Dateien/Coding/go/src/github.com/parnurzeal/gorequest/main.go:665 +0x25e
github.com/parnurzeal/gorequest.(*SuperAgent).End(0xc08209c600, 0x0, 0x0, 0x0, 0x7bf980, 0x0, 0x0, 0x0, 0x0, 0x0)
    D:/Eigene Dateien/Coding/go/src/github.com/parnurzeal/gorequest/main.go:629 +0x15e
my/path/to/my/projects/apackage.(*api).LoginIAApiEndpoint(0xc08204cf60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    D:/Eigene Dateien/Coding/go/src/y/path/to/my/projects/apackage/api.go:70 +0x2e3
main.main()
    my/path/to/my/projects/apackage/main.go:14 +0x3b
exit status 2

SuperAgent can not be reused when I have many gorouting

I want to reuse gorequest.SuperAgent in my program, so I new a req, then I always reuse this.This does work at most time,

But when I have multiple goroutine in linux, this just got nil pointer dereference error.Anyway, if I new a SuperAgent, this is not a problem.And also, something strange is that I just run everything well in my Mac, but not ok in linux.

I upload my source code in a txt file.
test_http.txt

Here is the stack trace:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x45c974]

goroutine 932 [running]:
github.com/parnurzeal/gorequest.(*SuperAgent).Timeout.func1(0x747008, 0x3, 0x78a687, 0x11, 0x0, 0x0, 0x0, 0x0)
    /home/roger/golang/src/github.com/parnurzeal/gorequest/main.go:374 +0x18b
net/http.(*Transport).dial(0xc8200181b0, 0x747008, 0x3, 0x78a687, 0x11, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/http/transport.go:499 +0x79
net/http.(*Transport).dialConn(0xc8200181b0, 0x0, 0x78a680, 0x4, 0x78a687, 0x11, 0xc8200b0f50, 0x0, 0x0)
    /usr/local/go/src/net/http/transport.go:596 +0x19a9
net/http.(*Transport).getConn.func4(0xc8200181b0, 0x0, 0x78a680, 0x4, 0x78a687, 0x11, 0xc82039daa0)
    /usr/local/go/src/net/http/transport.go:549 +0x66
created by net/http.(*Transport).getConn
    /usr/local/go/src/net/http/transport.go:551 +0x265

goroutine 1 [runnable]:
syscall.Syscall(0x1, 0x1, 0xc820116240, 0x2, 0x2, 0x2, 0x0)
    /usr/local/go/src/syscall/asm_linux_amd64.s:18 +0x5
syscall.write(0x1, 0xc820116240, 0x2, 0x60, 0xc820127d68, 0x0, 0x0)
    /usr/local/go/src/syscall/zsyscall_linux_amd64.go:1064 +0x5f
syscall.Write(0x1, 0xc820116240, 0x2, 0x60, 0x0, 0x0, 0x0)
    /usr/local/go/src/syscall/syscall_unix.go:176 +0x4d
os.(*File).write(0xc82002e010, 0xc820116240, 0x2, 0x60, 0x0, 0x0, 0x0)
    /usr/local/go/src/os/file_unix.go:232 +0xaa
os.(*File).Write(0xc82002e010, 0xc820116240, 0x2, 0x60, 0xc820200101, 0x0, 0x0)
    /usr/local/go/src/os/file.go:139 +0x8a
fmt.Fprintln(0x7f9173307358, 0xc82002e010, 0xc820127f30, 0x1, 0x1, 0x40c760, 0x0, 0x0)
    /usr/local/go/src/fmt/print.go:255 +0xa5
fmt.Println(0xc820127f30, 0x1, 0x1, 0x670a20, 0x0, 0x0)
    /usr/local/go/src/fmt/print.go:264 +0x73
main.main()
    /home/roger/test/test_http.go:67 +0x255

Headers not setting?

Setting headers doesn't work. Searching for 'Header.Set' in the repo, I can't find any occurrences that aren't hard-coded; that is, there doesn't seem to be any code linking the gorequest 'Set' method to the builtin http methods.

The below example, for me, displays the SuperAgent struct as containing the correct headers, but the returned data shows none of these headers, only the set seemingly built-in to Golang's http libs.

package main

import (
    "fmt"
    "github.com/parnurzeal/gorequest"
)

func main() {
    requestor := gorequest.New()
    requestor.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0")
    requestor.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
    fmt.Println(requestor)
    _, body, _ := requestor.Get("https://httpbin.org/headers").End()
    fmt.Println(body)
}

SetBasicAuth not working / not available

Trying to use SetBasicAuth doesn't work. Compiler gives this error: "SetBasicAuth undefined (type *gorequest.SuperAgent has no field or method SetBasicAuth)".

Even a copy and paste of the sample code for SetBasicAuth found in the Go Docs fails. (There's a missing . in the example code, but adding that didn't fix anything.)

All other documented methods and properties are available and work fine.

I have no idea what's causing this.

Leaking memory/sockets due to repeated SuperAgent creation

Recommend you update the documentation to state that the same SuperAgent be used as much as possible due to the behavior of creating a new http.Transport each time. Go's HTTP library recycles sockets by using DefaultTransport, which obviously you're not using.

You could also refactor the code to only create a transport when actually executing the request and when necessary (proxy/timeout operations); otherwise, just use the DefaultTransport.

For future reference... the package's name is quite misleading with the current API. The package should be named as an agent or client rather than request. goagent.New() is more accurate than gorequest.New(). gorequest.NewClient() would be acceptable too, but it's too late for API changes.

Api Method?

There should be a method Api where we can pass the method type and it would automatically call a Get or Post etc..

resp, body, errs := req.Api("GET", "/home")

JSON field reordering

There's a bug in how the JSON is being marshalled, maps are supposedly unordered but this isn't actually true.

So when adding adding json fields to the Data map[string] interface{} member of the SuperAgent struct the map sorts them in alphabetical order. The implication is that the json can't be unmarshaled on the receiving end, if the types members weren't specified in alphabetical order.

Please see https://github.com/parnurzeal/gorequest/blob/master/main.go#L407

My suggestion would be to implement an array of pairs rather than a map[string]interface{}

Decode maps in Query and Body?

It would be better if we could pass in map objects for Query() and Send() also.

Something like this would make it easily readable.

type H map[string]interface{}

request.Query(H{"test": "value"}).Send(H{"test": "value"}).End()

//This is what i do now
params := url.Values{}
for k, v := range query {
  params.Add(k, v.(string))
} 
route + params.Encode()

Concurrent Requests.

How does this library handle concurrency?

Like multiple simultaneous requests?

Is there an example?

Looks like fun.

Thanks.

Disable SSL certificate checks

Hi,

Using the net/http library I can do something like this to disable cert checks:

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

Can this be configured for use with gorequest ?

Thanks.

Proxy w/Authentication support

It is not clear if the library supports a proxy with authentication.

I tried using

resp, body, errs:= request.Proxy("http://myusername:mypassword@proxyurl:proxyport").Get("http://google.com").End()

With no success.

The proxy server is Squid

Is there a way to fetch the response cookies?

I want to move cookies from a response to a request, so I need a way to fetch the response cookies, but it seems that the gorequest response does not expose the cookies method...

Allow for sending both query data and request body.

Refactor the API to support easier request building and allow for query params and post/put data

How about

data := struct{Name string `json:"name"`}{"jkbbwr"}
resp, body, errs := request.Post("http://example.com").
  Set("Notes","gorequst is coming!").
  Query("test", true).
  Send(data).
  End()

Which would result in

POST /?test=true
{"name":"jkbbwr"}

Memory Leak?

code

request := gorequest.New().Timeout(20 * time.Second)

for {
    select {
    case value := <-checkpool:
        if value == "" {
            continue
        }
        proxyinfo := proxy(string(value))
        resp, _, err := request.Proxy(proxyinfo).Head(checkUrl).End()
        if err == nil {
            headers := resp.Header["Server"]
            if headers != nil {
                serverHeader := headers[0]
                if strings.Contains(serverHeader, bws) {
                    cleanpool <- value
                    fmt.Printf("%s %s success\n", name, value)
                }
            }
        } else {
            fmt.Printf("%s %s failed %s\n", name, value, err)
        }
    }
}

I use go request like above,and the memory of progress keep larger,did my code cause a memory leak or it's a bug of gorequest

add HEAD request

You're probably already planning this. But to get the issue tracking going...

Have you thought about adding a HEAD request?

request := gorequest.New()
resp, _, errs := request.Head("http://example.com/").End()

Nice work on the JSON handling in the post requests btw!

Auto decompress body

Hi,

Thank you for this useful package.

Looks like now you simply return body even if it is compressed.
Maybe you can automatically decompress body when you find Content-Encoding: gzip header.

Go net/http is doing that already.

Please implement PATCH command

Many APIs require the use of PATCH to supply application updates. Would you please add the PATCH command to the GET/POST/PUT/DELETE/HEAD family that gorequest supports?

Thank you!

gorequest install problems

i am using ubuntu and muanlly install go in my home dir with GOPATH all set. and got this:
package golang.org/x/net/publicsuffix: unrecognized import path "golang.org/x/net/publicsuffix"

request.Post not correctly using struct fields

I am trying to use request.Post and a struct and it seems the method is not honoring the JSON field mappings. Has anyone seen this or am I doing something wrong?

request := gorequest.New()
resp, _, errs := request.Post("https://example.com/").
    Send(event).
    End()

The struct I am using is below.

type Event struct {
    Name           string   `json:user_name"`
}

The JSON is coming through like the following.

{
    "Name": "Bob"
}

Notice the field name is coming through as Name instead of user_name.

What am I doing wrong here or is this not supported?

Possibility to add Query params in form of struct.

Don'y You mind if i'll implement such thing?
Its pretty obvious to send struct as query params too, due to already existing possibility to do this with POST (sendStruct).
Why I'm asking - i have a structure which represents some parameters for GET request and what am i doing right now its marshalling data and sending them to Query function in form of string. And when Query unmarshalls it again. Its absolutely unnecessary overhead.
Of course i can concatenate this string in cycle - but it would be really shitty way.

So, what would You say?

HTTP Authentication is Broken

For authentication other than HTTP Basic (bearer auth for something like web tokens) this will not work:

https://github.com/parnurzeal/gorequest/blob/master/main.go#L541-L545

And will effectively nuke any manually set Authorization headers. I had to comment out line 544 to get things working again (I am using Bearer Auth). Is deleting the else half of this branch sufficient? If so, I'll happily send over a pull request. Or maybe I should just switch over to goreq ?

File Descriptor leak

I have a code like this:

    func testRequest() {
        gorequest.New().Get("http://www.google.com").End()
    }

    for {
        go testRequest()
        time.Sleep(1 * time.Second)
        fmt.Println("Request done, open files =", countOpenFiles())
    }

The real code is a bit more complicated, but anyways..

It seems to be in line with what docs recommend, but it actually leaks file descriptors:

    for {
        go testRequest()
        time.Sleep(1 * time.Second)
        fmt.Println("Request done, open files =", countOpenFiles())
    }

the output that I get is:

Request done, open files = 15
Request done, open files = 17
Request done, open files = 19
Request done, open files = 21
Request done, open files = 23
Request done, open files = 25
Request done, open files = 27

Ok, let's change it a bit (which is not documented, but ok):

gorequest.New().Get("http://www.google.com").Set("Connection", "close").End()

This time it's better:

Request done, open files = 14 Request done, open files = 15 Request done, open files = 16 Request done, open files = 17 Request done, open files = 18 Request done, open files = 19 Request done, open files = 20

But it still leaks.

  1. Maybe the documentation should be explicit about the need to set .Set("Connection", "close")
  2. How to get rid of second leak? I can't reuse the connection since that's going in different goroutines

The full code is here: https://git.io/vaDBp

wrong type convert in send method

not matter i set a struct or string into send method,inside it auto convert {"DealerId":2004410,"IPAddress":"36.59.237.195"} to {"DealerId":2.00441e+06,"IPAddress":"36.59.237.195"},finally i find the json lib auto convert it( http://stackoverflow.com/questions/22343083/json-marshaling-with-long-numbers-in-golang-gives-floating-point-number ),so everyone have a struct with int should care about this ,haven't find any solution for this, i think in the SendString method should not Unmarshal again

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.