package httpx import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "net/url" ) // NewRequest creates an http.Request with context. It is a convenience // wrapper around http.NewRequestWithContext. func NewRequest(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) { return http.NewRequestWithContext(ctx, method, url, body) } // NewJSONRequest creates an http.Request with a JSON-encoded body and // sets Content-Type to application/json. func NewJSONRequest(ctx context.Context, method, url string, body any) (*http.Request, error) { b, err := json.Marshal(body) if err != nil { return nil, fmt.Errorf("httpx: encoding JSON body: %w", err) } req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewReader(b)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") req.GetBody = func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(b)), nil } return req, nil } // NewFormRequest creates an http.Request with a form-encoded body and // sets Content-Type to application/x-www-form-urlencoded. // The GetBody function is set so that the request can be retried. func NewFormRequest(ctx context.Context, method, rawURL string, values url.Values) (*http.Request, error) { encoded := values.Encode() b := []byte(encoded) req, err := http.NewRequestWithContext(ctx, method, rawURL, bytes.NewReader(b)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.GetBody = func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(b)), nil } return req, nil }