package request import ( "io" "net/http" "net/http/cookiejar" "strings" ) type ( BeforeRequest func(req *http.Request) (err error) AfterRequest func(req *http.Request, res *http.Response) (err error) Client struct { baseUrl string Authorization Authorization client *http.Client cookieJar *cookiejar.Jar interceptorRequest []BeforeRequest interceptorResponse []AfterRequest } ) func (client *Client) stashUri(urlPath string) string { var ( pos int ) if len(urlPath) == 0 { return client.baseUrl } if pos = strings.Index(urlPath, "//"); pos == -1 { if client.baseUrl != "" { if urlPath[0] != '/' { urlPath = "/" + urlPath } return client.baseUrl + urlPath } } return urlPath } func (client *Client) BeforeRequest(cb BeforeRequest) *Client { client.interceptorRequest = append(client.interceptorRequest, cb) return client } func (client *Client) AfterRequest(cb AfterRequest) *Client { client.interceptorResponse = append(client.interceptorResponse, cb) return client } func (client *Client) SetBaseUrl(s string) *Client { client.baseUrl = strings.TrimSuffix(s, "/") return client } func (client *Client) SetCookieJar(cookieJar *cookiejar.Jar) *Client { client.client.Jar = cookieJar return client } func (client *Client) SetClient(httpClient *http.Client) *Client { client.client = httpClient if client.cookieJar != nil { client.client.Jar = client.cookieJar } return client } func (client *Client) SetTransport(transport http.RoundTripper) *Client { client.client.Transport = transport return client } func (client *Client) Get(urlPath string) *Request { return newRequest(http.MethodGet, client.stashUri(urlPath), client) } func (client *Client) Put(urlPath string) *Request { return newRequest(http.MethodPut, client.stashUri(urlPath), client) } func (client *Client) Post(urlPath string) *Request { return newRequest(http.MethodPost, client.stashUri(urlPath), client) } func (client *Client) Delete(urlPath string) *Request { return newRequest(http.MethodDelete, client.stashUri(urlPath), client) } func (client *Client) execute(r *Request) (res *http.Response, err error) { var ( n int reader io.Reader ) if r.contentType == "" && r.body != nil { r.contentType = r.detectContentType(r.body) } if r.body != nil { if reader, err = r.readRequestBody(r.contentType, r.body); err != nil { return } } if r.rawRequest, err = http.NewRequest(r.method, r.uri, reader); err != nil { return } for k, vs := range r.header { for _, v := range vs { r.rawRequest.Header.Add(k, v) } } if r.contentType != "" { r.rawRequest.Header.Set("Content-Type", r.contentType) } if client.Authorization != nil { r.rawRequest.Header.Set("Authorization", client.Authorization.Token()) } if r.context != nil { r.rawRequest = r.rawRequest.WithContext(r.context) } n = len(client.interceptorRequest) for i := n - 1; i >= 0; i-- { if err = client.interceptorRequest[i](r.rawRequest); err != nil { return } } if r.rawResponse, err = client.client.Do(r.rawRequest); err != nil { return nil, err } n = len(client.interceptorResponse) for i := n - 1; i >= 0; i-- { if err = client.interceptorResponse[i](r.rawRequest, r.rawResponse); err != nil { _ = r.rawResponse.Body.Close() return } } return r.rawResponse, err } func New() *Client { client := &Client{ client: http.DefaultClient, interceptorRequest: make([]BeforeRequest, 0, 10), interceptorResponse: make([]AfterRequest, 0, 10), } client.cookieJar, _ = cookiejar.New(nil) client.client.Jar = client.cookieJar return client }