// Do sends an HTTP request with the provided http.Client and returns an HTTP response. // If the client is nil, http.DefaultClient is used. // If the context is canceled or times out, ctx.Err() will be returned. func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { if client == nil { client = http.DefaultClient } // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go. cancel := canceler(client, req) type responseAndError struct { resp *http.Response err error } result := make(chan responseAndError, 1) go func() { resp, err := client.Do(req) result <- responseAndError{resp, err} }() var resp *http.Response select { case <-ctx.Done(): cancel() return nil, ctx.Err() case r := <-result: var err error resp, err = r.resp, r.err if err != nil { return resp, err } } c := make(chan struct{}) go func() { select { case <-ctx.Done(): cancel() case <-c: // The response's Body is closed. } }() resp.Body = ¬ifyingReader{resp.Body, c} return resp, nil }
func (c *Client) get(ctx context.Context, config *apiConfig, apiReq apiRequest) (*http.Response, error) { select { case <-ctx.Done(): return nil, ctx.Err() case <-c.rateLimiter: // Execute request. } host := config.host if c.baseURL != "" { host = c.baseURL } req, err := http.NewRequest("GET", host+config.path, nil) if err != nil { return nil, err } q, err := c.generateAuthQuery(config.path, apiReq.params(), config.acceptsClientID) if err != nil { return nil, err } req.URL.RawQuery = q return ctxhttp.Do(ctx, c.httpClient, req) }