Documentation
ΒΆ
Index ΒΆ
- func SetDefaultTimeout(d time.Duration)
- type Client
- func (c *Client) Delete(ctx context.Context, path string, v any) *Request
- func (c *Client) Error() error
- func (c *Client) Get(ctx context.Context, path string) *Request
- func (c *Client) Head(ctx context.Context, path string) *Request
- func (c *Client) Options(ctx context.Context, path string) *Request
- func (c *Client) Patch(ctx context.Context, path string, v any) *Request
- func (c *Client) Post(ctx context.Context, path string, v any) *Request
- func (c *Client) Put(ctx context.Context, path string, v any) *Request
- func (c *Client) UseRequest(fns ...RequestInterceptorFn)
- func (c *Client) UseResponse(fns ...ResponseInterceptorFn)
- type FetchError
- type Option
- type Request
- func Delete(rawURL string, v any) *Request
- func DeleteWithContext(ctx context.Context, rawURL string, v any) *Request
- func Get(rawURL string) *Request
- func GetWithContext(ctx context.Context, rawURL string) *Request
- func Patch(rawURL string, v any) *Request
- func PatchWithContext(ctx context.Context, rawURL string, v any) *Request
- func Post(rawURL string, v any) *Request
- func PostWithContext(ctx context.Context, rawURL string, v any) *Request
- func Put(rawURL string, v any) *Request
- func PutWithContext(ctx context.Context, rawURL string, v any) *Request
- func (r *Request) Do() (*Response, error)
- func (r *Request) Scan(v any) error
- func (r *Request) WithBasicAuth(username, password string) *Request
- func (r *Request) WithBearerToken(token string) *Request
- func (r *Request) WithFormBody(fields map[string]string) *Request
- func (r *Request) WithHeader(key, value string) *Request
- func (r *Request) WithHeaders(headers map[string]string) *Request
- func (r *Request) WithJSONBody(v any) *Request
- func (r *Request) WithMultipartBody(fields map[string]any) *Request
- func (r *Request) WithParam(key, value string) *Request
- func (r *Request) WithParams(params map[string]string) *Request
- func (r *Request) WithRawBody(reader io.Reader, contentType string) *Request
- func (r *Request) WithTextBody(text string) *Request
- type RequestInterceptorFn
- type Response
- func (r *Response) Bytes() ([]byte, error)
- func (r *Response) IsClientError() bool
- func (r *Response) IsOK() bool
- func (r *Response) IsRedirect() bool
- func (r *Response) IsServerError() bool
- func (r *Response) JSON(v any) error
- func (r *Response) Text() (string, error)
- func (r *Response) XML(v any) error
- type ResponseInterceptorFn
Examples ΒΆ
Constants ΒΆ
This section is empty.
Variables ΒΆ
This section is empty.
Functions ΒΆ
func SetDefaultTimeout ΒΆ
SetDefaultTimeout changes the timeout of the package-level default client.
Types ΒΆ
type Client ΒΆ
type Client struct {
// contains filtered or unexported fields
}
Client is a reusable HTTP client bound to a base URL β the Go equivalent of an axios instance. Create one via New; share it across goroutines freely.
Any error that occurs during construction (e.g. an invalid base URL) is stored inside the Client and returned the first time Do or Scan is called. Call client.Error() to inspect it eagerly before making any requests.
func New ΒΆ
New creates a Client bound to baseURL. It never returns an error directly β any construction error (e.g. an invalid URL) is stored inside the Client and surfaced the first time Do or Scan is called on any request built from it.
Check eagerly with client.Error() if you need to fail fast at startup.
client := fetch.New("https://api.example.com")
if err := client.Error(); err != nil {
log.Fatal(err)
}
Example ΒΆ
ExampleNew demonstrates creating a reusable client with common defaults.
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
"github.com/rixotech/fetch-go"
)
// ExampleNew demonstrates creating a reusable client with common defaults.
func main() {
client := fetch.New("https://api.example.com",
fetch.WithTimeout(10*time.Second),
fetch.WithDefaultHeaders(map[string]string{
"Accept": "application/json",
"User-Agent": "my-app/1.0",
}),
)
// Attach a request interceptor that injects an auth token on every call.
client.UseRequest(func(req *http.Request) (*http.Request, error) {
req.Header.Set("Authorization", "Bearer "+getToken())
return req, nil
})
// Attach a response interceptor for structured logging.
client.UseResponse(func(resp *http.Response) (*http.Response, error) {
fmt.Printf("[fetch] %s %s β %s\n", resp.Request.Method, resp.Request.URL.Path, resp.Status)
return resp, nil
})
ctx := context.Background()
// ββ GET with query params βββββββββββββββββββββββββββββββββββββββββββββ
var users []struct {
ID int `json:"id"`
Name string `json:"name"`
}
client.Get(ctx, "/users").
WithParam("page", "1").
WithParam("limit", "20").
Scan(&users)
if err := client.Error(); err != nil {
// Non-2xx responses surface as *fetch.FetchError.
if fe, ok := fetch.AsFetchError(err); ok {
fmt.Printf("HTTP %d: %s\n", fe.StatusCode, fe.Body)
}
log.Fatal(err)
}
// ββ POST with JSON body βββββββββββββββββββββββββββββββββββββββββββββββ
type CreateUserReq struct {
Name string `json:"name"`
Email string `json:"email"`
}
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
var created User
client.Post(ctx, "/users", CreateUserReq{
Name: "Alice",
Email: "alice@example.com",
}).Scan(&created)
if err := client.Error(); err != nil {
log.Fatal(err)
}
fmt.Printf("created user id=%d\n", created.ID)
// ββ PUT βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
var updated User
client.Put(ctx, "/users/1", CreateUserReq{Name: "Alice Updated"}).
Scan(&updated)
if err := client.Error(); err != nil {
log.Fatal(err)
}
// ββ PATCH βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
client.Patch(ctx, "/users/1", map[string]string{"name": "Alice V2"}).
Scan(&updated)
if err := client.Error(); err != nil {
log.Fatal(err)
}
// ββ DELETE ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
resp, err := client.Delete(ctx, "/users/1", nil).Do()
if err := client.Error(); err != nil {
log.Fatal(err)
}
fmt.Printf("delete status: %s\n", resp.Status)
// ββ Form-encoded body βββββββββββββββββββββββββββββββββββββββββββββββββ
_, err = client.Post(ctx, "/login", nil).
WithFormBody(map[string]string{
"username": "alice",
"password": "s3cr3t",
}).Do()
if err != nil {
log.Fatal(err)
}
// ββ Raw text body ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
_, err = client.Post(ctx, "/logs", nil).
WithTextBody("something happened").
Do()
if err != nil {
log.Fatal(err)
}
// ββ Read response as plain text ββββββββββββββββββββββββββββββββββββββββ
r, err := client.Get(ctx, "/health").Do()
if err != nil {
log.Fatal(err)
}
text, _ := r.Text()
fmt.Println(text)
}
func getToken() string { return "secret-token" }
Output:
func (*Client) Delete ΒΆ
Delete returns a DELETE Request. An optional body may be passed (nil is fine).
func (*Client) Error ΒΆ added in v0.3.0
Error returns the first error that occurred during client construction, or nil if the client was created successfully.
Use this when you want to validate the client at startup rather than waiting for the first request to fail:
client := fetch.New(os.Getenv("API_URL"))
if err := client.Error(); err != nil {
log.Fatal(err)
}
func (*Client) UseRequest ΒΆ
func (c *Client) UseRequest(fns ...RequestInterceptorFn)
UseRequest appends one or more request interceptors. They are executed in registration order before every outgoing request.
func (*Client) UseResponse ΒΆ
func (c *Client) UseResponse(fns ...ResponseInterceptorFn)
UseResponse appends one or more response interceptors. They are executed in registration order after every response is received.
type FetchError ΒΆ
FetchError represents an HTTP-level error (non-2xx response). It is distinct from a network/transport error so callers can branch on response status without string-matching.
func AsFetchError ΒΆ
func AsFetchError(err error) (*FetchError, bool)
AsFetchError unwraps err into *FetchError. Returns (nil, false) when err is not (or does not wrap) a *FetchError.
func (*FetchError) Error ΒΆ
func (e *FetchError) Error() string
func (*FetchError) IsForbidden ΒΆ
func (e *FetchError) IsForbidden() bool
IsForbidden returns true when the server returned 403.
func (*FetchError) IsNotFound ΒΆ
func (e *FetchError) IsNotFound() bool
IsNotFound returns true when the server returned 404.
func (*FetchError) IsServerError ΒΆ
func (e *FetchError) IsServerError() bool
IsServerError returns true for any 5xx status.
func (*FetchError) IsUnauthorized ΒΆ
func (e *FetchError) IsUnauthorized() bool
IsUnauthorized returns true when the server returned 401.
type Option ΒΆ
type Option func(*Client)
Option is a functional option for Client.
func WithDefaultHeaders ΒΆ
WithDefaultHeaders merges h into the client's default headers. Per-request headers always take precedence over these.
func WithHTTPClient ΒΆ
WithHTTPClient replaces the underlying *http.Client entirely. Useful when you need custom TLS config, a proxy, or cookie jars.
func WithTimeout ΒΆ
WithTimeout sets the total timeout for every request made by this client. Default: 30 s.
func WithoutErrorOnStatus ΒΆ
func WithoutErrorOnStatus() Option
WithoutErrorOnStatus disables automatic *FetchError wrapping for non-2xx responses. Use when you want to inspect every status code yourself.
type Request ΒΆ
type Request struct {
// contains filtered or unexported fields
}
Request is a single pending HTTP request built via the fluent API. Call Do or Scan to execute it.
func DeleteWithContext ΒΆ added in v1.0.0
Delete issues a one-off DELETE request without a base URL.
func GetWithContext ΒΆ added in v1.0.0
Get issues a one-off GET request without a base URL.
func PatchWithContext ΒΆ added in v1.0.0
Patch issues a one-off PATCH request without a base URL.
func PostWithContext ΒΆ added in v1.0.0
Post issues a one-off POST request without a base URL.
func PutWithContext ΒΆ added in v1.0.0
Put issues a one-off PUT request without a base URL.
func (*Request) Do ΒΆ
Do executes the request and returns the raw *Response.
Unless WithoutErrorOnStatus was set on the client, a *FetchError is returned for any non-2xx status code so the caller does not need to check resp.IsOK() manually.
func (*Request) Scan ΒΆ
Scan executes the request and JSON-decodes a successful response body into v. It is shorthand for:
resp, err := r.Do()
if err != nil { return err }
return resp.JSON(v)
func (*Request) WithBasicAuth ΒΆ
WithBasicAuth sets the Authorization header using HTTP Basic Auth encoding.
func (*Request) WithBearerToken ΒΆ
WithBearerToken is a convenience shortcut for Authorization: Bearer <token>.
func (*Request) WithFormBody ΒΆ
WithFormBody replaces the request body with URL-encoded form data and sets Content-Type: application/x-www-form-urlencoded.
func (*Request) WithHeader ΒΆ
WithHeader sets a single HTTP header.
func (*Request) WithHeaders ΒΆ
WithHeaders merges HTTP headers into the request. Per-request headers override client-level default headers.
func (*Request) WithJSONBody ΒΆ
WithJSONBody replaces the request body with a JSON-encoded v. It also sets Content-Type: application/json.
func (*Request) WithMultipartBody ΒΆ
WithMultipartBody replaces the request body with a multipart/form-data payload. Pass file content as []byte values; all other values are treated as text fields.
func (*Request) WithParams ΒΆ
WithParams merges query parameters into the request URL. May be called multiple times; later values overwrite earlier ones for the same key.
r.WithParams(map[string]string{"page": "2", "limit": "50"})
func (*Request) WithRawBody ΒΆ
WithRawBody sets an arbitrary body reader and Content-Type.
func (*Request) WithTextBody ΒΆ
WithTextBody replaces the request body with a plain-text string.
type RequestInterceptorFn ΒΆ
RequestInterceptorFn is called just before an HTTP request is sent. It may mutate or replace the request. Returning a non-nil error aborts the request and surfaces the error from Do / Scan.
type Response ΒΆ
type Response struct {
// StatusCode is the HTTP response status code (e.g. 200, 404).
StatusCode int
// Status is the raw status string (e.g. "200 OK").
Status string
// Header contains the response headers.
Header http.Header
// Raw is the underlying *http.Response for callers who need lower-level
// access. Body has NOT been consumed; call exactly one of the decode
// helpers, or read Body yourself and close it.
Raw *http.Response
}
Response wraps *http.Response and exposes ergonomic decode helpers. The underlying body is always closed after any Scan / JSON / Text / Bytes call β callers must not read the body a second time.
func (*Response) IsClientError ΒΆ
IsClientError returns true for any 4xx status code.
func (*Response) IsRedirect ΒΆ
IsRedirect returns true for any 3xx status code.
func (*Response) IsServerError ΒΆ
IsServerError returns true for any 5xx status code.
type ResponseInterceptorFn ΒΆ
ResponseInterceptorFn is called immediately after a response is received (but before the body is read / decoded). It may mutate or replace the response. Returning a non-nil error surfaces the error from Do / Scan.