diff --git a/client.go b/client.go index 345ccdd..216459b 100644 --- a/client.go +++ b/client.go @@ -14,9 +14,9 @@ import ( type ClientOptions map[string]interface{} -func (opt *ClientOptions) Merge(other ClientOptions) { +func (c ClientOptions) Merge(other ClientOptions) { for key := range other { - (*opt)[key] = other[key] + c[key] = other[key] } } @@ -30,30 +30,30 @@ func New() *Request { return NewRequest(Cleaned()) } -func Default() (cl *StandardClient) { +func Default() *StandardClient { return &StandardClient{ Client: &http.Client{}, Logger: defaultLogger, } } -func Cleaned() (cl *StandardClient) { +func Cleaned() *StandardClient { return &StandardClient{ Client: cleanhttp.DefaultClient(), Logger: defaultLogger, } } -func Pooled() (cl *StandardClient) { +func Pooled() *StandardClient { return &StandardClient{ Client: cleanhttp.DefaultPooledClient(), Logger: defaultLogger, } } -func NewClient(clients ...*http.Client) (cl *StandardClient) { - +func NewClient(clients ...*http.Client) *StandardClient { var client *http.Client + if len(clients) == 0 { client = &http.Client{} } else { @@ -66,66 +66,57 @@ func NewClient(clients ...*http.Client) (cl *StandardClient) { } } -func (client *StandardClient) Error() error { - return client.err +func (cl StandardClient) Error() error { + return cl.err } -func (client *StandardClient) With(options ...interface{}) *StandardClient { - +func (cl *StandardClient) With(options ...interface{}) *StandardClient { for _, option := range options { switch option.(type) { case time.Duration: - client.Timeout = option.(time.Duration) + cl.Timeout = option.(time.Duration) case http.RoundTripper: - client.Transport = option.(http.RoundTripper) + cl.Transport = option.(http.RoundTripper) case http.CookieJar: - client.Jar = option.(http.CookieJar) + cl.Jar = option.(http.CookieJar) } } - return client + return cl } -func (client *StandardClient) WithTimeout( - timeout time.Duration) *StandardClient { - - client.Timeout = timeout - return client +func (cl *StandardClient) WithTimeout(timeout time.Duration) *StandardClient { + cl.Timeout = timeout + return cl } -func (client *StandardClient) WithJar(jar http.CookieJar) *StandardClient { - - client.Jar = jar - return client +func (cl *StandardClient) WithJar(jar http.CookieJar) *StandardClient { + cl.Jar = jar + return cl } -func (client *StandardClient) SetCookies( - host string, cookies ...*http.Cookie) *StandardClient { - - if client.Jar == nil { - client.Jar, _ = cookiejar.New(nil) +func (cl *StandardClient) SetCookies(host string, cookies ...*http.Cookie) *StandardClient { + if cl.Jar == nil { + cl.Jar, _ = cookiejar.New(nil) } u, _ := url.Parse(host) - client.Jar.SetCookies(u, cookies) - return client + cl.Jar.SetCookies(u, cookies) + return cl } -func (client *StandardClient) Cookies(host string) []*http.Cookie { +func (cl StandardClient) Cookies(host string) []*http.Cookie { u, _ := url.Parse(host) - return client.Jar.Cookies(u) + return cl.Jar.Cookies(u) } -func (client *StandardClient) WithTransport( - transport http.RoundTripper) *StandardClient { - - client.Transport = transport - return client +func (cl *StandardClient) WithTransport(transport http.RoundTripper) *StandardClient { + cl.Transport = transport + return cl } -func (client *StandardClient) WithLogger(logger Logger) *StandardClient { - - client.Logger = logger - return client +func (cl *StandardClient) WithLogger(logger Logger) *StandardClient { + cl.Logger = logger + return cl } diff --git a/go.mod b/go.mod index d810991..c928bf7 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,12 @@ module github.com/GarryGaller/go-www go 1.17 -require github.com/softlandia/cpd v0.0.0-20210117083209-2413526f2815 +require ( + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/softlandia/cpd v0.0.0-20210117083209-2413526f2815 +) require ( - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/stretchr/testify v1.7.0 // indirect - golang.org/x/net v0.0.0-20211111160137-58aab5ef257a // indirect golang.org/x/text v0.3.6 // indirect ) diff --git a/go.sum b/go.sum index 72bf6d1..9f27557 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,6 @@ github.com/softlandia/cpd v0.0.0-20210117083209-2413526f2815/go.mod h1:4xzl60B5T github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/net v0.0.0-20211111160137-58aab5ef257a h1:c83jeVQW0KGKNaKBRfelNYNHaev+qawl9yaA825s8XE= -golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/request.go b/request.go index f22df6d..70d84c4 100644 --- a/request.go +++ b/request.go @@ -14,7 +14,7 @@ import ( "strings" ) -var ErrorEmptyListValues = errors.New("An empty list of values is passed to create multipart content") +var ErrorEmptyListValues = errors.New("an empty list of values is passed to create multipart content") type Request struct { *http.Request @@ -27,42 +27,30 @@ type Request struct { } func NewRequest(client *StandardClient) *Request { - return &Request{client: client} + return &Request{ + client: client, + } } -func (r *Request) Error() error { +func (r Request) Error() error { return r.err } -func (r *Request) Headers() (out http.Header) { +func (r Request) Headers() (out http.Header) { if r.Request != nil { out = r.Request.Header } - return + + return out } -func (r *Request) Cookies() (out []*http.Cookie) { +func (r Request) Cookies() (out []*http.Cookie) { if r.Request != nil { out = r.Request.Cookies() } - return -} - -/* -func (r *Request) SetHeaders(headers http.Header) *Request { - for key, val := range headers { - r.Request.Header.Set(key, val[0]) - } - return r -} -func (r *Request) AddHeaders(headers http.Header) *Request { - for key, val := range headers { - r.Request.Header.Add(key, val[0]) - } - return r + return out } -*/ func (r *Request) SetCookies(cookies ...*http.Cookie) *Request { r.cookies = cookies @@ -70,7 +58,6 @@ func (r *Request) SetCookies(cookies ...*http.Cookie) *Request { } func (r *Request) prepareCookies() { - for _, cookie := range r.cookies { r.Request.AddCookie(cookie) } @@ -106,62 +93,63 @@ func (r *Request) prepareRequest( } func (r *Request) Get(uri string, headers ...http.Header) *Response { - - return r.Do("GET", uri, headers...) + return r.Do(http.MethodGet, uri, headers...) } -func (r *Request) Post( - uri string, headers ...http.Header) *Response { - - return r.Do("POST", uri, headers...) +func (r *Request) Post(uri string, headers ...http.Header) *Response { + return r.Do(http.MethodPost, uri, headers...) } func (r *Request) Put(uri string, headers ...http.Header) *Response { - return r.Do("PUT", uri, headers...) // with body, output body + return r.Do(http.MethodPut, uri, headers...) // with body, output body } func (r *Request) Patch(uri string, headers ...http.Header) *Response { - return r.Do("PATCH", uri, headers...) // with body, output body + return r.Do(http.MethodPatch, uri, headers...) // with body, output body } func (r *Request) Delete(uri string, headers ...http.Header) *Response { - return r.Do("DELETE", uri, headers...) // can have a body, output body + return r.Do(http.MethodDelete, uri, headers...) // may have a body, output body } func (r *Request) Head(uri string) *Response { - return r.Do("HEAD", uri) // no body + return r.Do(http.MethodHead, uri) // no body } func (r *Request) Trace(uri string) *Response { - return r.Do("TRACE", uri) // no body + return r.Do(http.MethodTrace, uri) // no body } func (r *Request) Options(uri string) *Response { - return r.Do("OPTIONS", uri) // no body + return r.Do(http.MethodOptions, uri) // no body } func (r *Request) Connect(uri string) *Response { - return r.Do("CONNECT", uri) // no body + return r.Do(http.MethodConnect, uri) // no body } -func (r *Request) Do(method string, - uri string, headers ...http.Header) *Response { - +func (r *Request) Do(method string, uri string, headers ...http.Header) *Response { var err error + defer closeReader(r.body) + if r.err != nil { - return &Response{nil, nil, nil} + return &Response{nil, r.err, nil} } r.prepareRequest(method, uri, headers...) r.prepareCookies() if r.err != nil { - return &Response{nil, nil, nil} + return &Response{nil, r.err, nil} } resp, err := r.client.Do(r.Request) - return &Response{resp, err, nil} + return &Response{ + Response: resp, + err: err, + content: nil, + } } func (r *Request) With(params *url.Values, data *url.Values) *Request { @@ -217,8 +205,7 @@ func (r *Request) AttachFile(reader io.Reader, contentType ...string) *Request { return r } - body := &bytes.Buffer{} - + body := new(bytes.Buffer) writer := multipart.NewWriter(body) if part, err = CreateFormFile( @@ -242,7 +229,6 @@ func (r *Request) AttachFile(reader io.Reader, contentType ...string) *Request { } func (r *Request) AttachFiles(files map[string][]interface{}) *Request { - var ( err error fileName string @@ -250,10 +236,11 @@ func (r *Request) AttachFiles(files map[string][]interface{}) *Request { part io.Writer ) - body := &bytes.Buffer{} - + body := new(bytes.Buffer) writer := multipart.NewWriter(body) + var closeReaders []io.Reader + for field, values := range files { if len(values) == 0 { r.err = ErrorEmptyListValues @@ -275,14 +262,11 @@ func (r *Request) AttachFiles(files map[string][]interface{}) *Request { if f, ok := reader.(*os.File); ok { fileName = filepath.Base(f.Name()) - defer func(reader io.Reader) { - closeReader(reader) - }(reader) + closeReaders = append(closeReaders, f) if part, err = CreateFormFile( writer, field, fileName, contentType); err != nil { r.err = err - //closeReader(reader) continue } } else { @@ -295,13 +279,15 @@ func (r *Request) AttachFiles(files map[string][]interface{}) *Request { r.err = err continue } - - //closeReader(reader) } r.mime = writer.FormDataContentType() writer.Close() r.body = body + for _, reader := range closeReaders { + closeReader(reader) + } + return r } diff --git a/response.go b/response.go index 688ed8c..8e38731 100644 --- a/response.go +++ b/response.go @@ -8,8 +8,6 @@ import ( "net/http" "strings" - //"fmt" - //"golang.org/x/net/html/charset" "github.com/softlandia/cpd" ) @@ -19,7 +17,7 @@ type Response struct { content []byte } -func (resp *Response) Error() error { +func (resp Response) Error() error { return resp.err } @@ -27,6 +25,7 @@ func (resp *Response) Content() []byte { if resp.content == nil { resp.content = resp.readAll() } + return resp.content } @@ -37,37 +36,36 @@ func (resp *Response) Text() string { return string(resp.content) } - -func (resp *Response) ContentType(contentTypes ...string) (mime, charset string) { + +func (resp Response) ContentType(contentTypes ...string) (mime, charset string) { var contentType string - + if len(contentTypes) > 0 { contentType = contentTypes[0] - } else { + } else { contentType = resp.Header.Get("Content-Type") } - cp := strings.Split(contentType, ";") + + cp := strings.Split(contentType, ";") mime = cp[0] - if len(cp) > 1 { - cp = strings.Split(cp[1], "=") - if len(cp) > 1 { - charset = strings.TrimSpace(cp[1]) - } - } - return + if len(cp) > 1 { + cp = strings.Split(cp[1], "=") + if len(cp) > 1 { + charset = strings.TrimSpace(cp[1]) + } + } + return } -func (resp *Response) Mime(contentTypes ...string) (mime string) { - mime, _ = resp.ContentType(contentTypes...) - return +func (resp Response) Mime(contentTypes ...string) (mime string) { + mime, _ = resp.ContentType(contentTypes...) + return mime } - -func (resp *Response) Charset(contentTypes ...string) (charset string) { - _, charset = resp.ContentType(contentTypes...) - return -} - +func (resp Response) Charset(contentTypes ...string) (charset string) { + _, charset = resp.ContentType(contentTypes...) + return charset +} func (resp *Response) DetectCodePage() string { if resp.content == nil { @@ -77,7 +75,6 @@ func (resp *Response) DetectCodePage() string { return cpd.CodepageAutoDetect(resp.content).String() } - func (resp *Response) NewReader() (reader io.Reader) { //reader, err := charset.NewReader(reader,resp.Header.Get("Content-Type")) reader, err := cpd.NewReader(resp.Body) // need to be tested. @@ -85,16 +82,14 @@ func (resp *Response) NewReader() (reader io.Reader) { resp.err = err } - return + return reader } -func (resp *Response) Headers() http.Header { - +func (resp Response) Headers() http.Header { return resp.Header } func (resp *Response) Json() (data map[string]interface{}) { - contentType := resp.Header.Get("Content-Type") if contentType == "application/json" { if resp.content == nil { @@ -104,17 +99,19 @@ func (resp *Response) Json() (data map[string]interface{}) { resp.err = err } } - return + + return data } -func (resp *Response) JSON() (data map[string]interface{}) { +func (resp Response) JSON() (data map[string]interface{}) { return resp.Json() } func (resp *Response) readAll(convertToUTF8 ...bool) (content []byte) { - var reader io.Reader - var err error - //contentType := resp.Header.Get("Content-Type") + var ( + reader io.Reader + err error + ) contentEncoding := resp.Header.Get("Content-Encoding") switch contentEncoding { @@ -122,7 +119,7 @@ func (resp *Response) readAll(convertToUTF8 ...bool) (content []byte) { reader, err = gzip.NewReader(resp.Body) if err != nil { resp.err = err - return + return nil } default: reader = resp.Body @@ -130,7 +127,7 @@ func (resp *Response) readAll(convertToUTF8 ...bool) (content []byte) { defer resp.Body.Close() - if len(convertToUTF8) > 0 && convertToUTF8[0] == true { + if len(convertToUTF8) > 0 && convertToUTF8[0] { reader = resp.NewReader() } @@ -139,5 +136,5 @@ func (resp *Response) readAll(convertToUTF8 ...bool) (content []byte) { resp.err = err } - return + return content } diff --git a/utils.go b/utils.go index d6f8d04..68e823b 100644 --- a/utils.go +++ b/utils.go @@ -31,10 +31,10 @@ func closeReader(r io.Reader, verbose ...bool) bool { return ok } -var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") +var quoteEscapists = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") func escapeQuotes(s string) string { - return quoteEscaper.Replace(s) + return quoteEscapists.Replace(s) } func CreateFormFile(w *multipart.Writer, diff --git a/www_test.go b/www_test.go index 8cac8e9..c68e45a 100644 --- a/www_test.go +++ b/www_test.go @@ -1,337 +1,337 @@ package www import ( - "net/http" - "net/http/cookiejar" - "net/url" - "strings" - "testing" - "time" + "fmt" + "net/http" + "net/http/cookiejar" + "net/url" + "strings" + "testing" + "time" ) func TestWWW(t *testing.T) { - headers := http.Header{"User-Agent": {"Mozilla"}} - params := &url.Values{"key": {"value"}} - data := &url.Values{"key2": {"value2"}} - - fileName := `utf-8.txt` - fileName2 := `utf-8(2).txt` - fileName3 := `windows-1251.txt` - filePath := `testdata\` + fileName - filePath2 := `testdata\` + fileName2 - filePath3 := `testdata\` + fileName3 - - cl := NewClient().With(2 * time.Second) - - t.Run("DELETE", func(t *testing.T) { - - r := NewRequest(cl) - - resp := r.Delete("https://httpbin.org/delete", http.Header{ - "User-Agent": {"Mozilla"}, - "Accept": {"application/json"}, - }) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Json()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("PATCH", func(t *testing.T) { - - r := NewRequest(cl) - - resp := r.Patch("https://httpbin.org/patch", http.Header{ - "User-Agent": {"Mozilla"}, - "Accept": {"application/json"}, - }) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Json()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("PUT", func(t *testing.T) { - - r := NewRequest(cl) - - resp := r.Put("https://httpbin.org/put", http.Header{ - "User-Agent": {"Mozilla"}, - "Accept": {"application/json"}, - }) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Json()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("GET", func(t *testing.T) { - - r := NewRequest(cl) - resp := r.WithQuery(params). - Get("https://httpbin.org/get", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("POST", func(t *testing.T) { - - t.Run("FORM", func(t *testing.T) { - r := NewRequest(cl) - resp := r.WithQuery(params). - WithForm(data). - Post("https://httpbin.org/post", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("JSON", func(t *testing.T) { - r := NewRequest(cl) - resp := r.WithQuery(params). - JSON(params). - Post("https://httpbin.org/post", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Json()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("FILE", func(t *testing.T) { - - reader := MustOpen(filePath3) - - r := NewRequest(cl) - resp := r.WithQuery(params). - WithFile(reader). - Post("https://httpbin.org/post", - http.Header{"Content-Type": {"text/plain; charset=windows-1251"}}, - ) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("AttachFile", func(t *testing.T) { - - r := NewRequest(cl) - resp := r.AttachFile(MustOpen(filePath), "text/plain; charset=utf-8"). - Post("https://httpbin.org/post", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Headers()) - } - } - }) - - t.Run("AttachFiles", func(t *testing.T) { - - files := map[string][]interface{}{ - "file": {MustOpen(filePath), "text/plain; charset=utf-8"}, - "file2": {MustOpen(filePath2), "text/plain; charset=utf-8"}, - "other": {strings.NewReader("hello world!")}, - } - - r := NewRequest(cl) - resp := r.AttachFiles(files). - Post("https://httpbin.org/post", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Headers()) - } - } - }) - - }) - - t.Run("COOKIES", func(t *testing.T) { - - jar, _ := cookiejar.New(nil) - cl.WithJar(jar).SetCookies("https://httpbin.org/", - &http.Cookie{ - Name: "token", - Value: "some_token", - MaxAge: 300, - }, - ) - r := NewRequest(cl) - - cookies := []*http.Cookie{ - { - Name: "token1", - Value: "some_token1", - MaxAge: 300, - }, - - { - Name: "token2", - Value: "some_token2", - MaxAge: 300, - }, - } - resp := r.SetCookies(cookies...). - Get("https://httpbin.org/cookies", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", r.Cookies()) // returns the cookies that are sent with the header Cookie - t.Logf("%s", r.Headers().Get("Cookie")) - } - } - }) - - t.Run("SET COOKIES", func(t *testing.T) { - - jar, _ := cookiejar.New(nil) - cl.WithJar(jar) - r := NewRequest(cl) - - resp := r.WithQuery(&url.Values{"name": {"token"}}). - Get("https://httpbin.org/cookies/set", headers) - - if resp.Error() != nil { - t.Errorf("%v", resp.Error()) - } else { - if resp.StatusCode != 200 { - t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) - } else { - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Text()) - t.Logf("%s", resp.Cookies()) // returns the cookies set in the Set-Cookie headers - t.Logf("%s", resp.Headers().Get("Set-Cookie")) - } - } - }) - - t.Run("GITHUB", func(t *testing.T) { - - client := NewClient() - client.WithTimeout(2 * time.Second) - jar, _ := cookiejar.New(nil) - client.WithJar(jar) - - req := NewRequest(client) - req.SetCookies(&http.Cookie{ - Name: "Garry", - Value: "Galler", - MaxAge: 300, - }) - req.WithQuery(&url.Values{"q": {"generics"}, "l": {"go"}, "type": {"topics"}}) - resp := req.Get("https://github.com/search", - http.Header{ - "User-Agent": {"Mozilla"}, - //"Accept": {"application/vnd.github.v3+json"}, - //"Authorization": {"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}, - }) - t.Logf("%s", resp.Status) - t.Logf("%s", resp.Headers()) - }) + headers := http.Header{"User-Agent": {"Mozilla"}} + params := &url.Values{"key": {"value"}} + data := &url.Values{"key2": {"value2"}} + + fileName := `utf-8.txt` + fileName2 := `utf-8(2).txt` + fileName3 := `windows-1251.txt` + filePath := `testdata/` + fileName + filePath2 := `testdata/` + fileName2 + filePath3 := `testdata/` + fileName3 + + cl := NewClient().With(2 * time.Second) + + t.Run("DELETE", func(t *testing.T) { + + r := NewRequest(cl) + + resp := r.Delete("https://httpbin.org/delete", http.Header{ + "User-Agent": {"Mozilla"}, + "Accept": {"application/json"}, + }) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Json()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("PATCH", func(t *testing.T) { + + r := NewRequest(cl) + + resp := r.Patch("https://httpbin.org/patch", http.Header{ + "User-Agent": {"Mozilla"}, + "Accept": {"application/json"}, + }) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Json()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("PUT", func(t *testing.T) { + + r := NewRequest(cl) + + resp := r.Put("https://httpbin.org/put", http.Header{ + "User-Agent": {"Mozilla"}, + "Accept": {"application/json"}, + }) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Json()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("GET", func(t *testing.T) { + + r := NewRequest(cl) + resp := r.WithQuery(params). + Get("https://httpbin.org/get", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("POST", func(t *testing.T) { + + t.Run("FORM", func(t *testing.T) { + r := NewRequest(cl) + resp := r.WithQuery(params). + WithForm(data). + Post("https://httpbin.org/post", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("JSON", func(t *testing.T) { + r := NewRequest(cl) + resp := r.WithQuery(params). + JSON(params). + Post("https://httpbin.org/post", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Json()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("FILE", func(t *testing.T) { + reader := MustOpen(filePath3) + + r := NewRequest(cl) + resp := r.WithQuery(params). + WithFile(reader). + Post("https://httpbin.org/post", + http.Header{"Content-Type": {"text/plain; charset=windows-1251"}}, + ) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("AttachFile", func(t *testing.T) { + + r := NewRequest(cl) + resp := r.AttachFile(MustOpen(filePath), "text/plain; charset=utf-8"). + Post("https://httpbin.org/post", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Headers()) + } + } + }) + + t.Run("AttachFiles", func(t *testing.T) { + files := map[string][]interface{}{ + "file": {MustOpen(filePath), "text/plain; charset=utf-8"}, + "file2": {MustOpen(filePath2), "text/plain; charset=utf-8"}, + "other": {strings.NewReader("hello world!")}, + } + + r := NewRequest(cl) + resp := r.AttachFiles(files). + Post("https://httpbin.org/post", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + fmt.Println(t, resp) + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Headers()) + } + } + }) + + }) + + t.Run("COOKIES", func(t *testing.T) { + + jar, _ := cookiejar.New(nil) + cl.WithJar(jar).SetCookies("https://httpbin.org/", + &http.Cookie{ + Name: "token", + Value: "some_token", + MaxAge: 300, + }, + ) + r := NewRequest(cl) + + cookies := []*http.Cookie{ + { + Name: "token1", + Value: "some_token1", + MaxAge: 300, + }, + + { + Name: "token2", + Value: "some_token2", + MaxAge: 300, + }, + } + resp := r.SetCookies(cookies...). + Get("https://httpbin.org/cookies", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", r.Cookies()) // returns the cookies that are sent with the header Cookie + t.Logf("%s", r.Headers().Get("Cookie")) + } + } + }) + + t.Run("SET COOKIES", func(t *testing.T) { + + jar, _ := cookiejar.New(nil) + cl.WithJar(jar) + r := NewRequest(cl) + + resp := r.WithQuery(&url.Values{"name": {"token"}}). + Get("https://httpbin.org/cookies/set", headers) + + if resp.Error() != nil { + t.Errorf("%v", resp.Error()) + } else { + if resp.StatusCode != 200 { + t.Errorf("StatusCode:got %d, want 200", resp.StatusCode) + } else { + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Text()) + t.Logf("%s", resp.Cookies()) // returns the cookies set in the Set-Cookie headers + t.Logf("%s", resp.Headers().Get("Set-Cookie")) + } + } + }) + + t.Run("GITHUB", func(t *testing.T) { + + client := NewClient() + client.WithTimeout(2 * time.Second) + jar, _ := cookiejar.New(nil) + client.WithJar(jar) + + req := NewRequest(client) + req.SetCookies(&http.Cookie{ + Name: "Garry", + Value: "Galler", + MaxAge: 300, + }) + req.WithQuery(&url.Values{"q": {"generics"}, "l": {"go"}, "type": {"topics"}}) + resp := req.Get("https://github.com/search", + http.Header{ + "User-Agent": {"Mozilla"}, + //"Accept": {"application/vnd.github.v3+json"}, + //"Authorization": {"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}, + }) + t.Logf("%s", resp.Status) + t.Logf("%s", resp.Headers()) + }) } func BenchmarkWWW(b *testing.B) { - headers := http.Header{"User-Agent": {"Mozilla"}} + headers := http.Header{"User-Agent": {"Mozilla"}} - fileName := `utf-8.txt` - filePath := `testdata\` + fileName + fileName := `utf-8.txt` + filePath := `testdata\` + fileName - cl := NewClient().WithTimeout(2 * time.Second) + cl := NewClient().WithTimeout(2 * time.Second) - b.RunParallel(func(pb *testing.PB) { + b.RunParallel(func(pb *testing.PB) { - for pb.Next() { + for pb.Next() { - r := NewRequest(cl) - resp := r.AttachFile(MustOpen(filePath)). - Post("https://httpbin.org/post", headers) + r := NewRequest(cl) + resp := r.AttachFile(MustOpen(filePath)). + Post("https://httpbin.org/post", headers) - if resp.Error() != nil { - b.Errorf("%v\n", resp.Error()) - } else { - b.Logf("status:%s", resp.Status) - } - } - }) + if resp.Error() != nil { + b.Errorf("%v\n", resp.Error()) + } else { + b.Logf("status:%s", resp.Status) + } + } + }) }