diff --git a/README.md b/README.md index 85997ca..023c47d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ GoRequest -- Simplified HTTP client ( inspired by famous SuperAgent lib in Node. #### "Shooting Requests like a Machine Gun" - Gopher -Sending request would never been fun and easier than this. It comes with lots of feature: +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 @@ -59,7 +59,7 @@ 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 is getting more complicated in golang. You need to create a Client, setting header in different command, ... to do just only one __GET__ +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__ ```go client := &http.Client{ @@ -72,7 +72,7 @@ req.Header.Add("If-None-Match", `W/"wyzzy"`) resp, err := client.Do(req) ``` -Why making things ugly while you can just do as follows: +Why make things ugly while you can just do it as follows: ```go request := gorequest.New() @@ -82,7 +82,7 @@ resp, body, errs := request.Get("http://example.com"). End() ``` -__DELETE__, __HEAD__, __POST__, __PUT__, __PATCH__ are now supported and can be used the same way as __GET__: +__DELETE__, __HEAD__, __POST__, __PUT__, __PATCH__ are now supported and can be used in the same way as __GET__: ```go request := gorequest.New() @@ -95,7 +95,7 @@ resp, body, errs := request.Post("http://example.com").End() ### JSON -For a __JSON POST__ with standard libraries, you might need to marshal map data structure to json format, setting header to 'application/json' (and other headers if you need to) and declare http.Client. So, you code become longer and hard to maintain: +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: ```go m := map[string]interface{}{ @@ -176,6 +176,31 @@ gorequest.New().Post("http://example.com/"). 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: + +```go +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: + +```go +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: diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..273f2ef --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/parnurzeal/gorequest + +go 1.25.5 + +require ( + github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 + github.com/pkg/errors v0.9.1 + golang.org/x/net v0.21.0 + moul.io/http2curl/v2 v2.3.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b4a42a8 --- /dev/null +++ b/go.sum @@ -0,0 +1,42 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M= +github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/gorequest.go b/gorequest.go index 54bc554..0fa79fd 100644 --- a/gorequest.go +++ b/gorequest.go @@ -3,33 +3,29 @@ package gorequest import ( "bytes" + "context" "crypto/tls" "encoding/json" + "fmt" "io" "io/ioutil" "log" + "mime/multipart" "net/http" "net/http/cookiejar" "net/http/httputil" + "net/textproto" "net/url" "os" + "path/filepath" "reflect" "strconv" "strings" "time" "github.com/pkg/errors" - - "mime/multipart" - - "net/textproto" - - "fmt" - - "path/filepath" - - "github.com/moul/http2curl" "golang.org/x/net/publicsuffix" + "moul.io/http2curl/v2" ) type Request *http.Request @@ -91,6 +87,7 @@ type SuperAgent struct { Retryable superAgentRetryable DoNotClearSuperAgent bool isClone bool + context context.Context } var DisableTransportSwap = false @@ -123,6 +120,7 @@ func New() *SuperAgent { CurlCommand: false, logger: log.New(os.Stderr, "[gorequest]", log.LstdFlags), isClone: false, + context: nil, } // disable keep alives by default, see this issue https://github.com/parnurzeal/gorequest/issues/75 s.Transport.DisableKeepAlives = true @@ -234,6 +232,7 @@ func (s *SuperAgent) Clone() *SuperAgent { Retryable: copyRetryable(s.Retryable), DoNotClearSuperAgent: true, isClone: true, + context: s.context, } return clone } @@ -280,6 +279,7 @@ func (s *SuperAgent) ClearSuperAgent() { s.TargetType = TypeJSON s.Cookies = make([]*http.Cookie, 0) s.Errors = nil + s.context = nil } // Just a wrapper to initialize SuperAgent instance by method string @@ -397,7 +397,7 @@ func (s *SuperAgent) AppendHeader(param string, value string) *SuperAgent { // gorequest.New(). // Post("/gamelist"). -// Retry(3, 5 * time.seconds, http.StatusBadRequest, http.StatusInternalServerError). +// Retry(3, 5 * time.Second, http.StatusBadRequest, http.StatusInternalServerError). // End() func (s *SuperAgent) Retry(retryerCount int, retryerTime time.Duration, statusCode ...int) *SuperAgent { for _, code := range statusCode { @@ -541,7 +541,6 @@ func (s *SuperAgent) queryStruct(content interface{}) *SuperAgent { s.Errors = append(s.Errors, err) } else { for k, v := range val { - k = strings.ToLower(k) var queryVal string switch t := v.(type) { case string: @@ -610,6 +609,34 @@ func (s *SuperAgent) TLSClientConfig(config *tls.Config) *SuperAgent { return s } +func (s *SuperAgent) safeModifyTransport() { + if !s.isClone { + return + } + oldTransport := s.Transport + s.Transport = &http.Transport{} + + s.Transport.Proxy = oldTransport.Proxy + s.Transport.DialContext = oldTransport.DialContext + s.Transport.Dial = oldTransport.Dial + s.Transport.DialTLS = oldTransport.DialTLS + s.Transport.TLSClientConfig = oldTransport.TLSClientConfig + s.Transport.TLSHandshakeTimeout = oldTransport.TLSHandshakeTimeout + s.Transport.DisableKeepAlives = oldTransport.DisableKeepAlives + s.Transport.DisableCompression = oldTransport.DisableCompression + s.Transport.MaxIdleConns = oldTransport.MaxIdleConns + s.Transport.MaxIdleConnsPerHost = oldTransport.MaxIdleConnsPerHost + s.Transport.IdleConnTimeout = oldTransport.IdleConnTimeout + s.Transport.ResponseHeaderTimeout = oldTransport.ResponseHeaderTimeout + s.Transport.ExpectContinueTimeout = oldTransport.ExpectContinueTimeout + s.Transport.TLSNextProto = oldTransport.TLSNextProto + s.Transport.MaxResponseHeaderBytes = oldTransport.MaxResponseHeaderBytes + s.Transport.ProxyConnectHeader = oldTransport.ProxyConnectHeader + // Note: Consider adding other fields from http.Transport if necessary for Go 1.24.3 compatibility + + s.Client.Transport = s.Transport +} + // Proxy function accepts a proxy url string to setup proxy url for any request. // It provides a convenience way to setup proxy which have advantages over usual old ways. // One example is you might try to set `http_proxy` environment. This means you are setting proxy up for all the requests. @@ -658,6 +685,25 @@ func (s *SuperAgent) RedirectPolicy(policy func(req Request, via []Request) erro return s } +func (s *SuperAgent) safeModifyHttpClient() { + if !s.isClone { + return + } + oldClient := s.Client + s.Client = &http.Client{} + s.Client.Jar = oldClient.Jar + s.Client.Transport = oldClient.Transport + s.Client.Timeout = oldClient.Timeout + s.Client.CheckRedirect = oldClient.CheckRedirect +} + +// Timeout sets the timeout for the HTTP client. +func (s *SuperAgent) Timeout(timeout time.Duration) *SuperAgent { + s.safeModifyHttpClient() + s.Client.Timeout = timeout + return s +} + // Send function accepts either json string or query strings which is usually used to assign data to POST or PUT method. // Without specifying any type, if you give Send with json data, you are doing requesting in json format: // @@ -877,7 +923,8 @@ type File struct { // End() // // The second optional argument (third argument overall) is the fieldname in the multipart/form-data request. It defaults to fileNUMBER (eg. file1), where number is ascending and starts counting at 1. -// So if you send multiple files, the fieldnames will be file1, file2, ... unless it is overwritten. If fieldname is set to "file" it will be automatically set to fileNUMBER, where number is the greatest exsiting number+1. +// So if you send multiple files, the fieldnames will be file1, file2, ... unless it is overwritten. If fieldname is set to "file" it will be automatically set to fileNUMBER, where number is the greatest exsiting number+1 unless +// a third argument skipFileNumbering is provided and true. // // b, _ := ioutil.ReadFile("./example_file.ext") // gorequest.New(). @@ -886,18 +933,34 @@ type File struct { // SendFile(b, "", "my_custom_fieldname"). // filename left blank, will become "example_file.ext" // End() // -func (s *SuperAgent) SendFile(file interface{}, args ...string) *SuperAgent { +func (s *SuperAgent) SendFile(file interface{}, args ...interface{}) *SuperAgent { filename := "" fieldname := "file" + skipFileNumbering := false - if len(args) >= 1 && len(args[0]) > 0 { - filename = strings.TrimSpace(args[0]) + if len(args) >= 1 { + argFilename := fmt.Sprintf("%v", args[0]) + if len(argFilename) > 0 { + filename = strings.TrimSpace(argFilename) + } } - if len(args) >= 2 && len(args[1]) > 0 { - fieldname = strings.TrimSpace(args[1]) + + if len(args) >= 2 { + argFieldname := fmt.Sprintf("%v", args[1]) + if len(argFieldname) > 0 { + fieldname = strings.TrimSpace(argFieldname) + } } - if fieldname == "file" || fieldname == "" { + + if len(args) >= 3 { + argSkipFileNumbering := reflect.ValueOf(args[2]) + if argSkipFileNumbering.Type().Name() == "bool" { + skipFileNumbering = argSkipFileNumbering.Interface().(bool) + } + } + + if (fieldname == "file" && !skipFileNumbering) || fieldname == "" { fieldname = "file" + strconv.Itoa(len(s.FileData)+1) } @@ -939,9 +1002,12 @@ func (s *SuperAgent) SendFile(file interface{}, args ...string) *SuperAgent { if len(args) == 1 { return s.SendFile(v.Elem().Interface(), args[0]) } - if len(args) >= 2 { + if len(args) == 2 { return s.SendFile(v.Elem().Interface(), args[0], args[1]) } + if len(args) == 3 { + return s.SendFile(v.Elem().Interface(), args[0], args[1], args[2]) + } return s.SendFile(v.Elem().Interface()) default: if v.Type() == reflect.TypeOf(os.File{}) { @@ -1120,6 +1186,14 @@ func contains(respStatus int, statuses []int) bool { return false } +func (s *SuperAgent) Context(ctx context.Context) *SuperAgent{ + if ctx == nil { + panic("context can't be nil") + } + s.context = ctx + return s +} + // EndStruct should be used when you want the body as a struct. The callbacks work the same way as with `End`, except that a struct is used instead of a string. func (s *SuperAgent) EndStruct(v interface{}, callback ...func(response Response, v interface{}, body []byte, errs []error)) (Response, []byte, []error) { resp, body, errs := s.EndBytes() @@ -1220,10 +1294,12 @@ func (s *SuperAgent) getResponseBytes() (Response, []byte, []error) { } } - body, _ := ioutil.ReadAll(resp.Body) + body, err := ioutil.ReadAll(resp.Body) // Reset resp.Body so it can be use again resp.Body = ioutil.NopCloser(bytes.NewBuffer(body)) - + if err != nil { + return nil, nil, []error{err} + } return resp, body, nil } @@ -1359,6 +1435,11 @@ func (s *SuperAgent) MakeRequest() (*http.Request, error) { if req, err = http.NewRequest(s.Method, s.Url, contentReader); err != nil { return nil, err } + + if s.context != nil { + req = req.WithContext(s.context) + } + for k, vals := range s.Header { for _, v := range vals { req.Header.Add(k, v) @@ -1366,11 +1447,13 @@ func (s *SuperAgent) MakeRequest() (*http.Request, error) { // Setting the Host header is a special case, see this issue: https://github.com/golang/go/issues/7682 if strings.EqualFold(k, "Host") { - req.Host = vals[0] + req.Host = vals[len(vals)-1] } } - if len(contentType) != 0 { + // https://github.com/parnurzeal/gorequest/issues/164 + // Don't infer the content type header if an overrride is already provided. + if len(contentType) != 0 && req.Header.Get("Content-Type") == "" { req.Header.Set("Content-Type", contentType) } diff --git a/gorequest_client_go1.2.go b/gorequest_client_go1.2.go deleted file mode 100644 index 58dcb47..0000000 --- a/gorequest_client_go1.2.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.2 -// +build !go1.3 - -package gorequest - -import ( - "net" - "net/http" - "time" -) - - -// we don't want to mess up other clones when we modify the client.. -// so unfortantely we need to create a new client -func (s *SuperAgent) safeModifyHttpClient() { - if !s.isClone { - return - } - oldClient := s.Client - s.Client = &http.Client{} - s.Client.Jar = oldClient.Jar - s.Client.Transport = oldClient.Transport - s.Client.CheckRedirect = oldClient.CheckRedirect -} - -// I'm not sure how this func will work with Clone. -func (s *SuperAgent) Timeout(timeout time.Duration) *SuperAgent { - s.Transport.Dial = func(network, addr string) (net.Conn, error) { - conn, err := net.DialTimeout(network, addr, timeout) - if err != nil { - s.Errors = append(s.Errors, err) - return nil, err - } - conn.SetDeadline(time.Now().Add(timeout)) - return conn, nil - } - return s -} \ No newline at end of file diff --git a/gorequest_client_go1.3.go b/gorequest_client_go1.3.go deleted file mode 100644 index 2970e81..0000000 --- a/gorequest_client_go1.3.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build go1.3 - -package gorequest - -import ( - "time" - "net/http" -) - - -// we don't want to mess up other clones when we modify the client.. -// so unfortantely we need to create a new client -func (s *SuperAgent) safeModifyHttpClient() { - if !s.isClone { - return - } - oldClient := s.Client - s.Client = &http.Client{} - s.Client.Jar = oldClient.Jar - s.Client.Transport = oldClient.Transport - s.Client.Timeout = oldClient.Timeout - s.Client.CheckRedirect = oldClient.CheckRedirect -} - - -func (s *SuperAgent) Timeout(timeout time.Duration) *SuperAgent { - s.safeModifyHttpClient() - s.Client.Timeout = timeout - return s -} \ No newline at end of file diff --git a/gorequest_test.go b/gorequest_test.go index 023f328..c9cfebb 100644 --- a/gorequest_test.go +++ b/gorequest_test.go @@ -2,6 +2,7 @@ package gorequest import ( "bytes" + "context" "encoding/base64" "encoding/json" "fmt" @@ -44,70 +45,70 @@ type ( // Test for type constants. func TestTypeConstants(t *testing.T) { if TypeJSON != "json" { - t.Errorf("Expected TypeJSON -> json | but got %s", TypeJSON) + t.Error(fmt.Sprintf("Expected TypeJSON -> json | but got %s", TypeJSON)) } if TypeXML != "xml" { - t.Errorf("Expected TypeXML -> xml | but got %s", TypeXML) + t.Error(fmt.Sprintf("Expected TypeXML -> xml | but got %s", TypeXML)) } if TypeForm != "form" { - t.Errorf("Expected TypeForm -> form | but got %s", TypeForm) + t.Error(fmt.Sprintf("Expected TypeForm -> form | but got %s", TypeForm)) } if TypeFormData != "form-data" { - t.Errorf("Expected TypeFormData -> form-data | but got %s", TypeFormData) + t.Error(fmt.Sprintf("Expected TypeFormData -> form-data | but got %s", TypeFormData)) } if TypeUrlencoded != "urlencoded" { - t.Errorf("Expected TypeUrlencoded -> urlencoded | but got %s", TypeUrlencoded) + t.Error(fmt.Sprintf("Expected TypeUrlencoded -> urlencoded | but got %s", TypeUrlencoded)) } if TypeHTML != "html" { - t.Errorf("Expected TypeHTML -> html | but got %s", TypeHTML) + t.Error(fmt.Sprintf("Expected TypeHTML -> html | but got %s", TypeHTML)) } if TypeText != "text" { - t.Errorf("Expected TypeText -> text | but got %s", TypeText) + t.Error(fmt.Sprintf("Expected TypeText -> text | but got %s", TypeText)) } if TypeMultipart != "multipart" { - t.Errorf("Expected TypeMultipart -> multipart | but got %s", TypeMultipart) + t.Error(fmt.Sprintf("Expected TypeMultipart -> multipart | but got %s", TypeMultipart)) } } // Test for Types map. func TestTypesMap(t *testing.T) { if Types[TypeJSON] != "application/json" { - t.Errorf(`Expected Types["json"] -> "application/json" | but got %s`, Types[TypeJSON]) + t.Error(fmt.Sprintf(`Expected Types["json"] -> "application/json" | but got %s`, Types[TypeJSON])) } if Types[TypeXML] != "application/xml" { - t.Errorf(`Expected Types["xml"] -> "applicaion/xml" | but got %s`, Types[TypeXML]) + t.Error(fmt.Sprintf(`Expected Types["xml"] -> "applicaion/xml" | but got %s`, Types[TypeXML])) } if Types[TypeForm] != "application/x-www-form-urlencoded" { - t.Errorf(`Expected Types["form"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeForm]) + t.Error(fmt.Sprintf(`Expected Types["form"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeForm])) } if Types[TypeFormData] != "application/x-www-form-urlencoded" { - t.Errorf(`Expected Types["form-data"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeFormData]) + t.Error(fmt.Sprintf(`Expected Types["form-data"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeFormData])) } if Types[TypeUrlencoded] != "application/x-www-form-urlencoded" { - t.Errorf(`Expected Types["urlencoded"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeUrlencoded]) + t.Error(fmt.Sprintf(`Expected Types["urlencoded"] -> "application/x-www-form-urlencoded" | but got %s`, Types[TypeUrlencoded])) } if Types[TypeHTML] != "text/html" { - t.Errorf(`Expected Types["html"] -> "text/html" | but got %s`, Types[TypeHTML]) + t.Error(fmt.Sprintf(`Expected Types["html"] -> "text/html" | but got %s`, Types[TypeHTML])) } if Types[TypeText] != "text/plain" { - t.Errorf(`Expected Types["text"] -> "text/plain" | but got %s`, Types[TypeText]) + t.Error(fmt.Sprintf(`Expected Types["text"] -> "text/plain" | but got %s`, Types[TypeText])) } if Types[TypeMultipart] != "multipart/form-data" { - t.Errorf(`Expected Types["multipart"] -> "multipart/form-data" | but got %s`, Types[TypeMultipart]) + t.Error(fmt.Sprintf(`Expected Types["multipart"] -> "multipart/form-data" | but got %s`, Types[TypeMultipart])) } } @@ -134,74 +135,74 @@ func TestChangeMapToURLValues(t *testing.T) { ) if s := urlValues.Get("s"); s != data["s"] { - t.Errorf("Expected string %v, got %v", data["s"], s) + t.Error(fmt.Sprintf("Expected string %v, got %v", data["s"], s)) } s = urlValues.Get("i") sd = strconv.Itoa(data["i"].(int)) if s != sd { - t.Errorf("Expected int %v, got %v", sd, s) + t.Error(fmt.Sprintf("Expected int %v, got %v", sd, s)) } s = urlValues.Get("bt") sd = strconv.FormatBool(data["bt"].(bool)) if s != sd { - t.Errorf("Expected boolean %v, got %v", sd, s) + t.Error(fmt.Sprintf("Expected boolean %v, got %v", sd, s)) } s = urlValues.Get("bf") sd = strconv.FormatBool(data["bf"].(bool)) if s != sd { - t.Errorf("Expected boolean %v, got %v", sd, s) + t.Error(fmt.Sprintf("Expected boolean %v, got %v", sd, s)) } s = urlValues.Get("f") sd = strconv.FormatFloat(data["f"].(float64), 'f', -1, 64) if s != sd { - t.Errorf("Expected float %v, got %v", data["f"], s) + t.Error(fmt.Sprintf("Expected float %v, got %v", data["f"], s)) } // array cases // "To access multiple values, use the map directly." if size := len(urlValues["sa"]); size != 2 { - t.Fatalf("Expected length %v, got %v", 2, size) + t.Fatal(fmt.Sprintf("Expected length %v, got %v", 2, size)) } if urlValues["sa"][0] != "s1" { - t.Errorf("Expected string %v, got %v", "s1", urlValues["sa"][0]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "s1", urlValues["sa"][0])) } if urlValues["sa"][1] != "s2" { - t.Errorf("Expected string %v, got %v", "s2", urlValues["sa"][1]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "s2", urlValues["sa"][1])) } if size := len(urlValues["ia"]); size != 2 { - t.Fatalf("Expected length %v, got %v", 2, size) + t.Fatal(fmt.Sprintf("Expected length %v, got %v", 2, size)) } if urlValues["ia"][0] != "47" { - t.Errorf("Expected string %v, got %v", "47", urlValues["ia"][0]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "47", urlValues["ia"][0])) } if urlValues["ia"][1] != "73" { - t.Errorf("Expected string %v, got %v", "73", urlValues["ia"][1]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "73", urlValues["ia"][1])) } if size := len(urlValues["ba"]); size != 2 { - t.Fatalf("Expected length %v, got %v", 2, size) + t.Fatal(fmt.Sprintf("Expected length %v, got %v", 2, size)) } if urlValues["ba"][0] != "true" { - t.Errorf("Expected string %v, got %v", "true", urlValues["ba"][0]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "true", urlValues["ba"][0])) } if urlValues["ba"][1] != "false" { - t.Errorf("Expected string %v, got %v", "false", urlValues["ba"][1]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "false", urlValues["ba"][1])) } if size := len(urlValues["fa"]); size != 2 { - t.Fatalf("Expected length %v, got %v", 2, size) + t.Fatal(fmt.Sprintf("Expected length %v, got %v", 2, size)) } if urlValues["fa"][0] != "1.23" { - t.Errorf("Expected string %v, got %v", "true", urlValues["fa"][0]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "true", urlValues["fa"][0])) } if urlValues["fa"][1] != "4.56" { - t.Errorf("Expected string %v, got %v", "false", urlValues["fa"][1]) + t.Error(fmt.Sprintf("Expected string %v, got %v", "false", urlValues["fa"][1])) } } @@ -225,14 +226,14 @@ func TestMakeRequest(t *testing.T) { for _, c := range cases { _, err = c.s.MakeRequest() if err != nil { - t.Errorf("Expected nil error for method %q; got %q", c.m, err.Error()) + t.Error(fmt.Sprintf("Expected nil error for method %q; got %q", c.m, err.Error())) } } // empty method should fail _, err = New().CustomMethod("", "/").MakeRequest() if err == nil { - t.Errorf("Expected non-nil error for empty method; got %q", err.Error()) + t.Error(fmt.Sprintf("Expected non-nil error for empty method; got %q", err.Error())) } } @@ -243,20 +244,20 @@ func TestGet(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty: t.Logf("case %v ", case1_empty) case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } } })) @@ -278,20 +279,20 @@ func TestGetWithClone(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty: t.Logf("case %v ", case1_empty) case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } } })) @@ -313,20 +314,20 @@ func TestGetWithCloneRequestAfterMake(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty: t.Logf("case %v ", case1_empty) case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } } })) @@ -352,49 +353,49 @@ func TestGetWithCloneWithHeadersAndQuery(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } t.Logf("header %v", r.Header) if r.Header.Get("base") != "header" { - t.Errorf("Expected base header: %s", r.Header.Get("base")) + t.Error(fmt.Sprintf("Expected base header: %s", r.Header.Get("base"))) } if r.URL.Query().Get("queryBase") != "yep" { - t.Errorf("Expected queryBase queryParam: %s", r.URL.Query().Get("queryBase")) + t.Error(fmt.Sprintf("Expected queryBase queryParam: %s", r.URL.Query().Get("queryBase"))) } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty, case5_empty: t.Logf("case %v ", case1_empty) if r.Header.Get("API-Key") != "base" { - t.Errorf("Expected 'API-Key' == %q; got %q", "base", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "base", r.Header.Get("API-Key"))) } if r.URL.Query().Get("newQuery") != "" { - t.Errorf("Expected 'newQuery' == %q; got %q", "", r.URL.Query().Get("newQuery")) + t.Error(fmt.Sprintf("Expected 'newQuery' == %q; got %q", "", r.URL.Query().Get("newQuery"))) } if r.Header.Get("FOURTH") != "" { - t.Errorf("Expected 'FOURTH' == %q; got %q", "", r.Header.Get("FOURTH")) + t.Error(fmt.Sprintf("Expected 'FOURTH' == %q; got %q", "", r.Header.Get("FOURTH"))) } case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } case case3_set_query: t.Logf("case %v ", case3_set_query) if r.URL.Query().Get("newQuery") != "newVal" { - t.Errorf("Expected 'newQuery' == %q; got %q", "newVal", r.URL.Query().Get("newQuery")) + t.Error(fmt.Sprintf("Expected 'newQuery' == %q; got %q", "newVal", r.URL.Query().Get("newQuery"))) } case case4_set_both: t.Logf("case %v ", case3_set_query) if r.URL.Query().Get("fourth") != "4val" { - t.Errorf("Expected 'fourth' == %q; got %q", "4val", r.URL.Query().Get("fourth")) + t.Error(fmt.Sprintf("Expected 'fourth' == %q; got %q", "4val", r.URL.Query().Get("fourth"))) } if r.Header.Get("FOURTH") != "fourkey" { - t.Errorf("Expected 'FOURTH' == %q; got %q", "fourkey", r.Header.Get("FOURTH")) + t.Error(fmt.Sprintf("Expected 'FOURTH' == %q; got %q", "fourkey", r.Header.Get("FOURTH"))) } } })) @@ -433,63 +434,63 @@ func TestConcurrently(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET && r.URL.Path != case5_post { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } else if r.Method != POST && r.URL.Path == case5_post { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } t.Logf("header %v", r.Header) if r.Header.Get("base") != "header" { - t.Errorf("Expected base header: %s", r.Header.Get("base")) + t.Error(fmt.Sprintf("Expected base header: %s", r.Header.Get("base"))) } if r.URL.Query().Get("queryBase") != "yep" { - t.Errorf("Expected queryBase queryParam: %s", r.URL.Query().Get("queryBase")) + t.Error(fmt.Sprintf("Expected queryBase queryParam: %s", r.URL.Query().Get("queryBase"))) } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty: t.Logf("case %v ", case1_empty) if r.Header.Get("API-Key") != "base" { - t.Errorf("Expected 'API-Key' == %q; got %q", "base", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "base", r.Header.Get("API-Key"))) } if r.URL.Query().Get("newQuery") != "" { - t.Errorf("Expected 'newQuery' == %q; got %q", "", r.URL.Query().Get("newQuery")) + t.Error(fmt.Sprintf("Expected 'newQuery' == %q; got %q", "", r.URL.Query().Get("newQuery"))) } if r.Header.Get("FOURTH") != "" { - t.Errorf("Expected 'FOURTH' == %q; got %q", "", r.Header.Get("FOURTH")) + t.Error(fmt.Sprintf("Expected 'FOURTH' == %q; got %q", "", r.Header.Get("FOURTH"))) } case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } case case3_set_query: t.Logf("case %v ", case3_set_query) if r.URL.Query().Get("newQuery") != "newVal" { - t.Errorf("Expected 'newQuery' == %q; got %q", "newVal", r.URL.Query().Get("newQuery")) + t.Error(fmt.Sprintf("Expected 'newQuery' == %q; got %q", "newVal", r.URL.Query().Get("newQuery"))) } case case4_set_both: t.Logf("case %v ", case3_set_query) if r.URL.Query().Get("fourth") != "4val" { - t.Errorf("Expected 'fourth' == %q; got %q", "4val", r.URL.Query().Get("fourth")) + t.Error(fmt.Sprintf("Expected 'fourth' == %q; got %q", "4val", r.URL.Query().Get("fourth"))) } if r.Header.Get("FOURTH") != "fourkey" { - t.Errorf("Expected 'FOURTH' == %q; got %q", "fourkey", r.Header.Get("FOURTH")) + t.Error(fmt.Sprintf("Expected 'FOURTH' == %q; got %q", "fourkey", r.Header.Get("FOURTH"))) } case case5_post: t.Logf("case %v ", case5_post) if r.URL.Query().Get("iteration") == "" { - t.Errorf("Expected 'fourth' != %q; got %q", "", r.URL.Query().Get("iteration")) + t.Error(fmt.Sprintf("Expected 'fourth' != %q; got %q", "", r.URL.Query().Get("iteration"))) } r.ParseForm() if r.Form.Get("form_iteration") == "" { - t.Errorf("Expected 'form_iteration' != %q; got %q", "", r.Form.Get("form_iteration")) + t.Error(fmt.Sprintf("Expected 'form_iteration' != %q; got %q", "", r.Form.Get("form_iteration"))) } if r.Form.Get("form_iteration") != r.URL.Query().Get("iteration") { - t.Errorf("Expected 'form_iteration' == %q; got %q", r.URL.Query().Get("iteration"), r.Form.Get("form_iteration")) + t.Error(fmt.Sprintf("Expected 'form_iteration' == %q; got %q", r.URL.Query().Get("iteration"), r.Form.Get("form_iteration"))) } } })) @@ -554,7 +555,7 @@ func TestRetryGet(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is GET before going to check other features if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } //set return status @@ -564,7 +565,7 @@ func TestRetryGet(t *testing.T) { } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case1_empty: w.WriteHeader(400) t.Logf("case %v ", case1_empty) @@ -586,24 +587,24 @@ func TestRetryGet(t *testing.T) { Retry(3, 1*time.Nanosecond, http.StatusBadRequest). End() if errs != nil { - t.Errorf("No testing for this case yet : %q", errs) + t.Error(fmt.Sprintf("No testing for this case yet : %q", errs)) } retryCountReturn := resp.Header.Get("Retry-Count") if retryCountReturn != retry_count_expected { - t.Errorf("Expected [%s] retry but was [%s]", retry_count_expected, retryCountReturn) + t.Error(fmt.Sprintf("Expected [%s] retry but was [%s]", retry_count_expected, retryCountReturn)) } resp, _, errs = New().Get(ts.URL+case24_after_3_attempt_return_valid). Retry(4, 1*time.Nanosecond, http.StatusBadRequest). End() if errs != nil { - t.Errorf("No testing for this case yet : %q", errs) + t.Error(fmt.Sprintf("No testing for this case yet : %q", errs)) } retryCountReturn = resp.Header.Get("Retry-Count") if retryCountReturn != retry_count_expected { - t.Errorf("Expected [%s] retry but was [%s]", retry_count_expected, retryCountReturn) + t.Error(fmt.Sprintf("Expected [%s] retry but was [%s]", retry_count_expected, retryCountReturn)) } } @@ -612,7 +613,7 @@ func TestOptions(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is OPTIONS before going to check other features if r.Method != OPTIONS { - t.Errorf("Expected method %q; got %q", OPTIONS, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", OPTIONS, r.Method)) } t.Log("test Options") w.Header().Set("Allow", "HEAD, GET") @@ -647,11 +648,11 @@ func TestParam(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Form.Get("code") != paramCode { - t.Errorf("Expected 'code' == %s; got %v", paramCode, r.Form.Get("code")) + t.Error(fmt.Sprintf("Expected 'code' == %s; got %v", paramCode, r.Form.Get("code"))) } if r.Form.Get("fields") != paramFields { - t.Errorf("Expected 'fields' == %s; got %v", paramFields, r.Form.Get("fields")) + t.Error(fmt.Sprintf("Expected 'fields' == %s; got %v", paramFields, r.Form.Get("fields"))) } })) @@ -697,53 +698,53 @@ func testPostServer(t *testing.T) *httptest.Server { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is POST before going to check other features if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case test_post_case1_empty: t.Logf("case %v ", test_post_case1_empty) case test_post_case2_set_header: t.Logf("case %v ", test_post_case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key"))) } case test_post_case3_send_json: t.Logf("case %v ", test_post_case3_send_json) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != `{"query1":"test","query2":"test"}` { - t.Error(`Expected Body with {"query1":"test","query2":"test"}`, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected Body with {"query1":"test","query2":"test"} | but got %s`, string(body))) } case test_post_case4_send_string, test_post_case11_send_string_pointer: t.Logf("case %v ", r.URL.Path) if r.Header.Get("Content-Type") != "application/x-www-form-urlencoded" { - t.Error("Expected Header Content-Type -> application/x-www-form-urlencoded", "| but got", r.Header.Get("Content-Type")) + t.Error(fmt.Sprintf("Expected Header Content-Type -> application/x-www-form-urlencoded | but got %s", r.Header.Get("Content-Type"))) } defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "query1=test&query2=test" { - t.Error("Expected Body with \"query1=test&query2=test\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"query1=test&query2=test\" | but got %s", string(body))) } case test_post_case5_integration_send_json_string: t.Logf("case %v ", test_post_case5_integration_send_json_string) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "query1=test&query2=test" { - t.Error("Expected Body with \"query1=test&query2=test\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"query1=test&query2=test\" | but got %s", string(body))) } case test_post_case6_set_query: t.Logf("case %v ", test_post_case6_set_query) v := r.URL.Query() if v["query1"][0] != "test" { - t.Error("Expected query1:test", "| but got", v["query1"][0]) + t.Error(fmt.Sprintf("Expected query1:test | but got %s", v["query1"][0])) } if v["query2"][0] != "test" { - t.Error("Expected query2:test", "| but got", v["query2"][0]) + t.Error(fmt.Sprintf("Expected query2:test | but got %s", v["query2"][0])) } case test_post_case7_integration_send_json_struct: t.Logf("case %v ", test_post_case7_integration_send_json_struct) @@ -751,21 +752,21 @@ func testPostServer(t *testing.T) *httptest.Server { body, _ := ioutil.ReadAll(r.Body) comparedBody := []byte(`{"Lower":{"Color":"green","Size":1.7},"Upper":{"Color":"red","Size":0},"a":"a","name":"Cindy"}`) if !bytes.Equal(body, comparedBody) { - t.Errorf(`Expected correct json but got ` + string(body)) + t.Error(fmt.Sprintf(`Expected correct json but got %s`, string(body))) } case test_post_case8_send_json_with_long_id_number: t.Logf("case %v ", test_post_case8_send_json_with_long_id_number) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != `{"id":123456789,"name":"nemo"}` { - t.Error(`Expected Body with {"id":123456789,"name":"nemo"}`, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected Body with {"id":123456789,"name":"nemo"} | but got %s`, string(body))) } case test_post_case9_send_json_string_with_long_id_number_as_form_result: t.Logf("case %v ", test_post_case9_send_json_string_with_long_id_number_as_form_result) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != `id=123456789&name=nemo` { - t.Error(`Expected Body with "id=123456789&name=nemo"`, `| but got`, string(body)) + t.Error(fmt.Sprintf(`Expected Body with "id=123456789&name=nemo" | but got %s`, string(body))) } case test_post_case19_send_struct, test_post_case10_send_struct_pointer: t.Logf("case %v ", r.URL.Path) @@ -773,7 +774,7 @@ func testPostServer(t *testing.T) *httptest.Server { body, _ := ioutil.ReadAll(r.Body) comparedBody := []byte(`{"Bfalse":false,"BoolArray":[true,false],"Btrue":true,"Float":12.345,"FloatArray":[1.23,4.56,7.89],"Int":42,"IntArray":[1,2],"String":"a string","StringArray":["string1","string2"]}`) if !bytes.Equal(body, comparedBody) { - t.Errorf(`Expected correct json but got ` + string(body)) + t.Error(fmt.Sprintf(`Expected correct json but got %s`, string(body))) } case test_post_case12_send_slice_string, test_post_case13_send_slice_string_pointer, test_post_case17_send_string_array, test_post_case18_send_string_array_pointer: t.Logf("case %v ", r.URL.Path) @@ -781,35 +782,35 @@ func testPostServer(t *testing.T) *httptest.Server { body, _ := ioutil.ReadAll(r.Body) comparedBody := []byte(`["string1","string2"]`) if !bytes.Equal(body, comparedBody) { - t.Errorf(`Expected correct json but got ` + string(body)) + t.Error(fmt.Sprintf(`Expected correct json but got %s`, string(body))) } case test_post_case14_send_int_pointer: t.Logf("case %v ", test_post_case14_send_int_pointer) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "42" { - t.Error("Expected Body with \"42\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"42\" | but got %s", string(body))) } case test_post_case15_send_float_pointer: t.Logf("case %v ", test_post_case15_send_float_pointer) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "12.345" { - t.Error("Expected Body with \"12.345\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"12.345\" | but got %s", string(body))) } case test_post_case16_send_bool_pointer: t.Logf("case %v ", test_post_case16_send_bool_pointer) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "true" { - t.Error("Expected Body with \"true\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"true\" | but got %s", string(body))) } case test_post_case20_send_byte_char, test_post_case21_send_byte_char_pointer, test_post_case22_send_byte_int, test_post_case22_send_byte_int_pointer: t.Logf("case %v ", r.URL.Path) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != "71" { - t.Error("Expected Body with \"71\"", "| but got", string(body)) + t.Error(fmt.Sprintf("Expected Body with \"71\" | but got %s", string(body))) } case test_post_case23_send_duplicate_query_params: t.Logf("case %v ", test_post_case23_send_duplicate_query_params) @@ -817,14 +818,14 @@ func testPostServer(t *testing.T) *httptest.Server { body, _ := ioutil.ReadAll(r.Body) sbody := string(body) if sbody != "param=4¶m=3¶m=2¶m=1" { - t.Error("Expected Body \"param=4¶m=3¶m=2¶m=1\"", "| but got", sbody) + t.Error(fmt.Sprintf("Expected Body \"param=4¶m=3¶m=2¶m=1\" | but got %s", sbody)) } values, _ := url.ParseQuery(sbody) if len(values["param"]) != 4 { - t.Error("Expected Body with 4 params", "| but got", sbody) + t.Error(fmt.Sprintf("Expected Body with 4 params | but got %s", sbody)) } if values["param"][0] != "4" || values["param"][1] != "3" || values["param"][2] != "2" || values["param"][3] != "1" { - t.Error("Expected Body with 4 params and values", "| but got", sbody) + t.Error(fmt.Sprintf("Expected Body with 4 params and values | but got %s", sbody)) } case test_post_case24_send_query_and_request_body: t.Logf("case %v ", test_post_case24_send_query_and_request_body) @@ -832,12 +833,12 @@ func testPostServer(t *testing.T) *httptest.Server { body, _ := ioutil.ReadAll(r.Body) sbody := string(body) if sbody != `{"name":"jkbbwr"}` { - t.Error(`Expected Body "{"name":"jkbbwr"}"`, "| but got", sbody) + t.Error(fmt.Sprintf(`Expected Body "{\"name\":\"jkbbwr\"}" | but got %s`, sbody)) } v := r.URL.Query() if v["test"][0] != "true" { - t.Error("Expected test:true", "| but got", v["test"][0]) + t.Error(fmt.Sprintf("Expected test:true | but got %s", v["test"][0])) } } })) @@ -848,6 +849,12 @@ func TestPost(t *testing.T) { ts := testPostServer(t) defer ts.Close() + // Add a test case for multiple Host headers + New().Post(ts.URL + test_post_case1_empty). + Set("Host", "bad.host"). + Set("Host", "good.host"). + End() + New().Post(ts.URL + test_post_case1_empty). End() @@ -1180,7 +1187,7 @@ func checkFile(t *testing.T, fileheader *multipart.FileHeader) { t.Error(err) } if len(b) == 0 { - t.Error("Expected file-content > 0", "| but got", len(b), string(b)) + t.Error(fmt.Sprintf("Expected file-content > 0 | but got %d %s", len(b), string(b))) } } @@ -1225,319 +1232,330 @@ func TestMultipartRequest(t *testing.T) { const case25_send_file_with_name_with_spaces_only = "/send_file_with_name_with_spaces_only" const case26_send_file_with_fieldname_with_spaces = "/send_file_with_fieldname_with_spaces" const case27_send_file_with_fieldname_with_spaces_only = "/send_file_with_fieldname_with_spaces_only" + const case28_send_file_with_file_as_fieldname_and_skip_file_numbering_true = "/send_file_with_file_as_fieldname_and_skip_file_numbering_true" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is POST before going to check other features if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %s", POST, r.Method)) } if !strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") { - t.Error("Expected Header Content-Type -> multipart/form-data", "| but got", r.Header.Get("Content-Type")) + t.Error(fmt.Sprintf("Expected Header Content-Type -> multipart/form-data | but got %s", r.Header.Get("Content-Type"))) } const _24K = (1 << 20) * 24 err := r.ParseMultipartForm(_24K) if err != nil { - t.Errorf("Error: %v", err) + t.Error(fmt.Sprintf("Error: %v", err)) } t.Logf("case %v ", r.URL.Path) switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) case case0_send_not_supported_filetype: // will be handled at place case case1_send_string, case2_send_json, case3_integration_send_json_string: if len(r.MultipartForm.Value["query1"]) != 1 { - t.Error("Expected length of query1:test == 1", "| but got", len(r.MultipartForm.Value["query1"])) + t.Error(fmt.Sprintf("Expected length of query1:test == 1 | but got %d", len(r.MultipartForm.Value["query1"]))) } if r.MultipartForm.Value["query1"][0] != "test" { - t.Error("Expected query1:test", "| but got", r.MultipartForm.Value["query1"][0]) + t.Error(fmt.Sprintf("Expected query1:test | but got %s", r.MultipartForm.Value["query1"][0])) } if len(r.MultipartForm.Value["query2"]) != 1 { - t.Error("Expected length of query2:test == 1", "| but got", len(r.MultipartForm.Value["query2"])) + t.Error(fmt.Sprintf("Expected length of query2:test == 1 | but got %d", len(r.MultipartForm.Value["query2"]))) } if r.MultipartForm.Value["query2"][0] != "test" { - t.Error("Expected query2:test", "| but got", r.MultipartForm.Value["query2"][0]) + t.Error(fmt.Sprintf("Expected query2:test | but got %s", r.MultipartForm.Value["query2"][0])) } case case4_set_query: v := r.URL.Query() if v["query1"][0] != "test" { - t.Error("Expected query1:test", "| but got", v["query1"][0]) + t.Error(fmt.Sprintf("Expected query1:test | but got %s", v["query1"][0])) } if v["query2"][0] != "test" { - t.Error("Expected query2:test", "| but got", v["query2"][0]) + t.Error(fmt.Sprintf("Expected query2:test | but got %s", v["query2"][0])) } if val, ok := r.MultipartForm.Value["query1"]; ok { - t.Error("Expected no value", "| but got", val) + t.Error(fmt.Sprintf("Expected no value | but got %v", val)) } if val, ok := r.MultipartForm.Value["query2"]; ok { - t.Error("Expected no value", "| but got", val) + t.Error(fmt.Sprintf("Expected no value | but got %v", val)) } case case5_send_struct: if r.MultipartForm.Value["String"][0] != "a string" { - t.Error("Expected String:'a string'", "| but got", r.MultipartForm.Value["String"][0]) + t.Error(fmt.Sprintf("Expected String:'a string' | but got %s", r.MultipartForm.Value["String"][0])) } if r.MultipartForm.Value["Int"][0] != "42" { - t.Error("Expected Int:42", "| but got", r.MultipartForm.Value["Int"][0]) + t.Error(fmt.Sprintf("Expected Int:42 | but got %s", r.MultipartForm.Value["Int"][0])) } if r.MultipartForm.Value["Btrue"][0] != "true" { - t.Error("Expected Btrue:true", "| but got", r.MultipartForm.Value["Btrue"][0]) + t.Error(fmt.Sprintf("Expected Btrue:true | but got %s", r.MultipartForm.Value["Btrue"][0])) } if r.MultipartForm.Value["Bfalse"][0] != "false" { - t.Error("Expected Btrue:false", "| but got", r.MultipartForm.Value["Bfalse"][0]) + t.Error(fmt.Sprintf("Expected Btrue:false | but got %s", r.MultipartForm.Value["Bfalse"][0])) } if r.MultipartForm.Value["Float"][0] != "12.345" { - t.Error("Expected Float:12.345", "| but got", r.MultipartForm.Value["Float"][0]) + t.Error(fmt.Sprintf("Expected Float:12.345 | but got %s", r.MultipartForm.Value["Float"][0])) } if len(r.MultipartForm.Value["StringArray"]) != 2 { - t.Error("Expected length of StringArray:2", "| but got", len(r.MultipartForm.Value["StringArray"])) + t.Error(fmt.Sprintf("Expected length of StringArray:2 | but got %d", len(r.MultipartForm.Value["StringArray"]))) } if r.MultipartForm.Value["StringArray"][0] != "string1" { - t.Error("Expected StringArray:string1", "| but got", r.MultipartForm.Value["StringArray"][0]) + t.Error(fmt.Sprintf("Expected StringArray:string1 | but got %s", r.MultipartForm.Value["StringArray"][0])) } if r.MultipartForm.Value["StringArray"][1] != "string2" { - t.Error("Expected StringArray:string2", "| but got", r.MultipartForm.Value["StringArray"][1]) + t.Error(fmt.Sprintf("Expected StringArray:string2 | but got %s", r.MultipartForm.Value["StringArray"][1])) } if len(r.MultipartForm.Value["IntArray"]) != 2 { - t.Error("Expected length of IntArray:2", "| but got", len(r.MultipartForm.Value["IntArray"])) + t.Error(fmt.Sprintf("Expected length of IntArray:2 | but got %d", len(r.MultipartForm.Value["IntArray"]))) } if r.MultipartForm.Value["IntArray"][0] != "1" { - t.Error("Expected IntArray:1", "| but got", r.MultipartForm.Value["IntArray"][0]) + t.Error(fmt.Sprintf("Expected IntArray:1 | but got %s", r.MultipartForm.Value["IntArray"][0])) } if r.MultipartForm.Value["IntArray"][1] != "2" { - t.Error("Expected IntArray:2", "| but got", r.MultipartForm.Value["IntArray"][1]) + t.Error(fmt.Sprintf("Expected IntArray:2 | but got %s", r.MultipartForm.Value["IntArray"][1])) } if len(r.MultipartForm.Value["BoolArray"]) != 2 { - t.Error("Expected length of BoolArray:2", "| but got", len(r.MultipartForm.Value["BoolArray"])) + t.Error(fmt.Sprintf("Expected length of BoolArray:2 | but got %d", len(r.MultipartForm.Value["BoolArray"]))) } if r.MultipartForm.Value["BoolArray"][0] != "true" { - t.Error("Expected BoolArray:true", "| but got", r.MultipartForm.Value["BoolArray"][0]) + t.Error(fmt.Sprintf("Expected BoolArray:true | but got %s", r.MultipartForm.Value["BoolArray"][0])) } if r.MultipartForm.Value["BoolArray"][1] != "false" { - t.Error("Expected BoolArray:false", "| but got", r.MultipartForm.Value["BoolArray"][1]) + t.Error(fmt.Sprintf("Expected BoolArray:false | but got %s", r.MultipartForm.Value["BoolArray"][1])) } if len(r.MultipartForm.Value["FloatArray"]) != 3 { - t.Error("Expected length of FloatArray:3", "| but got", len(r.MultipartForm.Value["FloatArray"])) + t.Error(fmt.Sprintf("Expected length of FloatArray:3 | but got %d", len(r.MultipartForm.Value["FloatArray"]))) } if r.MultipartForm.Value["FloatArray"][0] != "1.23" { - t.Error("Expected FloatArray:1.23", "| but got", r.MultipartForm.Value["FloatArray"][0]) + t.Error(fmt.Sprintf("Expected FloatArray:1.23 | but got %s", r.MultipartForm.Value["FloatArray"][0])) } if r.MultipartForm.Value["FloatArray"][1] != "4.56" { - t.Error("Expected FloatArray:4.56", "| but got", r.MultipartForm.Value["FloatArray"][1]) + t.Error(fmt.Sprintf("Expected FloatArray:4.56 | but got %s", r.MultipartForm.Value["FloatArray"][1])) } if r.MultipartForm.Value["FloatArray"][2] != "7.89" { - t.Error("Expected FloatArray:7.89", "| but got", r.MultipartForm.Value["FloatArray"][2]) + t.Error(fmt.Sprintf("Expected FloatArray:7.89 | but got %s", r.MultipartForm.Value["FloatArray"][2])) } case case6_send_slice_string, case7_send_array: if len(r.MultipartForm.Value["data"]) != 1 { - t.Error("Expected length of data:JSON == 1", "| but got", len(r.MultipartForm.Value["data"])) + t.Error(fmt.Sprintf("Expected length of data:JSON == 1 | but got %d", len(r.MultipartForm.Value["data"]))) } if r.MultipartForm.Value["data"][0] != `["string1","string2"]` { - t.Error(`Expected 'data' with ["string1","string2"]`, "| but got", r.MultipartForm.Value["data"][0]) + t.Error(fmt.Sprintf(`Expected 'data' with ["string1","string2"] | but got %s`, r.MultipartForm.Value["data"][0])) } case case6_send_slice_string_with_custom_fieldname: if len(r.MultipartForm.Value["my_custom_data"]) != 1 { - t.Error("Expected length of my_custom_data:JSON == 1", "| but got", len(r.MultipartForm.Value["my_custom_data"])) + t.Error(fmt.Sprintf("Expected length of my_custom_data:JSON == 1 | but got %d", len(r.MultipartForm.Value["my_custom_data"]))) } if r.MultipartForm.Value["my_custom_data"][0] != `["string1","string2"]` { - t.Error(`Expected 'my_custom_data' with ["string1","string2"]`, "| but got", r.MultipartForm.Value["my_custom_data"][0]) + t.Error(fmt.Sprintf(`Expected 'my_custom_data' with ["string1","string2"] | but got %s`, r.MultipartForm.Value["my_custom_data"][0])) } case case8_integration_send_json_struct: if len(r.MultipartForm.Value["query1"]) != 1 { - t.Error("Expected length of query1:test == 1", "| but got", len(r.MultipartForm.Value["query1"])) + t.Error(fmt.Sprintf("Expected length of query1:test == 1 | but got %d", len(r.MultipartForm.Value["query1"]))) } if r.MultipartForm.Value["query1"][0] != "test" { - t.Error("Expected query1:test", "| but got", r.MultipartForm.Value["query1"][0]) + t.Error(fmt.Sprintf("Expected query1:test | but got %s", r.MultipartForm.Value["query1"][0])) } if r.MultipartForm.Value["hey"][0] != "hey" { - t.Error("Expected hey:'hey'", "| but got", r.MultipartForm.Value["Hey"][0]) + t.Error(fmt.Sprintf("Expected hey:'hey' | but got %s", r.MultipartForm.Value["Hey"][0])) } case case9_send_duplicate_query_params: if len(r.MultipartForm.Value["param"]) != 4 { - t.Error("Expected length of param:[] == 4", "| but got", len(r.MultipartForm.Value["param"])) + t.Error(fmt.Sprintf("Expected length of param:[] == 4 | but got %d", len(r.MultipartForm.Value["param"]))) } if r.MultipartForm.Value["param"][0] != "4" { - t.Error("Expected param:0:4", "| but got", r.MultipartForm.Value["param"][0]) + t.Error(fmt.Sprintf("Expected param:0:4 | but got %s", r.MultipartForm.Value["param"][0])) } if r.MultipartForm.Value["param"][1] != "3" { - t.Error("Expected param:1:3", "| but got", r.MultipartForm.Value["param"][1]) + t.Error(fmt.Sprintf("Expected param:1:3 | but got %s", r.MultipartForm.Value["param"][1])) } if r.MultipartForm.Value["param"][2] != "2" { - t.Error("Expected param:2:2", "| but got", r.MultipartForm.Value["param"][2]) + t.Error(fmt.Sprintf("Expected param:2:2 | but got %s", r.MultipartForm.Value["param"][2])) } if r.MultipartForm.Value["param"][3] != "1" { - t.Error("Expected param:3:1", "| but got", r.MultipartForm.Value["param"][3]) + t.Error(fmt.Sprintf("Expected param:3:1 | but got %s", r.MultipartForm.Value["param"][3])) } case case10_send_file_by_path, case11_send_file_by_path_without_name, case14_send_file_by_content_with_name, case20_send_file_as_osfile: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if r.MultipartForm.File["file1"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file1"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file1"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file1"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["file1"][0]) case case10a_send_file_by_path_with_name, case10b_send_file_by_path_pointer, case21_send_file_as_osfile_with_name: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if r.MultipartForm.File["file1"][0].Filename != "MY_LICENSE" { - t.Error("Expected Filename:MY_LICENSE", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:MY_LICENSE | but got %s", r.MultipartForm.File["file1"][0].Filename)) } case case12_send_file_by_path_without_name_but_with_fieldname: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if _, ok := r.MultipartForm.File["my_fieldname"]; !ok { keys := reflect.ValueOf(r.MultipartForm.File).MapKeys() - t.Error("Expected Fieldname:my_fieldname", "| but got", keys) + t.Error(fmt.Sprintf("Expected Fieldname:my_fieldname | but got %v", keys)) } if r.MultipartForm.File["my_fieldname"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["my_fieldname"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["my_fieldname"][0].Filename)) } if r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["my_fieldname"][0]) case case13_send_file_by_content_without_name, case13a_send_file_by_content_without_name_pointer: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if r.MultipartForm.File["file1"][0].Filename != "filename" { - t.Error("Expected Filename:filename", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:filename | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file1"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file1"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file1"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["file1"][0]) case case15_send_file_by_content_without_name_but_with_fieldname: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if _, ok := r.MultipartForm.File["my_fieldname"]; !ok { keys := reflect.ValueOf(r.MultipartForm.File).MapKeys() - t.Error("Expected Fieldname:my_fieldname", "| but got", keys) + t.Error(fmt.Sprintf("Expected Fieldname:my_fieldname | but got %v", keys)) } if r.MultipartForm.File["my_fieldname"][0].Filename != "filename" { - t.Error("Expected Filename:filename", "| but got", r.MultipartForm.File["my_fieldname"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:filename | but got %s", r.MultipartForm.File["my_fieldname"][0].Filename)) } if r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["my_fieldname"][0]) case case16_send_file_by_content_with_name_and_with_fieldname, case22_send_file_as_osfile_with_name_and_with_fieldname: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if _, ok := r.MultipartForm.File["my_fieldname"]; !ok { keys := reflect.ValueOf(r.MultipartForm.File).MapKeys() - t.Error("Expected Fieldname:my_fieldname", "| but got", keys) + t.Error(fmt.Sprintf("Expected Fieldname:my_fieldname | but got %v", keys)) } if r.MultipartForm.File["my_fieldname"][0].Filename != "MY_LICENSE" { - t.Error("Expected Filename:MY_LICENSE", "| but got", r.MultipartForm.File["my_fieldname"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:MY_LICENSE | but got %s", r.MultipartForm.File["my_fieldname"][0].Filename)) } if r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["my_fieldname"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["my_fieldname"][0]) case case17_send_file_multiple_by_path_and_content_without_name: if len(r.MultipartForm.File) != 2 { - t.Error("Expected length of files:[] == 2", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 2 | but got %d", len(r.MultipartForm.File))) } // depends on map iteration order if r.MultipartForm.File["file1"][0].Filename != "LICENSE" && r.MultipartForm.File["file1"][0].Filename != "filename" { - t.Error("Expected Filename:LICENSE||filename", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE||filename | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file1"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file1"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file1"][0].Header["Content-Type"])) } // depends on map iteration order if r.MultipartForm.File["file2"][0].Filename != "LICENSE" && r.MultipartForm.File["file2"][0].Filename != "filename" { - t.Error("Expected Filename:LICENSE||filename", "| but got", r.MultipartForm.File["file2"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE||filename | but got %s", r.MultipartForm.File["file2"][0].Filename)) } if r.MultipartForm.File["file2"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file2"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file2"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["file1"][0]) checkFile(t, r.MultipartForm.File["file2"][0]) case case18_send_file_multiple_by_path_and_content_with_name: if len(r.MultipartForm.File) != 2 { - t.Error("Expected length of files:[] == 2", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 2 | but got %d", len(r.MultipartForm.File))) } // depends on map iteration order if r.MultipartForm.File["file1"][0].Filename != "LICENSE" && r.MultipartForm.File["file1"][0].Filename != "MY_LICENSE" { - t.Error("Expected Filename:LICENSE||MY_LICENSE", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE||MY_LICENSE | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file1"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file1"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file1"][0].Header["Content-Type"])) } // depends on map iteration order if r.MultipartForm.File["file2"][0].Filename != "LICENSE" && r.MultipartForm.File["file2"][0].Filename != "MY_LICENSE" { - t.Error("Expected Filename:LICENSE||MY_LICENSE", "| but got", r.MultipartForm.File["file2"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE||MY_LICENSE | but got %s", r.MultipartForm.File["file2"][0].Filename)) } if r.MultipartForm.File["file2"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file2"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file2"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["file1"][0]) checkFile(t, r.MultipartForm.File["file2"][0]) case case19_integration_send_file_and_data: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if r.MultipartForm.File["file1"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file1"][0].Header["Content-Type"][0] != "application/octet-stream" { - t.Error("Expected Header:Content-Type:application/octet-stream", "| but got", r.MultipartForm.File["file1"][0].Header["Content-Type"]) + t.Error(fmt.Sprintf("Expected Header:Content-Type:application/octet-stream | but got %v", r.MultipartForm.File["file1"][0].Header["Content-Type"])) } checkFile(t, r.MultipartForm.File["file1"][0]) if len(r.MultipartForm.Value["query1"]) != 1 { - t.Error("Expected length of query1:test == 1", "| but got", len(r.MultipartForm.Value["query1"])) + t.Error(fmt.Sprintf("Expected length of query1:test == 1 | but got %d", len(r.MultipartForm.Value["query1"]))) } if r.MultipartForm.Value["query1"][0] != "test" { - t.Error("Expected query1:test", "| but got", r.MultipartForm.Value["query1"][0]) + t.Error(fmt.Sprintf("Expected query1:test | but got %s", r.MultipartForm.Value["query1"][0])) } case case23_send_file_with_file_as_fieldname: if len(r.MultipartForm.File) != 2 { - t.Error("Expected length of files:[] == 2", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 2 | but got %d", len(r.MultipartForm.File))) } if val, ok := r.MultipartForm.File["file1"]; !ok { - t.Error("Expected file with key: file1", "| but got ", val) + t.Error(fmt.Sprintf("Expected file with key: file1 | but got %v", val)) } if val, ok := r.MultipartForm.File["file2"]; !ok { - t.Error("Expected file with key: file2", "| but got ", val) + t.Error(fmt.Sprintf("Expected file with key: file2 | but got %v", val)) } if r.MultipartForm.File["file1"][0].Filename != "b.file" { - t.Error("Expected Filename:b.file", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:b.file | but got %s", r.MultipartForm.File["file1"][0].Filename)) } if r.MultipartForm.File["file2"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["file2"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["file2"][0].Filename)) } checkFile(t, r.MultipartForm.File["file1"][0]) checkFile(t, r.MultipartForm.File["file2"][0]) case case24_send_file_with_name_with_spaces, case25_send_file_with_name_with_spaces_only, case27_send_file_with_fieldname_with_spaces_only: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if val, ok := r.MultipartForm.File["file1"]; !ok { - t.Error("Expected file with key: file1", "| but got ", val) + t.Error(fmt.Sprintf("Expected file with key: file1 | but got %v", val)) } if r.MultipartForm.File["file1"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["file1"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["file1"][0].Filename)) } checkFile(t, r.MultipartForm.File["file1"][0]) case case26_send_file_with_fieldname_with_spaces: if len(r.MultipartForm.File) != 1 { - t.Error("Expected length of files:[] == 1", "| but got", len(r.MultipartForm.File)) + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) } if val, ok := r.MultipartForm.File["my_fieldname"]; !ok { - t.Error("Expected file with key: my_fieldname", "| but got ", val) + t.Error(fmt.Sprintf("Expected file with key: my_fieldname | but got %v", val)) } if r.MultipartForm.File["my_fieldname"][0].Filename != "LICENSE" { - t.Error("Expected Filename:LICENSE", "| but got", r.MultipartForm.File["my_fieldname"][0].Filename) + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["my_fieldname"][0].Filename)) } checkFile(t, r.MultipartForm.File["my_fieldname"][0]) + case case28_send_file_with_file_as_fieldname_and_skip_file_numbering_true: + if len(r.MultipartForm.File) != 1 { + t.Error(fmt.Sprintf("Expected length of files:[] == 1 | but got %d", len(r.MultipartForm.File))) + } + if val, ok := r.MultipartForm.File["file"]; !ok { + t.Error(fmt.Sprintf("Expected file with key: file | but got %v", val)) + } + if r.MultipartForm.File["file"][0].Filename != "LICENSE" { + t.Error(fmt.Sprintf("Expected Filename:LICENSE | but got %s", r.MultipartForm.File["file"][0].Filename)) + } } })) @@ -1551,7 +1569,7 @@ func TestMultipartRequest(t *testing.T) { End() if len(errs) == 0 { - t.Errorf("Expected error, but got nothing: %v", errs) + t.Error(fmt.Sprintf("Expected error, but got nothing: %v", errs)) } New().Post(ts.URL + case1_send_string). @@ -1736,6 +1754,11 @@ func TestMultipartRequest(t *testing.T) { Type("multipart"). SendFile(osFile, "", " "). End() + + New().Post(ts.URL+case28_send_file_with_file_as_fieldname_and_skip_file_numbering_true). + Type("multipart"). + SendFile(osFile, "", "file", true). + End() } // testing for Patch method @@ -1746,27 +1769,27 @@ func TestPatch(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is PATCH before going to check other features if r.Method != PATCH { - t.Errorf("Expected method %q; got %q", PATCH, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %s", PATCH, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) + t.Error(fmt.Sprintf("No testing for this case yet : %s", r.URL.Path)) case case1_empty: t.Logf("case %v ", case1_empty) case case2_set_header: t.Logf("case %v ", case2_set_header) if r.Header.Get("API-Key") != "fookey" { - t.Errorf("Expected 'API-Key' == %q; got %q", "fookey", r.Header.Get("API-Key")) + t.Error(fmt.Sprintf("Expected 'API-Key' == %q; got %s", "fookey", r.Header.Get("API-Key"))) } case case3_send_json: t.Logf("case %v ", case3_send_json) defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != `{"query1":"test","query2":"test"}` { - t.Error(`Expected Body with {"query1":"test","query2":"test"}`, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected Body with {"query1":"test","query2":"test"} | but got %s`, string(body))) } } })) @@ -1793,7 +1816,7 @@ func checkQuery(t *testing.T, q map[string][]string, key string, want string) { } else if len(v) < 1 { t.Error("No values for", key) } else if v[0] != want { - t.Errorf("Expected %v:%v | but got %v", key, want, v[0]) + t.Error(fmt.Sprintf("Expected %v:%v | but got %v", key, want, v[0])) } return } @@ -1806,28 +1829,36 @@ func TestQueryFunc(t *testing.T) { const case4_send_map = "/send_map" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } - v := r.URL.Query() + if err := r.ParseForm(); err != nil { + t.Fatal(fmt.Sprintf("Failed to parse form: %v", err)) + } + v := r.Form + t.Logf("TestQueryFunc: Path=%s, RawQuery=%s, Form=%v", r.URL.Path, r.URL.RawQuery, r.Form) + switch r.URL.Path { default: - t.Errorf("No testing for this case yet : %q", r.URL.Path) - case case1_send_string, case2_send_struct: + t.Error(fmt.Sprintf("No testing for this case yet : %q", r.URL.Path)) + case case1_send_string: checkQuery(t, v, "query1", "test1") checkQuery(t, v, "query2", "test2") + case case2_send_struct: + checkQuery(t, v, "Query1", "test1") // Changed to uppercase "Query1" + checkQuery(t, v, "Query2", "test2") // Changed to uppercase "Query2" case case3_send_string_with_duplicates: checkQuery(t, v, "query1", "test1") checkQuery(t, v, "query2", "test2") if len(v["param"]) != 4 { - t.Errorf("Expected Body with 4 params | but got %q", len(v["param"])) + t.Error(fmt.Sprintf("Expected Body with 4 params | but got %d", len(v["param"]))) } if v["param"][0] != "1" || v["param"][1] != "2" || v["param"][2] != "3" || v["param"][3] != "4" { - t.Error("Expected Body with 4 params and values", "| but got", r.URL.RawQuery) + t.Error(fmt.Sprintf("Expected Body with 4 params and values | but got %s", r.Form.Encode())) } case case4_send_map: checkQuery(t, v, "query1", "test1") @@ -1911,23 +1942,23 @@ func TestEndBytes(t *testing.T) { { resp, bodyBytes, errs := New().Get(ts.URL).EndBytes(func(resp Response, body []byte, errs []error) { if len(errs) > 0 { - t.Fatalf("Unexpected errors: %s", errs) + t.Fatal(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Fatalf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Fatal(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if string(body) != serverOutput { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(body)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(body))) } }) if len(errs) > 0 { - t.Fatalf("Unexpected errors: %s", errs) + t.Fatal(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Fatalf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Fatal(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if string(bodyBytes) != serverOutput { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes))) } } @@ -1935,13 +1966,13 @@ func TestEndBytes(t *testing.T) { { resp, bodyBytes, errs := New().Get(ts.URL).EndBytes() if len(errs) > 0 { - t.Errorf("Unexpected errors: %s", errs) + t.Error(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Errorf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Error(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if string(bodyBytes) != serverOutput { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes))) } } } @@ -1951,7 +1982,7 @@ func TestEndStruct(t *testing.T) { expStruct := heyYou{Hey: "you"} serverOutput, err := json.Marshal(expStruct) if err != nil { - t.Errorf("Unexpected errors: %s", err) + t.Error(fmt.Sprintf("Unexpected errors: %s", err)) } ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) @@ -1963,27 +1994,27 @@ func TestEndStruct(t *testing.T) { { resp, bodyBytes, errs := New().Get(ts.URL).EndStruct(func(resp Response, v interface{}, body []byte, errs []error) { if len(errs) > 0 { - t.Fatalf("Unexpected errors: %s", errs) + t.Fatal(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Fatalf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Fatal(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if !reflect.DeepEqual(expStruct, resStruct) { resBytes, _ := json.Marshal(resStruct) - t.Errorf("Expected body=%s, actual bodyBytes=%s", serverOutput, string(resBytes)) + t.Error(fmt.Sprintf("Expected body=%s, actual bodyBytes=%s", serverOutput, string(resBytes))) } if !reflect.DeepEqual(body, serverOutput) { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(body)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(body))) } }) if len(errs) > 0 { - t.Fatalf("Unexpected errors: %s", errs) + t.Fatal(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Fatalf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Fatal(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if !reflect.DeepEqual(bodyBytes, serverOutput) { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes))) } } @@ -1991,17 +2022,17 @@ func TestEndStruct(t *testing.T) { { resp, bodyBytes, errs := New().Get(ts.URL).EndStruct(&resStruct) if len(errs) > 0 { - t.Errorf("Unexpected errors: %s", errs) + t.Error(fmt.Sprintf("Unexpected errors: %s", errs)) } if resp.StatusCode != 200 { - t.Errorf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode) + t.Error(fmt.Sprintf("Expected StatusCode=200, actual StatusCode=%v", resp.StatusCode)) } if !reflect.DeepEqual(expStruct, resStruct) { resBytes, _ := json.Marshal(resStruct) - t.Errorf("Expected body=%s, actual bodyBytes=%s", serverOutput, string(resBytes)) + t.Error(fmt.Sprintf("Expected body=%s, actual bodyBytes=%s", serverOutput, string(resBytes))) } if !reflect.DeepEqual(bodyBytes, serverOutput) { - t.Errorf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes)) + t.Error(fmt.Sprintf("Expected bodyBytes=%s, actual bodyBytes=%s", serverOutput, string(bodyBytes))) } } } @@ -2088,7 +2119,7 @@ func TestTimeoutFunc(t *testing.T) { t.Error("Expected dial timeout error but get nothing") } if elapsedTime < 1000*time.Millisecond || elapsedTime > 1500*time.Millisecond { - t.Errorf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime) + t.Error(fmt.Sprintf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime)) } // 2st case, read/write timeout (Can dial to url but want to timeout because too long operation on the server) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -2103,7 +2134,7 @@ func TestTimeoutFunc(t *testing.T) { t.Error("Expected dial+read/write timeout | but get nothing") } if elapsedTime < 1000*time.Millisecond || elapsedTime > 1500*time.Millisecond { - t.Errorf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime) + t.Error(fmt.Sprintf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime)) } // 3rd case, testing reuse of same request ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -2117,7 +2148,7 @@ func TestTimeoutFunc(t *testing.T) { t.Error("Expected dial+read/write timeout | but get nothing") } if elapsedTime < 1000*time.Millisecond || elapsedTime > 1500*time.Millisecond { - t.Errorf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime) + t.Error(fmt.Sprintf("Expected timeout in between 1000 -> 1500 ms | but got %d", elapsedTime)) } } @@ -2138,7 +2169,7 @@ func TestCookies(t *testing.T) { func TestGetSetCookie(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } c, err := r.Cookie("API-Cookie-Name") if err != nil { @@ -2147,7 +2178,7 @@ func TestGetSetCookie(t *testing.T) { if c == nil { t.Error("Expected non-nil request Cookie 'API-Cookie-Name'") } else if c.Value != "api-cookie-value" { - t.Errorf("Expected 'API-Cookie-Name' == %q; got %q", "api-cookie-value", c.Value) + t.Error(fmt.Sprintf("Expected 'API-Cookie-Name' == %q; got %q", "api-cookie-value", c.Value)) } })) defer ts.Close() @@ -2160,7 +2191,7 @@ func TestGetSetCookie(t *testing.T) { func TestGetSetCookies(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != GET { - t.Errorf("Expected method %q; got %q", GET, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", GET, r.Method)) } c, err := r.Cookie("API-Cookie-Name1") if err != nil { @@ -2169,7 +2200,7 @@ func TestGetSetCookies(t *testing.T) { if c == nil { t.Error("Expected non-nil request Cookie 'API-Cookie-Name1'") } else if c.Value != "api-cookie-value1" { - t.Errorf("Expected 'API-Cookie-Name1' == %q; got %q", "api-cookie-value1", c.Value) + t.Error(fmt.Sprintf("Expected 'API-Cookie-Name1' == %q; got %q", "api-cookie-value1", c.Value)) } c, err = r.Cookie("API-Cookie-Name2") if err != nil { @@ -2178,7 +2209,7 @@ func TestGetSetCookies(t *testing.T) { if c == nil { t.Error("Expected non-nil request Cookie 'API-Cookie-Name2'") } else if c.Value != "api-cookie-value2" { - t.Errorf("Expected 'API-Cookie-Name2' == %q; got %q", "api-cookie-value2", c.Value) + t.Error(fmt.Sprintf("Expected 'API-Cookie-Name2' == %q; got %q", "api-cookie-value2", c.Value)) } })) defer ts.Close() @@ -2202,7 +2233,7 @@ func TestErrorTypeWrongKey(t *testing.T) { End() if len(err) != 0 { if err[0].Error() != "Type func: incorrect type \"wrongtype\"" { - t.Errorf("Wrong error message: " + err[0].Error()) + t.Error(fmt.Sprintf("Wrong error message: %s", err[0].Error())) } } else { t.Error("Should have error") @@ -2231,7 +2262,7 @@ func TestErrorThenReUseBase(t *testing.T) { End() if len(err) != 0 { if err[0].Error() != "Type func: incorrect type \"wrongtype\"" { - t.Errorf("Wrong error message: " + err[0].Error()) + t.Error(fmt.Sprintf("Wrong error message: %s", err[0].Error())) } } else { t.Error("Should have error") @@ -2241,7 +2272,7 @@ func TestErrorThenReUseBase(t *testing.T) { Get(ts.URL). End() if len(err) != 0 { - t.Errorf("Expected No error %v", err) + t.Error(fmt.Sprintf("Expected No error %v", err)) } } @@ -2359,20 +2390,20 @@ func TestXml(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is PATCH before going to check other features if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } if r.Header.Get("Content-Type") != "application/xml" { - t.Error("Expected Header Content-Type -> application/xml", "| but got", r.Header.Get("Content-Type")) + t.Error(fmt.Sprintf("Expected Header Content-Type -> application/xml | but got %s", r.Header.Get("Content-Type"))) } defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != xml { - t.Error(`Expected XML `, xml, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected XML %s | but got %s`, xml, string(body))) } })) @@ -2395,19 +2426,19 @@ func TestPlainText(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is PATCH before going to check other features if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } if r.Header.Get("Content-Type") != "text/plain" { - t.Error("Expected Header Content-Type -> text/plain", "| but got", r.Header.Get("Content-Type")) + t.Error(fmt.Sprintf("Expected Header Content-Type -> text/plain | but got %s", r.Header.Get("Content-Type"))) } defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != text { - t.Error(`Expected text `, text, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected text %s | but got %s`, text, string(body))) } })) @@ -2424,92 +2455,55 @@ func TestPlainText(t *testing.T) { End() } -// Test for force type to plain text even the request has specific Content-Type header. -func TestForceTypeToPlainText(t *testing.T) { - text := `hello world \r\n I am GoRequest` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // check method is PATCH before going to check other features - if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) - } - if r.Header == nil { - t.Error("Expected non-nil request Header") - } - if r.Header.Get("Content-Type") != "text/plain" { - t.Error("Expected Header Content-Type -> text/plain", "| but got", r.Header.Get("Content-Type")) - } - - defer r.Body.Close() - body, _ := ioutil.ReadAll(r.Body) - if string(body) != text { - t.Error("Expected text ", text, "| but got", string(body)) - } - })) - - defer ts.Close() - - New().Post(ts.URL). - Set("Content-Type", "text/plain"). - Type("text"). - Send(text). - End() - - New().Post(ts.URL). - Set("Content-Type", "application/json"). - Type("text"). - Send(text). - End() - - New().Post(ts.URL). - Type("text"). - Set("Content-Type", "application/json"). - Send(text). - End() -} - -// Test for force type to JSON even the request has specific Content-Type header. -func TestForceTypeToJSON(t *testing.T) { - jsonData := `{"data":"hello world \r\n I am GoRequest"}` - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // check method is PATCH before going to check other features - if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) - } - if r.Header == nil { - t.Error("Expected non-nil request Header") - } - if r.Header.Get("Content-Type") != "application/json" { - t.Error("Expected Header Content-Type -> application/json", "| but got", r.Header.Get("Content-Type")) - } - - defer r.Body.Close() - body, _ := ioutil.ReadAll(r.Body) - if string(body) != jsonData { - t.Error("Expected JSON ", jsonData, "| but got", string(body)) - } - })) - - defer ts.Close() - - New().Post(ts.URL). - Set("Content-Type", "application/json"). - Type("json"). - Send(jsonData). - End() - - New().Post(ts.URL). - Set("Content-Type", "text/plain"). - Type("json"). - Send(jsonData). - End() - - New().Post(ts.URL). - Type("json"). - Set("Content-Type", "text/plain"). - Send(jsonData). - End() +// TestContentTypeInference tests that the ContentType header is set +// properly when a custom override is provided using AppendHeader +// or Set methods. +// https://github.com/parnurzeal/gorequest/issues/164 +func TestContentTypeInference(t *testing.T) { + var tests = []struct { + customContentType string + //type is reserved keyword + Type string + expectedHeader string + body string + }{ + {"application/json", "json", "application/json", "{}"}, + {"", "json", "", ""}, + {"", "json", "", "{}"}, + {"text/json", "json", "text/json", "{}"}, + {"text/xml", "json", "text/xml", ""}, + } + for _, test := range tests { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // check method is PATCH before going to check other features + if r.Method != POST { + t.Error(fmt.Sprintf("Expected method %q; got %q", POST, r.Method)) + } + if r.Header == nil { + t.Error("Expected non-nil request Header") + } + if r.Header.Get("Content-Type") != test.expectedHeader { + t.Error(fmt.Sprintf("Expected Header Content-Type -> %q | but got %q", test.expectedHeader, r.Header.Get("Content-Type"))) + } + })) + + New().Post(ts.URL). + Set("Content-Type", test.customContentType). + Type(test.Type). + Send(test.body). + End() + New().Post(ts.URL). + Set("cOnTent-tYpE", test.customContentType). + Type(test.Type). + Send(test.body). + End() + New().Post(ts.URL). + AppendHeader("Content-Type", test.customContentType). + Type(test.Type). + Send(test.body). + End() + ts.Close() + } } // Test for request can accept multiple types. @@ -2519,24 +2513,24 @@ func TestAcceptMultipleTypes(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // check method is PATCH before going to check other features if r.Method != POST { - t.Errorf("Expected method %q; got %q", POST, r.Method) + t.Error(fmt.Sprintf("Expected method %q; got %s", POST, r.Method)) } if r.Header == nil { t.Error("Expected non-nil request Header") } if r.Header.Get("Content-Type") != "text/plain" { - t.Error("Expected Header Content-Type -> text/plain", "| but got", r.Header.Get("Content-Type")) + t.Error(fmt.Sprintf("Expected Header Content-Type -> text/plain | but got %s", r.Header.Get("Content-Type"))) } expectedAccepts := []string{"text/plain", "application/json"} if strings.Join(r.Header["Accept"], ", ") != strings.Join(expectedAccepts, ", ") { - t.Error("Expected Header Accept -> ", expectedAccepts, "| but got", r.Header["Accept"]) + t.Error(fmt.Sprintf("Expected Header Accept -> %v | but got %v", expectedAccepts, r.Header["Accept"])) } defer r.Body.Close() body, _ := ioutil.ReadAll(r.Body) if string(body) != text { - t.Error(`Expected text `, text, "| but got", string(body)) + t.Error(fmt.Sprintf(`Expected text %s | but got %s`, text, string(body))) } })) @@ -2580,7 +2574,7 @@ func TestAsCurlCommand(t *testing.T) { expected := fmt.Sprintf(`curl -X 'PUT' -d '%v' -H 'Content-Type: application/json' '%v'`, strings.Replace(jsonData, " ", "", -1), endpoint) if curlComand != expected { - t.Fatalf("\nExpected curlCommand=%v\n but actual result=%v", expected, curlComand) + t.Fatal(fmt.Sprintf("\nExpected curlCommand=%v\n but actual result=%v", expected, curlComand)) } } @@ -2594,7 +2588,7 @@ func TestSetDebugByEnvironmentVar(t *testing.T) { New().SetLogger(logger).Get(endpoint).End() if len(buf.String()) == 0 { - t.Fatalf("\nExpected gorequest to log request and response object if GOREQUEST_DEBUG=1") + t.Fatal(fmt.Sprintf("\nExpected gorequest to log request and response object if GOREQUEST_DEBUG=1")) } os.Setenv("GOREQUEST_DEBUG", "") @@ -2603,6 +2597,26 @@ func TestSetDebugByEnvironmentVar(t *testing.T) { New().SetLogger(logger).Get(endpoint).End() if len(buf.String()) > 0 { - t.Fatalf("\nExpected gorequest not to log request and response object if GOREQUEST_DEBUG is not set.") + t.Fatal(fmt.Sprintf("\nExpected gorequest not to log request and response object if GOREQUEST_DEBUG is not set.")) + } +} + +func TestContenxt(t *testing.T) { + // requesting a long connection which block this requst for a time, + // but 2 seconds later we unable to hold ourself back and force close it + ctx, cancel := context.WithCancel(context.Background()) + go New().Context(ctx).Get("http://127.0.0.1:8080/foo").EndBytes(func(response Response, body []byte, errs []error) { + + + if len(errs) > 0 { + fmt.Printf("%+v\n", errs[0]) + } + fmt.Println(string(body)) + }) + + select { + case <-time.After(2 * time.Second): + fmt.Println("cancel...") + cancel() } } diff --git a/gorequest_transport_go1.2.go b/gorequest_transport_go1.2.go deleted file mode 100644 index 47baa7c..0000000 --- a/gorequest_transport_go1.2.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build go1.2 -// +build !go1.3 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - Dial: oldTransport.Dial, - TLSClientConfig: oldTransport.TLSClientConfig, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - } -} diff --git a/gorequest_transport_go1.3.go b/gorequest_transport_go1.3.go deleted file mode 100644 index 15247f0..0000000 --- a/gorequest_transport_go1.3.go +++ /dev/null @@ -1,27 +0,0 @@ -// +build go1.3 -// +build !go1.4 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - Dial: oldTransport.Dial, - TLSClientConfig: oldTransport.TLSClientConfig, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - // new in 1.3 - TLSHandshakeTimeout: oldTransport.TLSHandshakeTimeout, - } -} diff --git a/gorequest_transport_go1.4.go b/gorequest_transport_go1.4.go deleted file mode 100644 index 6e5f1c1..0000000 --- a/gorequest_transport_go1.4.go +++ /dev/null @@ -1,28 +0,0 @@ -// +build go1.4 -// +build !go1.6 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - Dial: oldTransport.Dial, - TLSClientConfig: oldTransport.TLSClientConfig, - TLSHandshakeTimeout: oldTransport.TLSHandshakeTimeout, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - // new in go1.4 - DialTLS: oldTransport.DialTLS, - } -} diff --git a/gorequest_transport_go1.6.go b/gorequest_transport_go1.6.go deleted file mode 100644 index 3786cd6..0000000 --- a/gorequest_transport_go1.6.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build go1.6 -// +build !go1.7 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - Dial: oldTransport.Dial, - DialTLS: oldTransport.DialTLS, - TLSClientConfig: oldTransport.TLSClientConfig, - TLSHandshakeTimeout: oldTransport.TLSHandshakeTimeout, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - // new in 1.6 - ExpectContinueTimeout: oldTransport.ExpectContinueTimeout, - TLSNextProto: oldTransport.TLSNextProto, - } -} diff --git a/gorequest_transport_go1.7.go b/gorequest_transport_go1.7.go deleted file mode 100644 index a3e77f0..0000000 --- a/gorequest_transport_go1.7.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build go1.7 -// +build !go1.8 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - Dial: oldTransport.Dial, - DialTLS: oldTransport.DialTLS, - TLSClientConfig: oldTransport.TLSClientConfig, - TLSHandshakeTimeout: oldTransport.TLSHandshakeTimeout, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConns: oldTransport.MaxIdleConns, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - ExpectContinueTimeout: oldTransport.ExpectContinueTimeout, - TLSNextProto: oldTransport.TLSNextProto, - // new in go1.7 - DialContext: oldTransport.DialContext, - IdleConnTimeout: oldTransport.IdleConnTimeout, - MaxResponseHeaderBytes: oldTransport.MaxResponseHeaderBytes, - } -} diff --git a/gorequest_transport_go1.8.go b/gorequest_transport_go1.8.go deleted file mode 100644 index 136ca5b..0000000 --- a/gorequest_transport_go1.8.go +++ /dev/null @@ -1,34 +0,0 @@ -// +build go1.8 - -package gorequest - -import ( - "net/http" -) - -// does a shallow clone of the transport -func (s *SuperAgent) safeModifyTransport() { - if !s.isClone { - return - } - oldTransport := s.Transport - s.Transport = &http.Transport{ - Proxy: oldTransport.Proxy, - DialContext: oldTransport.DialContext, - Dial: oldTransport.Dial, - DialTLS: oldTransport.DialTLS, - TLSClientConfig: oldTransport.TLSClientConfig, - TLSHandshakeTimeout: oldTransport.TLSHandshakeTimeout, - DisableKeepAlives: oldTransport.DisableKeepAlives, - DisableCompression: oldTransport.DisableCompression, - MaxIdleConns: oldTransport.MaxIdleConns, - MaxIdleConnsPerHost: oldTransport.MaxIdleConnsPerHost, - IdleConnTimeout: oldTransport.IdleConnTimeout, - ResponseHeaderTimeout: oldTransport.ResponseHeaderTimeout, - ExpectContinueTimeout: oldTransport.ExpectContinueTimeout, - TLSNextProto: oldTransport.TLSNextProto, - MaxResponseHeaderBytes: oldTransport.MaxResponseHeaderBytes, - // new in go1.8 - ProxyConnectHeader: oldTransport.ProxyConnectHeader, - } -}