From 9901266769025467b1737a5ccaf09c4a7eb93b6a Mon Sep 17 00:00:00 2001 From: shengxiang Date: Sun, 13 Sep 2015 14:53:25 +0800 Subject: [PATCH] remove useless dep --- Godeps/Godeps.json | 4 - .../src/github.com/franela/goreq/.gitignore | 24 - .../src/github.com/franela/goreq/.travis.yml | 8 - .../src/github.com/franela/goreq/LICENSE | 20 - .../src/github.com/franela/goreq/Makefile | 3 - .../src/github.com/franela/goreq/README.md | 444 ------- .../src/github.com/franela/goreq/goreq.go | 494 ------- .../github.com/franela/goreq/goreq_test.go | 1184 ----------------- .../src/github.com/franela/goreq/tags.go | 64 - 9 files changed, 2245 deletions(-) delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/.gitignore delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/.travis.yml delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/LICENSE delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/Makefile delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/README.md delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/goreq.go delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/goreq_test.go delete mode 100644 Godeps/_workspace/src/github.com/franela/goreq/tags.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 6ab9377..b97ebb6 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -20,10 +20,6 @@ "ImportPath": "github.com/codeskyblue/kproc", "Rev": "fcb55eb35ab6b7290f395ad596e80e8355d52d69" }, - { - "ImportPath": "github.com/franela/goreq", - "Rev": "72c51a544272e007ab3da4f7d9ac959b7af7af03" - }, { "ImportPath": "github.com/golang/protobuf/proto", "Rev": "1dceb1a2654bdc74ca97ad91f71f500eecc96269" diff --git a/Godeps/_workspace/src/github.com/franela/goreq/.gitignore b/Godeps/_workspace/src/github.com/franela/goreq/.gitignore deleted file mode 100644 index 131fc16..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -src diff --git a/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml b/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml deleted file mode 100644 index 629753d..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - 1.2 - - tip -notifications: - email: - - ionathan@gmail.com - - marcosnils@gmail.com diff --git a/Godeps/_workspace/src/github.com/franela/goreq/LICENSE b/Godeps/_workspace/src/github.com/franela/goreq/LICENSE deleted file mode 100644 index 068dee1..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Jonathan Leibiusky and Marcos Lilljedahl - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/franela/goreq/Makefile b/Godeps/_workspace/src/github.com/franela/goreq/Makefile deleted file mode 100644 index 0f04d65..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -test: - go get -v -d -t ./... - go test -v diff --git a/Godeps/_workspace/src/github.com/franela/goreq/README.md b/Godeps/_workspace/src/github.com/franela/goreq/README.md deleted file mode 100644 index b6a0bfd..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/README.md +++ /dev/null @@ -1,444 +0,0 @@ -[![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:). diff --git a/Godeps/_workspace/src/github.com/franela/goreq/goreq.go b/Godeps/_workspace/src/github.com/franela/goreq/goreq.go deleted file mode 100644 index 27a1561..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/goreq.go +++ /dev/null @@ -1,494 +0,0 @@ -package goreq - -import ( - "bufio" - "bytes" - "compress/gzip" - "compress/zlib" - "crypto/tls" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httputil" - "net/url" - "reflect" - "strings" - "time" -) - -type Request struct { - headers []headerTuple - cookies []*http.Cookie - Method string - Uri string - Body interface{} - QueryString interface{} - Timeout time.Duration - ContentType string - Accept string - Host string - UserAgent string - Insecure bool - MaxRedirects int - RedirectHeaders bool - Proxy string - Compression *compression - BasicAuthUsername string - BasicAuthPassword string - CookieJar http.CookieJar - ShowDebug bool - OnBeforeRequest func(goreq *Request, httpreq *http.Request) -} - -type compression struct { - writer func(buffer io.Writer) (io.WriteCloser, error) - reader func(buffer io.Reader) (io.ReadCloser, error) - ContentEncoding string -} - -type Response struct { - *http.Response - Uri string - Body *Body - req *http.Request -} - -func (r Response) CancelRequest() { - cancelRequest(r.req) - -} - -func cancelRequest(r *http.Request) { - if transport, ok := DefaultTransport.(transportRequestCanceler); ok { - transport.CancelRequest(r) - } -} - -type headerTuple struct { - name string - value string -} - -type Body struct { - reader io.ReadCloser - compressedReader io.ReadCloser -} - -type Error struct { - timeout bool - Err error -} - -type transportRequestCanceler interface { - CancelRequest(*http.Request) -} - -func (e *Error) Timeout() bool { - return e.timeout -} - -func (e *Error) Error() string { - return e.Err.Error() -} - -func (b *Body) Read(p []byte) (int, error) { - if b.compressedReader != nil { - return b.compressedReader.Read(p) - } - return b.reader.Read(p) -} - -func (b *Body) Close() error { - err := b.reader.Close() - if b.compressedReader != nil { - return b.compressedReader.Close() - } - return err -} - -func (b *Body) FromJsonTo(o interface{}) error { - return json.NewDecoder(b).Decode(o) -} - -func (b *Body) ToString() (string, error) { - body, err := ioutil.ReadAll(b) - if err != nil { - return "", err - } - return string(body), nil -} - -func Gzip() *compression { - reader := func(buffer io.Reader) (io.ReadCloser, error) { - return gzip.NewReader(buffer) - } - writer := func(buffer io.Writer) (io.WriteCloser, error) { - return gzip.NewWriter(buffer), nil - } - return &compression{writer: writer, reader: reader, ContentEncoding: "gzip"} -} - -func Deflate() *compression { - reader := func(buffer io.Reader) (io.ReadCloser, error) { - return zlib.NewReader(buffer) - } - writer := func(buffer io.Writer) (io.WriteCloser, error) { - return zlib.NewWriter(buffer), nil - } - return &compression{writer: writer, reader: reader, ContentEncoding: "deflate"} -} - -func Zlib() *compression { - return Deflate() -} - -func paramParse(query interface{}) (string, error) { - switch query.(type) { - case url.Values: - return query.(url.Values).Encode(), nil - case *url.Values: - return query.(*url.Values).Encode(), nil - default: - var v = &url.Values{} - err := paramParseStruct(v, query) - return v.Encode(), err - } -} - -func paramParseStruct(v *url.Values, query interface{}) error { - var ( - s = reflect.ValueOf(query) - t = reflect.TypeOf(query) - ) - for t.Kind() == reflect.Ptr || t.Kind() == reflect.Interface { - s = s.Elem() - t = s.Type() - } - if t.Kind() != reflect.Struct { - return errors.New("Can not parse QueryString.") - } - - for i := 0; i < t.NumField(); i++ { - var name string - - field := s.Field(i) - typeField := t.Field(i) - - if !field.CanInterface() { - continue - } - - urlTag := typeField.Tag.Get("url") - if urlTag == "-" { - continue - } - - name, opts := parseTag(urlTag) - - var omitEmpty, squash bool - omitEmpty = opts.Contains("omitempty") - squash = opts.Contains("squash") - - if squash { - err := paramParseStruct(v, field.Interface()) - if err != nil { - return err - } - continue - } - - if urlTag == "" { - name = strings.ToLower(typeField.Name) - } - - if val := fmt.Sprintf("%v", field.Interface()); !(omitEmpty && len(val) == 0) { - v.Add(name, val) - } - } - return nil -} - -func prepareRequestBody(b interface{}) (io.Reader, error) { - switch b.(type) { - case string: - // treat is as text - return strings.NewReader(b.(string)), nil - case io.Reader: - // treat is as text - return b.(io.Reader), nil - case []byte: - //treat as byte array - return bytes.NewReader(b.([]byte)), nil - case nil: - return nil, nil - default: - // try to jsonify it - j, err := json.Marshal(b) - if err == nil { - return bytes.NewReader(j), nil - } - return nil, err - } -} - -var DefaultDialer = &net.Dialer{Timeout: 1000 * time.Millisecond} -var DefaultTransport http.RoundTripper = &http.Transport{Dial: DefaultDialer.Dial, Proxy: http.ProxyFromEnvironment} -var DefaultClient = &http.Client{Transport: DefaultTransport} - -var proxyTransport http.RoundTripper -var proxyClient *http.Client - -func SetConnectTimeout(duration time.Duration) { - DefaultDialer.Timeout = duration -} - -func (r *Request) AddHeader(name string, value string) { - if r.headers == nil { - r.headers = []headerTuple{} - } - r.headers = append(r.headers, headerTuple{name: name, value: value}) -} - -func (r Request) WithHeader(name string, value string) Request { - r.AddHeader(name, value) - return r -} - -func (r *Request) AddCookie(c *http.Cookie) { - r.cookies = append(r.cookies, c) -} - -func (r Request) WithCookie(c *http.Cookie) Request { - r.AddCookie(c) - return r - -} - -func (r Request) Do() (*Response, error) { - var client = DefaultClient - var transport = DefaultTransport - var resUri string - var redirectFailed bool - - r.Method = valueOrDefault(r.Method, "GET") - - // use a client with a cookie jar if necessary. We create a new client not - // to modify the default one. - if r.CookieJar != nil { - client = &http.Client{ - Transport: transport, - Jar: r.CookieJar, - } - } - - if r.Proxy != "" { - proxyUrl, err := url.Parse(r.Proxy) - if err != nil { - // proxy address is in a wrong format - return nil, &Error{Err: err} - } - - //If jar is specified new client needs to be built - if proxyTransport == nil || client.Jar != nil { - proxyTransport = &http.Transport{Dial: DefaultDialer.Dial, Proxy: http.ProxyURL(proxyUrl)} - proxyClient = &http.Client{Transport: proxyTransport, Jar: client.Jar} - } else if proxyTransport, ok := proxyTransport.(*http.Transport); ok { - proxyTransport.Proxy = http.ProxyURL(proxyUrl) - } - transport = proxyTransport - client = proxyClient - } - - client.CheckRedirect = func(req *http.Request, via []*http.Request) error { - - if len(via) > r.MaxRedirects { - redirectFailed = true - return errors.New("Error redirecting. MaxRedirects reached") - } - - resUri = req.URL.String() - - //By default Golang will not redirect request headers - // https://code.google.com/p/go/issues/detail?id=4800&q=request%20header - if r.RedirectHeaders { - for key, val := range via[0].Header { - req.Header[key] = val - } - } - return nil - } - - if transport, ok := transport.(*http.Transport); ok { - if r.Insecure { - if transport.TLSClientConfig != nil { - transport.TLSClientConfig.InsecureSkipVerify = true - } else { - transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - } else if transport.TLSClientConfig != nil { - // the default TLS client (when transport.TLSClientConfig==nil) is - // already set to verify, so do nothing in that case - transport.TLSClientConfig.InsecureSkipVerify = false - } - } - - req, err := r.NewRequest() - - if err != nil { - // we couldn't parse the URL. - return nil, &Error{Err: err} - } - - timeout := false - var timer *time.Timer - if r.Timeout > 0 { - timer = time.AfterFunc(r.Timeout, func() { - cancelRequest(req) - timeout = true - }) - } - - if r.ShowDebug { - dump, err := httputil.DumpRequest(req, true) - if err != nil { - log.Println(err) - } - log.Println(string(dump)) - } - - if r.OnBeforeRequest != nil { - r.OnBeforeRequest(&r, req) - } - res, err := client.Do(req) - if timer != nil { - timer.Stop() - } - - if err != nil { - if !timeout { - switch err := err.(type) { - case *net.OpError: - timeout = err.Timeout() - case *url.Error: - if op, ok := err.Err.(*net.OpError); ok { - timeout = op.Timeout() - } - } - } - - var response *Response - //If redirect fails we still want to return response data - if redirectFailed { - if res != nil { - response = &Response{res, resUri, &Body{reader: res.Body}, req} - } else { - response = &Response{res, resUri, nil, req} - } - } - - //If redirect fails and we haven't set a redirect count we shouldn't return an error - if redirectFailed && r.MaxRedirects == 0 { - return response, nil - } - - return response, &Error{timeout: timeout, Err: err} - } - - if r.Compression != nil && strings.Contains(res.Header.Get("Content-Encoding"), r.Compression.ContentEncoding) { - compressedReader, err := r.Compression.reader(res.Body) - if err != nil { - return nil, &Error{Err: err} - } - return &Response{res, resUri, &Body{reader: res.Body, compressedReader: compressedReader}, req}, nil - } - - return &Response{res, resUri, &Body{reader: res.Body}, req}, nil -} - -func (r Request) addHeaders(headersMap http.Header) { - if len(r.UserAgent) > 0 { - headersMap.Add("User-Agent", r.UserAgent) - } - if r.Accept != "" { - headersMap.Add("Accept", r.Accept) - } - if r.ContentType != "" { - headersMap.Add("Content-Type", r.ContentType) - } -} - -func (r Request) NewRequest() (*http.Request, error) { - - b, e := prepareRequestBody(r.Body) - if e != nil { - // there was a problem marshaling the body - return nil, &Error{Err: e} - } - - if r.QueryString != nil { - param, e := paramParse(r.QueryString) - if e != nil { - return nil, &Error{Err: e} - } - r.Uri = r.Uri + "?" + param - } - - var bodyReader io.Reader - if b != nil && r.Compression != nil { - buffer := bytes.NewBuffer([]byte{}) - readBuffer := bufio.NewReader(b) - writer, err := r.Compression.writer(buffer) - if err != nil { - return nil, &Error{Err: err} - } - _, e = readBuffer.WriteTo(writer) - writer.Close() - if e != nil { - return nil, &Error{Err: e} - } - bodyReader = buffer - } else { - bodyReader = b - } - - req, err := http.NewRequest(r.Method, r.Uri, bodyReader) - if err != nil { - return nil, err - } - // add headers to the request - req.Host = r.Host - - r.addHeaders(req.Header) - if r.Compression != nil { - req.Header.Add("Content-Encoding", r.Compression.ContentEncoding) - req.Header.Add("Accept-Encoding", r.Compression.ContentEncoding) - } - if r.headers != nil { - for _, header := range r.headers { - req.Header.Add(header.name, header.value) - } - } - - //use basic auth if required - if r.BasicAuthUsername != "" { - req.SetBasicAuth(r.BasicAuthUsername, r.BasicAuthPassword) - } - - for _, c := range r.cookies { - req.AddCookie(c) - } - return req, nil -} - -// Return value if nonempty, def otherwise. -func valueOrDefault(value, def string) string { - if value != "" { - return value - } - return def -} diff --git a/Godeps/_workspace/src/github.com/franela/goreq/goreq_test.go b/Godeps/_workspace/src/github.com/franela/goreq/goreq_test.go deleted file mode 100644 index 3b88c22..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/goreq_test.go +++ /dev/null @@ -1,1184 +0,0 @@ -package goreq - -import ( - "compress/gzip" - "compress/zlib" - "encoding/base64" - "fmt" - "io" - "io/ioutil" - "math" - "net/http" - "net/http/cookiejar" - "net/http/httptest" - "net/url" - "strings" - "testing" - "time" - - . "github.com/franela/goblin" - . "github.com/onsi/gomega" -) - -type Query struct { - Limit int - Skip int -} - -func TestRequest(t *testing.T) { - - query := Query{ - Limit: 3, - Skip: 5, - } - - valuesQuery := url.Values{} - valuesQuery.Set("name", "marcos") - valuesQuery.Add("friend", "jonas") - valuesQuery.Add("friend", "peter") - - g := Goblin(t) - - RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) }) - - g.Describe("Request", func() { - - g.Describe("General request methods", func() { - var ts *httptest.Server - var requestHeaders http.Header - - g.Before(func() { - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requestHeaders = r.Header - if (r.Method == "GET" || r.Method == "OPTIONS" || r.Method == "TRACE" || r.Method == "PATCH" || r.Method == "FOOBAR") && r.URL.Path == "/foo" { - w.WriteHeader(200) - fmt.Fprint(w, "bar") - } - if r.Method == "GET" && r.URL.Path == "/getquery" { - w.WriteHeader(200) - fmt.Fprint(w, fmt.Sprintf("%v", r.URL)) - } - if r.Method == "GET" && r.URL.Path == "/getbody" { - w.WriteHeader(200) - io.Copy(w, r.Body) - } - if r.Method == "POST" && r.URL.Path == "/" { - w.Header().Add("Location", ts.URL+"/123") - w.WriteHeader(201) - io.Copy(w, r.Body) - } - if r.Method == "POST" && r.URL.Path == "/getquery" { - w.WriteHeader(200) - fmt.Fprint(w, fmt.Sprintf("%v", r.URL)) - } - if r.Method == "PUT" && r.URL.Path == "/foo/123" { - w.WriteHeader(200) - io.Copy(w, r.Body) - } - if r.Method == "DELETE" && r.URL.Path == "/foo/123" { - w.WriteHeader(204) - } - if r.Method == "GET" && r.URL.Path == "/redirect_test/301" { - http.Redirect(w, r, "/redirect_test/302", 301) - } - if r.Method == "GET" && r.URL.Path == "/redirect_test/302" { - http.Redirect(w, r, "/redirect_test/303", 302) - } - if r.Method == "GET" && r.URL.Path == "/redirect_test/303" { - http.Redirect(w, r, "/redirect_test/307", 303) - } - if r.Method == "GET" && r.URL.Path == "/redirect_test/307" { - http.Redirect(w, r, "/getquery", 307) - } - if r.Method == "GET" && r.URL.Path == "/redirect_test/destination" { - http.Redirect(w, r, ts.URL+"/destination", 301) - } - if r.Method == "GET" && r.URL.Path == "/getcookies" { - defer r.Body.Close() - w.WriteHeader(200) - fmt.Fprint(w, requestHeaders.Get("Cookie")) - } - if r.Method == "GET" && r.URL.Path == "/setcookies" { - defer r.Body.Close() - w.Header().Add("Set-Cookie", "foobar=42 ; Path=/") - w.WriteHeader(200) - } - if r.Method == "GET" && r.URL.Path == "/compressed" { - defer r.Body.Close() - b := "{\"foo\":\"bar\",\"fuu\":\"baz\"}" - gw := gzip.NewWriter(w) - defer gw.Close() - if strings.Contains(r.Header.Get("Content-Encoding"), "gzip") { - w.Header().Add("Content-Encoding", "gzip") - } - w.WriteHeader(200) - gw.Write([]byte(b)) - } - if r.Method == "GET" && r.URL.Path == "/compressed_deflate" { - defer r.Body.Close() - b := "{\"foo\":\"bar\",\"fuu\":\"baz\"}" - gw := zlib.NewWriter(w) - defer gw.Close() - if strings.Contains(r.Header.Get("Content-Encoding"), "deflate") { - w.Header().Add("Content-Encoding", "deflate") - } - w.WriteHeader(200) - gw.Write([]byte(b)) - } - if r.Method == "GET" && r.URL.Path == "/compressed_and_return_compressed_without_header" { - defer r.Body.Close() - b := "{\"foo\":\"bar\",\"fuu\":\"baz\"}" - gw := gzip.NewWriter(w) - defer gw.Close() - w.WriteHeader(200) - gw.Write([]byte(b)) - } - if r.Method == "GET" && r.URL.Path == "/compressed_deflate_and_return_compressed_without_header" { - defer r.Body.Close() - b := "{\"foo\":\"bar\",\"fuu\":\"baz\"}" - gw := zlib.NewWriter(w) - defer gw.Close() - w.WriteHeader(200) - gw.Write([]byte(b)) - } - if r.Method == "POST" && r.URL.Path == "/compressed" && r.Header.Get("Content-Encoding") == "gzip" { - defer r.Body.Close() - gr, _ := gzip.NewReader(r.Body) - defer gr.Close() - b, _ := ioutil.ReadAll(gr) - w.WriteHeader(201) - w.Write(b) - } - if r.Method == "POST" && r.URL.Path == "/compressed_deflate" && r.Header.Get("Content-Encoding") == "deflate" { - defer r.Body.Close() - gr, _ := zlib.NewReader(r.Body) - defer gr.Close() - b, _ := ioutil.ReadAll(gr) - w.WriteHeader(201) - w.Write(b) - } - if r.Method == "POST" && r.URL.Path == "/compressed_and_return_compressed" { - defer r.Body.Close() - w.Header().Add("Content-Encoding", "gzip") - w.WriteHeader(201) - io.Copy(w, r.Body) - } - if r.Method == "POST" && r.URL.Path == "/compressed_deflate_and_return_compressed" { - defer r.Body.Close() - w.Header().Add("Content-Encoding", "deflate") - w.WriteHeader(201) - io.Copy(w, r.Body) - } - if r.Method == "POST" && r.URL.Path == "/compressed_deflate_and_return_compressed_without_header" { - defer r.Body.Close() - w.WriteHeader(201) - io.Copy(w, r.Body) - } - if r.Method == "POST" && r.URL.Path == "/compressed_and_return_compressed_without_header" { - defer r.Body.Close() - w.WriteHeader(201) - io.Copy(w, r.Body) - } - })) - }) - - g.After(func() { - ts.Close() - }) - - g.Describe("GET", func() { - - g.It("Should do a GET", func() { - res, err := Request{Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should return ContentLength", func() { - res, err := Request{Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - Expect(res.ContentLength).Should(Equal(int64(3))) - }) - - g.It("Should do a GET with querystring", func() { - res, err := Request{ - Uri: ts.URL + "/getquery", - QueryString: query, - }.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("/getquery?limit=3&skip=5")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should support url.Values in querystring", func() { - res, err := Request{ - Uri: ts.URL + "/getquery", - QueryString: valuesQuery, - }.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("/getquery?friend=jonas&friend=peter&name=marcos")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should support sending string body", func() { - res, err := Request{Uri: ts.URL + "/getbody", Body: "foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Shoulds support sending a Reader body", func() { - res, err := Request{Uri: ts.URL + "/getbody", Body: strings.NewReader("foo")}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Support sending any object that is json encodable", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Uri: ts.URL + "/getbody", Body: obj}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Support sending an array of bytes body", func() { - bdy := []byte{'f', 'o', 'o'} - res, err := Request{Uri: ts.URL + "/getbody", Body: bdy}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should return an error when body is not JSON encodable", func() { - res, err := Request{Uri: ts.URL + "/getbody", Body: math.NaN()}.Do() - - Expect(res).Should(BeNil()) - Expect(err).ShouldNot(BeNil()) - }) - - g.It("Should return a gzip reader if Content-Encoding is 'gzip'", func() { - res, err := Request{Uri: ts.URL + "/compressed", Compression: Gzip()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(res.Body.compressedReader).ShouldNot(BeNil()) - Expect(res.Body.reader).ShouldNot(BeNil()) - Expect(string(b)).Should(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - Expect(res.Body.compressedReader).ShouldNot(BeNil()) - Expect(res.Body.reader).ShouldNot(BeNil()) - }) - - g.It("Should close reader and compresserReader on Body close", func() { - res, err := Request{Uri: ts.URL + "/compressed", Compression: Gzip()}.Do() - Expect(err).Should(BeNil()) - - _, e := ioutil.ReadAll(res.Body.reader) - Expect(e).Should(BeNil()) - _, e = ioutil.ReadAll(res.Body.compressedReader) - Expect(e).Should(BeNil()) - - _, e = ioutil.ReadAll(res.Body.reader) - //when reading body again it doesnt error - Expect(e).Should(BeNil()) - - res.Body.Close() - _, e = ioutil.ReadAll(res.Body.reader) - //error because body is already closed - Expect(e).ShouldNot(BeNil()) - - _, e = ioutil.ReadAll(res.Body.compressedReader) - //compressedReaders dont error on reading when closed - Expect(e).Should(BeNil()) - }) - - g.It("Should not return a gzip reader if Content-Encoding is not 'gzip'", func() { - res, err := Request{Uri: ts.URL + "/compressed_and_return_compressed_without_header", Compression: Gzip()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(string(b)).ShouldNot(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - }) - - g.It("Should return a deflate reader if Content-Encoding is 'deflate'", func() { - res, err := Request{Uri: ts.URL + "/compressed_deflate", Compression: Deflate()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(string(b)).Should(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - }) - - g.It("Should not return a delfate reader if Content-Encoding is not 'deflate'", func() { - res, err := Request{Uri: ts.URL + "/compressed_deflate_and_return_compressed_without_header", Compression: Deflate()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(string(b)).ShouldNot(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - }) - - g.It("Should return a deflate reader when using zlib if Content-Encoding is 'deflate'", func() { - res, err := Request{Uri: ts.URL + "/compressed_deflate", Compression: Zlib()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(string(b)).Should(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - }) - - g.It("Should not return a delfate reader when using zlib if Content-Encoding is not 'deflate'", func() { - res, err := Request{Uri: ts.URL + "/compressed_deflate_and_return_compressed_without_header", Compression: Zlib()}.Do() - b, _ := ioutil.ReadAll(res.Body) - Expect(err).Should(BeNil()) - Expect(string(b)).ShouldNot(Equal("{\"foo\":\"bar\",\"fuu\":\"baz\"}")) - }) - - g.It("Should send cookies from the cookiejar", func() { - uri, err := url.Parse(ts.URL + "/getcookies") - Expect(err).Should(BeNil()) - - jar, err := cookiejar.New(nil) - Expect(err).Should(BeNil()) - - jar.SetCookies(uri, []*http.Cookie{ - { - Name: "bar", - Value: "foo", - Path: "/", - }, - }) - - res, err := Request{ - Uri: ts.URL + "/getcookies", - CookieJar: jar, - }.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar=foo")) - Expect(res.StatusCode).Should(Equal(200)) - Expect(res.ContentLength).Should(Equal(int64(7))) - }) - - g.It("Should send cookies added with .AddCookie", func() { - c1 := &http.Cookie{Name: "c1", Value: "v1"} - c2 := &http.Cookie{Name: "c2", Value: "v2"} - - req := Request{Uri: ts.URL + "/getcookies"} - req.AddCookie(c1) - req.AddCookie(c2) - - res, err := req.Do() - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("c1=v1; c2=v2")) - Expect(res.StatusCode).Should(Equal(200)) - Expect(res.ContentLength).Should(Equal(int64(12))) - }) - - g.It("Should send cookies added with .WithCookie", func() { - c1 := &http.Cookie{Name: "c1", Value: "v2"} - c2 := &http.Cookie{Name: "c2", Value: "v3"} - - res, err := Request{Uri: ts.URL + "/getcookies"}. - WithCookie(c1). - WithCookie(c2). - Do() - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("c1=v2; c2=v3")) - Expect(res.StatusCode).Should(Equal(200)) - Expect(res.ContentLength).Should(Equal(int64(12))) - }) - - g.It("Should populate the cookiejar", func() { - uri, err := url.Parse(ts.URL + "/setcookies") - Expect(err).Should(BeNil()) - - jar, _ := cookiejar.New(nil) - Expect(err).Should(BeNil()) - - res, err := Request{ - Uri: ts.URL + "/setcookies", - CookieJar: jar, - }.Do() - - Expect(err).Should(BeNil()) - - Expect(res.Header.Get("Set-Cookie")).Should(Equal("foobar=42 ; Path=/")) - - cookies := jar.Cookies(uri) - Expect(len(cookies)).Should(Equal(1)) - - cookie := cookies[0] - Expect(*cookie).Should(Equal(http.Cookie{ - Name: "foobar", - Value: "42", - })) - }) - }) - - g.Describe("POST", func() { - g.It("Should send a string", func() { - res, err := Request{Method: "POST", Uri: ts.URL, Body: "foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(201)) - Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123")) - }) - - g.It("Should send a Reader", func() { - res, err := Request{Method: "POST", Uri: ts.URL, Body: strings.NewReader("foo")}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(201)) - Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123")) - }) - - g.It("Send any object that is json encodable", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL, Body: obj}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123")) - }) - - g.It("Send an array of bytes", func() { - bdy := []byte{'f', 'o', 'o'} - res, err := Request{Method: "POST", Uri: ts.URL, Body: bdy}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(201)) - Expect(res.Header.Get("Location")).Should(Equal(ts.URL + "/123")) - }) - - g.It("Should return an error when body is not JSON encodable", func() { - res, err := Request{Method: "POST", Uri: ts.URL, Body: math.NaN()}.Do() - - Expect(res).Should(BeNil()) - Expect(err).ShouldNot(BeNil()) - }) - - g.It("Should do a POST with querystring", func() { - bdy := []byte{'f', 'o', 'o'} - res, err := Request{ - Method: "POST", - Uri: ts.URL + "/getquery", - Body: bdy, - QueryString: query, - }.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("/getquery?limit=3&skip=5")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should send body as gzip if compressed", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed", Body: obj, Compression: Gzip()}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate if compressed", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate", Body: obj, Compression: Deflate()}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate using zlib if compressed", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate", Body: obj, Compression: Zlib()}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as gzip if compressed and parse return body", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_and_return_compressed", Body: obj, Compression: Gzip()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate if compressed and parse return body", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate_and_return_compressed", Body: obj, Compression: Deflate()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate using zlib if compressed and parse return body", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate_and_return_compressed", Body: obj, Compression: Zlib()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).Should(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as gzip if compressed and not parse return body if header not set ", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_and_return_compressed_without_header", Body: obj, Compression: Gzip()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).ShouldNot(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate if compressed and not parse return body if header not set ", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate_and_return_compressed_without_header", Body: obj, Compression: Deflate()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).ShouldNot(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - - g.It("Should send body as deflate using zlib if compressed and not parse return body if header not set ", func() { - obj := map[string]string{"foo": "bar"} - res, err := Request{Method: "POST", Uri: ts.URL + "/compressed_deflate_and_return_compressed_without_header", Body: obj, Compression: Zlib()}.Do() - - Expect(err).Should(BeNil()) - b, _ := ioutil.ReadAll(res.Body) - Expect(string(b)).ShouldNot(Equal(`{"foo":"bar"}`)) - Expect(res.StatusCode).Should(Equal(201)) - }) - }) - - g.It("Should do a PUT", func() { - res, err := Request{Method: "PUT", Uri: ts.URL + "/foo/123", Body: "foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should do a DELETE", func() { - res, err := Request{Method: "DELETE", Uri: ts.URL + "/foo/123"}.Do() - - Expect(err).Should(BeNil()) - Expect(res.StatusCode).Should(Equal(204)) - }) - - g.It("Should do a OPTIONS", func() { - res, err := Request{Method: "OPTIONS", Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should do a PATCH", func() { - res, err := Request{Method: "PATCH", Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should do a TRACE", func() { - res, err := Request{Method: "TRACE", Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should do a custom method", func() { - res, err := Request{Method: "FOOBAR", Uri: ts.URL + "/foo"}.Do() - - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(str).Should(Equal("bar")) - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.Describe("Responses", func() { - g.It("Should handle strings", func() { - res, _ := Request{Method: "POST", Uri: ts.URL, Body: "foo bar"}.Do() - - str, _ := res.Body.ToString() - Expect(str).Should(Equal("foo bar")) - }) - - g.It("Should handle io.ReaderCloser", func() { - res, _ := Request{Method: "POST", Uri: ts.URL, Body: "foo bar"}.Do() - - body, _ := ioutil.ReadAll(res.Body) - Expect(string(body)).Should(Equal("foo bar")) - }) - - g.It("Should handle parsing JSON", func() { - res, _ := Request{Method: "POST", Uri: ts.URL, Body: `{"foo": "bar"}`}.Do() - - var foobar map[string]string - - res.Body.FromJsonTo(&foobar) - - Expect(foobar).Should(Equal(map[string]string{"foo": "bar"})) - }) - - g.It("Should return the original request response", func() { - res, _ := Request{Method: "POST", Uri: ts.URL, Body: `{"foo": "bar"}`}.Do() - - Expect(res.Response).ShouldNot(BeNil()) - }) - }) - g.Describe("Redirects", func() { - g.It("Should not follow by default", func() { - res, _ := Request{ - Uri: ts.URL + "/redirect_test/301", - }.Do() - Expect(res.StatusCode).Should(Equal(301)) - }) - - g.It("Should not follow if method is explicitly specified", func() { - res, err := Request{ - Method: "GET", - Uri: ts.URL + "/redirect_test/301", - }.Do() - Expect(res.StatusCode).Should(Equal(301)) - Expect(err).ShouldNot(HaveOccurred()) - }) - - g.It("Should throw an error if MaxRedirect limit is exceeded", func() { - res, err := Request{ - Method: "GET", - MaxRedirects: 1, - Uri: ts.URL + "/redirect_test/301", - }.Do() - Expect(res.StatusCode).Should(Equal(302)) - Expect(err).Should(HaveOccurred()) - }) - - g.It("Should copy request headers headers when redirecting if specified", func() { - req := Request{ - Method: "GET", - Uri: ts.URL + "/redirect_test/301", - MaxRedirects: 4, - RedirectHeaders: true, - } - req.AddHeader("Testheader", "TestValue") - res, _ := req.Do() - Expect(res.StatusCode).Should(Equal(200)) - Expect(requestHeaders.Get("Testheader")).Should(Equal("TestValue")) - }) - - g.It("Should follow only specified number of MaxRedirects", func() { - res, _ := Request{ - Uri: ts.URL + "/redirect_test/301", - MaxRedirects: 1, - }.Do() - Expect(res.StatusCode).Should(Equal(302)) - res, _ = Request{ - Uri: ts.URL + "/redirect_test/301", - MaxRedirects: 2, - }.Do() - Expect(res.StatusCode).Should(Equal(303)) - res, _ = Request{ - Uri: ts.URL + "/redirect_test/301", - MaxRedirects: 3, - }.Do() - Expect(res.StatusCode).Should(Equal(307)) - res, _ = Request{ - Uri: ts.URL + "/redirect_test/301", - MaxRedirects: 4, - }.Do() - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should return final URL of the response when redirecting", func() { - res, _ := Request{ - Uri: ts.URL + "/redirect_test/destination", - MaxRedirects: 2, - }.Do() - Expect(res.Uri).Should(Equal(ts.URL + "/destination")) - }) - }) - }) - - g.Describe("Timeouts", func() { - - g.Describe("Connection timeouts", func() { - g.It("Should connect timeout after a default of 1000 ms", func() { - start := time.Now() - res, err := Request{Uri: "http://10.255.255.1"}.Do() - elapsed := time.Since(start) - - Expect(elapsed).Should(BeNumerically("<", 1100*time.Millisecond)) - Expect(elapsed).Should(BeNumerically(">=", 1000*time.Millisecond)) - Expect(res).Should(BeNil()) - Expect(err.(*Error).Timeout()).Should(BeTrue()) - }) - g.It("Should connect timeout after a custom amount of time", func() { - SetConnectTimeout(100 * time.Millisecond) - start := time.Now() - res, err := Request{Uri: "http://10.255.255.1"}.Do() - elapsed := time.Since(start) - - Expect(elapsed).Should(BeNumerically("<", 150*time.Millisecond)) - Expect(elapsed).Should(BeNumerically(">=", 100*time.Millisecond)) - Expect(res).Should(BeNil()) - Expect(err.(*Error).Timeout()).Should(BeTrue()) - }) - g.It("Should connect timeout after a custom amount of time even with method set", func() { - SetConnectTimeout(100 * time.Millisecond) - start := time.Now() - request := Request{ - Uri: "http://10.255.255.1", - Method: "GET", - } - res, err := request.Do() - elapsed := time.Since(start) - - Expect(elapsed).Should(BeNumerically("<", 150*time.Millisecond)) - Expect(elapsed).Should(BeNumerically(">=", 100*time.Millisecond)) - Expect(res).Should(BeNil()) - Expect(err.(*Error).Timeout()).Should(BeTrue()) - }) - }) - - g.Describe("Request timeout", func() { - var ts *httptest.Server - stop := make(chan bool) - - g.Before(func() { - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - <-stop - // just wait for someone to tell you when to end the request. this is used to simulate a slow server - })) - }) - g.After(func() { - stop <- true - ts.Close() - }) - g.It("Should request timeout after a custom amount of time", func() { - SetConnectTimeout(1000 * time.Millisecond) - - start := time.Now() - res, err := Request{Uri: ts.URL, Timeout: 500 * time.Millisecond}.Do() - elapsed := time.Since(start) - - Expect(elapsed).Should(BeNumerically("<", 550*time.Millisecond)) - Expect(elapsed).Should(BeNumerically(">=", 500*time.Millisecond)) - Expect(res).Should(BeNil()) - Expect(err.(*Error).Timeout()).Should(BeTrue()) - }) - }) - }) - - g.Describe("Misc", func() { - g.It("Should set default golang user agent when not explicitly passed", func() { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - Expect(r.Header.Get("User-Agent")).ShouldNot(BeZero()) - Expect(r.Host).Should(Equal("foobar.com")) - - w.WriteHeader(200) - })) - defer ts.Close() - - req := Request{Uri: ts.URL, Host: "foobar.com"} - res, err := req.Do() - Expect(err).ShouldNot(HaveOccurred()) - - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should offer to set request headers", func() { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - Expect(r.Header.Get("User-Agent")).Should(Equal("foobaragent")) - Expect(r.Host).Should(Equal("foobar.com")) - Expect(r.Header.Get("Accept")).Should(Equal("application/json")) - Expect(r.Header.Get("Content-Type")).Should(Equal("application/json")) - Expect(r.Header.Get("X-Custom")).Should(Equal("foobar")) - Expect(r.Header.Get("X-Custom2")).Should(Equal("barfoo")) - - w.WriteHeader(200) - })) - defer ts.Close() - - req := Request{Uri: ts.URL, Accept: "application/json", ContentType: "application/json", UserAgent: "foobaragent", Host: "foobar.com"} - req.AddHeader("X-Custom", "foobar") - res, _ := req.WithHeader("X-Custom2", "barfoo").Do() - - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should call hook before request", func() { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - Expect(r.Header.Get("X-Custom")).Should(Equal("foobar")) - - w.WriteHeader(200) - })) - defer ts.Close() - - hook := func(goreq *Request, httpreq *http.Request) { - httpreq.Header.Add("X-Custom", "foobar") - } - req := Request{Uri: ts.URL, OnBeforeRequest: hook} - res, _ := req.Do() - - Expect(res.StatusCode).Should(Equal(200)) - }) - - g.It("Should not create a body by defualt", func() { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - b, _ := ioutil.ReadAll(r.Body) - Expect(b).Should(HaveLen(0)) - w.WriteHeader(200) - })) - defer ts.Close() - - req := Request{Uri: ts.URL, Host: "foobar.com"} - req.Do() - }) - g.It("Should change transport TLS config if Request.Insecure is set", func() { - ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - })) - defer ts.Close() - - req := Request{ - Insecure: true, - Uri: ts.URL, - Host: "foobar.com", - } - res, _ := req.Do() - - Expect(DefaultClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify).Should(Equal(true)) - Expect(res.StatusCode).Should(Equal(200)) - }) - g.It("Should work if a different transport is specified", func() { - ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - })) - defer ts.Close() - var currentTransport = DefaultTransport - DefaultTransport = &http.Transport{Dial: DefaultDialer.Dial} - - req := Request{ - Insecure: true, - Uri: ts.URL, - Host: "foobar.com", - } - res, _ := req.Do() - - Expect(DefaultClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify).Should(Equal(true)) - Expect(res.StatusCode).Should(Equal(200)) - - DefaultTransport = currentTransport - - }) - g.It("GetRequest should return the underlying httpRequest ", func() { - req := Request{ - Host: "foobar.com", - } - - request, _ := req.NewRequest() - Expect(request).ShouldNot(BeNil()) - Expect(request.Host).Should(Equal(req.Host)) - }) - - g.It("Response should allow to cancel in-flight request", func() { - unblockc := make(chan bool) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello") - w.(http.Flusher).Flush() - <-unblockc - })) - defer ts.Close() - defer close(unblockc) - - req := Request{ - Insecure: true, - Uri: ts.URL, - Host: "foobar.com", - } - res, _ := req.Do() - res.CancelRequest() - _, err := ioutil.ReadAll(res.Body) - g.Assert(err != nil).IsTrue() - }) - }) - - g.Describe("Errors", func() { - var ts *httptest.Server - - g.Before(func() { - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" && r.URL.Path == "/" { - w.Header().Add("Location", ts.URL+"/123") - w.WriteHeader(201) - io.Copy(w, r.Body) - } - })) - }) - - g.After(func() { - ts.Close() - }) - g.It("Should throw an error when FromJsonTo fails", func() { - res, _ := Request{Method: "POST", Uri: ts.URL, Body: `{"foo" "bar"}`}.Do() - var foobar map[string]string - - err := res.Body.FromJsonTo(&foobar) - Expect(err).Should(HaveOccurred()) - }) - g.It("Should handle Url parsing errors", func() { - _, err := Request{Uri: ":"}.Do() - - Expect(err).ShouldNot(BeNil()) - }) - g.It("Should handle DNS errors", func() { - _, err := Request{Uri: "http://.localhost"}.Do() - Expect(err).ShouldNot(BeNil()) - }) - }) - - g.Describe("Proxy", func() { - var ts *httptest.Server - var lastReq *http.Request - g.Before(func() { - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" && r.URL.Path == "/" { - lastReq = r - w.Header().Add("x-forwarded-for", "test") - w.Header().Add("Set-Cookie", "foo=bar") - w.WriteHeader(200) - w.Write([]byte("")) - } else if r.Method == "GET" && r.URL.Path == "/redirect_test/301" { - http.Redirect(w, r, "/", 301) - } - })) - - }) - - g.BeforeEach(func() { - lastReq = nil - }) - - g.After(func() { - ts.Close() - }) - - g.It("Should use Proxy", func() { - proxiedHost := "www.google.com" - res, err := Request{Uri: "http://" + proxiedHost, Proxy: ts.URL}.Do() - Expect(err).Should(BeNil()) - Expect(res.Header.Get("x-forwarded-for")).Should(Equal("test")) - Expect(lastReq).ShouldNot(BeNil()) - Expect(lastReq.Host).Should(Equal(proxiedHost)) - }) - - g.It("Should not redirect if MaxRedirects is not set", func() { - res, err := Request{Uri: ts.URL + "/redirect_test/301", Proxy: ts.URL}.Do() - Expect(err).ShouldNot(HaveOccurred()) - Expect(res.StatusCode).Should(Equal(301)) - }) - - g.It("Should use Proxy authentication", func() { - proxiedHost := "www.google.com" - uri := strings.Replace(ts.URL, "http://", "http://user:pass@", -1) - res, err := Request{Uri: "http://" + proxiedHost, Proxy: uri}.Do() - Expect(err).Should(BeNil()) - Expect(res.Header.Get("x-forwarded-for")).Should(Equal("test")) - Expect(lastReq).ShouldNot(BeNil()) - Expect(lastReq.Header.Get("Proxy-Authorization")).Should(Equal("Basic dXNlcjpwYXNz")) - }) - - g.It("Should propagate cookies", func() { - proxiedHost, _ := url.Parse("http://www.google.com") - jar, _ := cookiejar.New(nil) - res, err := Request{Uri: proxiedHost.String(), Proxy: ts.URL, CookieJar: jar}.Do() - Expect(err).Should(BeNil()) - Expect(res.Header.Get("x-forwarded-for")).Should(Equal("test")) - - Expect(jar.Cookies(proxiedHost)).Should(HaveLen(1)) - Expect(jar.Cookies(proxiedHost)[0].Name).Should(Equal("foo")) - Expect(jar.Cookies(proxiedHost)[0].Value).Should(Equal("bar")) - }) - - }) - - g.Describe("BasicAuth", func() { - var ts *httptest.Server - - g.Before(func() { - ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/basic_auth" { - auth_array := r.Header["Authorization"] - if len(auth_array) > 0 { - auth := strings.TrimSpace(auth_array[0]) - w.WriteHeader(200) - fmt.Fprint(w, auth) - } else { - w.WriteHeader(401) - fmt.Fprint(w, "private") - } - } - })) - - }) - - g.After(func() { - ts.Close() - }) - - g.It("Should support basic http authorization", func() { - res, err := Request{ - Uri: ts.URL + "/basic_auth", - BasicAuthUsername: "username", - BasicAuthPassword: "password", - }.Do() - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(res.StatusCode).Should(Equal(200)) - expectedStr := "Basic " + base64.StdEncoding.EncodeToString([]byte("username:password")) - Expect(str).Should(Equal(expectedStr)) - }) - - g.It("Should fail when basic http authorization is required and not provided", func() { - res, err := Request{ - Uri: ts.URL + "/basic_auth", - }.Do() - Expect(err).Should(BeNil()) - str, _ := res.Body.ToString() - Expect(res.StatusCode).Should(Equal(401)) - Expect(str).Should(Equal("private")) - }) - }) - }) -} - -func Test_paramParse(t *testing.T) { - type Form struct { - A string - B string - c string - } - - type AnnotedForm struct { - Foo string `url:"foo_bar"` - Baz string `url:"bad,omitempty"` - Norf string `url:"norf,omitempty"` - Qux string `url:"-"` - } - - type EmbedForm struct { - AnnotedForm `url:",squash"` - Form `url:",squash"` - Corge string `url:"corge"` - } - - g := Goblin(t) - RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) }) - var form = Form{} - var aform = AnnotedForm{} - var eform = EmbedForm{} - var values = url.Values{} - const result = "a=1&b=2" - g.Describe("QueryString ParamParse", func() { - g.Before(func() { - form.A = "1" - form.B = "2" - form.c = "3" - aform.Foo = "xyz" - aform.Norf = "abc" - aform.Qux = "def" - eform.Form = form - eform.AnnotedForm = aform - eform.Corge = "xxx" - values.Add("a", "1") - values.Add("b", "2") - }) - g.It("Should accept struct and ignores unexported field", func() { - str, err := paramParse(form) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - g.It("Should accept struct and use the field annotations", func() { - str, err := paramParse(aform) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal("foo_bar=xyz&norf=abc")) - }) - g.It("Should accept pointer of struct", func() { - str, err := paramParse(&form) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - g.It("Should accept recursive pointer of struct", func() { - f := &form - ff := &f - str, err := paramParse(ff) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - g.It("Should accept embedded struct", func() { - str, err := paramParse(eform) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal("a=1&b=2&corge=xxx&foo_bar=xyz&norf=abc")) - }) - g.It("Should accept interface{} which forcely converted by struct", func() { - str, err := paramParse(interface{}(&form)) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - - g.It("Should accept url.Values", func() { - str, err := paramParse(values) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - g.It("Should accept &url.Values", func() { - str, err := paramParse(&values) - Expect(err).Should(BeNil()) - Expect(str).Should(Equal(result)) - }) - }) - -} diff --git a/Godeps/_workspace/src/github.com/franela/goreq/tags.go b/Godeps/_workspace/src/github.com/franela/goreq/tags.go deleted file mode 100644 index ffe8789..0000000 --- a/Godeps/_workspace/src/github.com/franela/goreq/tags.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package goreq - -import ( - "strings" - "unicode" -) - -// tagOptions is the string following a comma in a struct field's "json" -// tag, or the empty string. It does not include the leading comma. -type tagOptions string - -// parseTag splits a struct field's json tag into its name and -// comma-separated options. -func parseTag(tag string) (string, tagOptions) { - if idx := strings.Index(tag, ","); idx != -1 { - return tag[:idx], tagOptions(tag[idx+1:]) - } - return tag, tagOptions("") -} - -// Contains reports whether a comma-separated list of options -// contains a particular substr flag. substr must be surrounded by a -// string boundary or commas. -func (o tagOptions) Contains(optionName string) bool { - if len(o) == 0 { - return false - } - s := string(o) - for s != "" { - var next string - i := strings.Index(s, ",") - if i >= 0 { - s, next = s[:i], s[i+1:] - } - if s == optionName { - return true - } - s = next - } - return false -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - default: - if !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - } - return true -}