package providers import ( "context" "fmt" "io" "net/http" "net/url" "strings" ) const maxOAuthResponseBodyBytes = 1 << 20 func postFormWithContext(ctx context.Context, client *http.Client, endpoint string, data url.Values) (*http.Response, error) { req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, strings.NewReader(data.Encode())) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") return client.Do(req) } func readOAuthResponseBody(resp *http.Response) ([]byte, error) { limited := io.LimitReader(resp.Body, maxOAuthResponseBodyBytes+1) body, err := io.ReadAll(limited) if err != nil { return nil, err } if len(body) > maxOAuthResponseBodyBytes { return nil, fmt.Errorf("oauth response body exceeded %d bytes", maxOAuthResponseBodyBytes) } if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices { snippet := strings.TrimSpace(string(body)) if len(snippet) > 256 { snippet = snippet[:256] } if snippet == "" { return nil, fmt.Errorf("oauth request failed with status %d", resp.StatusCode) } return nil, fmt.Errorf("oauth request failed with status %d: %s", resp.StatusCode, snippet) } return body, nil }