reqws

package module
v0.0.0-...-d2855f3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: MIT Imports: 14 Imported by: 0

README

go-reqws

Simple HTTP client with built-in WebSocket streaming for Go microservices

Go Reference Go Version License

Features

  • Clean functional options pattern - Idiomatic Go API design
  • Context-first design - Proper cancellation and timeout support
  • Built-in WebSocket streaming - Bidirectional communication with channels
  • Automatic retry with exponential backoff - Smart retry logic for transient failures
  • WebSocket auto-reconnection - Resilient real-time connections
  • Middleware/hooks support - Extensible request/response pipeline
  • Type-safe error handling - Custom error types for better debugging
  • Response helper methods - Convenient JSON parsing and status checking
  • Minimal dependencies - Only requires coder/websocket
  • Production-ready - Secure defaults, proper logging, extensive godoc

Installation

go get github.com/gurizzu/go-reqws

Quick Start

Basic HTTP Request
package main

import (
    "context"
    "log"
    "time"

    "github.com/gurizzu/go-reqws"
)

func main() {
    client := reqws.NewClient("https://api.example.com", 30*time.Second)

    // Simple GET request - clean and concise!
    body, err := client.Request(context.Background(),
        reqws.GET("/users/123"),
    )
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("Response: %s", body)
}
HTTP Request with Response Details
resp, err := client.Do(context.Background(),
    reqws.POST("/users"),
    reqws.WithJSON(map[string]string{
        "name": "John Doe",
        "email": "john@example.com",
    }),
    reqws.WithBearerToken("YOUR_TOKEN"),
)

if err != nil {
    log.Fatal(err)
}

if !resp.IsSuccess() {
    log.Fatalf("Request failed: %d", resp.StatusCode)
}

var user User
if err := resp.JSON(&user); err != nil {
    log.Fatal(err)
}

log.Printf("Created user: %+v", user)
WebSocket Streaming
sendChan := make(chan interface{})
receiveChan := make(chan reqws.WebSocketResponse)

go client.WebSocketStream(context.Background(), sendChan, receiveChan,
    reqws.WithPath("/ws/stream"),
    reqws.WithQueryParam("token", "YOUR_TOKEN"),
)

// Send message
sendChan <- map[string]string{"action": "subscribe", "channel": "updates"}

// Receive messages
for msg := range receiveChan {
    if msg.Error != nil {
        log.Printf("Error: %v", msg.Error)
        break
    }
    if msg.Closed {
        log.Println("Connection closed")
        break
    }
    log.Printf("Received: %v", msg.Data)
}

Advanced Usage

Retry Mechanism

Automatically retry failed requests with exponential backoff:

// Use default retry (3 attempts, 100ms initial delay, 5s max delay)
body, err := client.Request(ctx,
    reqws.GET("/api/data"),
    reqws.WithDefaultRetry(),
)

// Custom retry configuration
body, err := client.Request(ctx,
    reqws.GET("/api/data"),
    reqws.WithRetry(reqws.RetryConfig{
        MaxRetries:   5,
        InitialDelay: 200 * time.Millisecond,
        MaxDelay:     10 * time.Second,
        Multiplier:   2.0, // Exponential backoff
    }),
)

Retry Logic:

  • ✅ Retries on: 5xx errors, 429 (rate limit), network errors
  • ❌ No retry on: 4xx client errors (except 429)
  • Exponential backoff: 100ms → 200ms → 400ms → 800ms → max 5s
WebSocket Auto-Reconnection

Automatic reconnection when WebSocket connection drops:

// Default reconnection (10 attempts, 1s initial delay, 30s max)
err := client.WebSocketStreamWithReconnect(ctx, sendChan, receiveChan,
    reqws.WithPath("/ws/stream"),
    reqws.WithDefaultWebSocketReconnect(),
)

// Custom reconnection with callback
reconnectCount := 0
err := client.WebSocketStreamWithReconnect(ctx, sendChan, receiveChan,
    reqws.WithPath("/ws/stream"),
    reqws.WithWebSocketAutoReconnect(reqws.WebSocketConfig{
        AutoReconnect:        true,
        MaxReconnectAttempts: 5,
        ReconnectDelay:       2 * time.Second,
        MaxReconnectDelay:    60 * time.Second,
        ReconnectMultiplier:  2.0,
        OnReconnect: func() {
            reconnectCount++
            log.Printf("Reconnecting... attempt #%d", reconnectCount)
        },
    }),
)
Middleware/Hooks

Inject custom logic into the request/response pipeline:

Logging
resp, err := client.Do(ctx,
    reqws.GET("/api/users"),
    reqws.WithBeforeRequest(func(req *http.Request) error {
        log.Printf("→ %s %s", req.Method, req.URL)
        return nil
    }),
    reqws.WithAfterResponse(func(req *http.Request, resp *http.Response) error {
        log.Printf("← %d %s", resp.StatusCode, req.URL)
        return nil
    }),
    reqws.WithOnError(func(req *http.Request, err error) {
        log.Printf("✘ Error for %s: %v", req.URL, err)
    }),
)
Metrics/Tracing
startTime := time.Now()
resp, err := client.Do(ctx,
    reqws.GET("/api/users"),
    reqws.WithAfterResponse(func(req *http.Request, resp *http.Response) error {
        duration := time.Since(startTime)
        metrics.RecordHTTPRequest(req.Method, resp.StatusCode, duration)
        return nil
    }),
)
Dynamic Authentication
resp, err := client.Do(ctx,
    reqws.GET("/api/protected"),
    reqws.WithBeforeRequest(func(req *http.Request) error {
        token, err := getAuthToken() // Your auth logic
        if err != nil {
            return err
        }
        req.Header.Set("Authorization", "Bearer "+token)
        return nil
    }),
)
Custom Logger

Integrate with your existing logging solution (slog, zap, logrus, etc.):

// Example with slog
type SlogAdapter struct {
    logger *slog.Logger
}

func (s SlogAdapter) Debug(msg string, keysAndValues ...interface{}) {
    s.logger.Debug(msg, keysAndValues...)
}

func (s SlogAdapter) Info(msg string, keysAndValues ...interface{}) {
    s.logger.Info(msg, keysAndValues...)
}

func (s SlogAdapter) Error(msg string, keysAndValues ...interface{}) {
    s.logger.Error(msg, keysAndValues...)
}

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

    client := reqws.NewClient("https://api.example.com", 30*time.Second).
        WithLogger(SlogAdapter{logger})

    // All requests will now use your logger
    client.Request(ctx, reqws.GET("/users"))
}
Error Handling

Type-safe error handling with custom error types:

body, err := client.Request(ctx, reqws.GET("/api/users"))
if err != nil {
    // Check for HTTP errors
    var httpErr *reqws.HTTPError
    if errors.As(err, &httpErr) {
        log.Printf("HTTP Error: %d", httpErr.StatusCode)
        log.Printf("Response body: %s", httpErr.Body)

        if httpErr.StatusCode == 404 {
            // Handle not found
        } else if httpErr.StatusCode >= 500 {
            // Handle server error
        }
    }
    return err
}

// WebSocket errors
err := client.WebSocketStream(ctx, sendChan, receiveChan, ...)
if err != nil {
    var wsErr *reqws.WebSocketError
    if errors.As(err, &wsErr) {
        log.Printf("WebSocket Error: %s", wsErr.Reason)
        log.Printf("Underlying error: %v", wsErr.Err)
    }
}
File Upload

Upload files with multipart form data:

// Assuming you have a multipart.FileHeader from a form upload
resp, err := client.Do(ctx,
    reqws.POST("/upload"),
    reqws.WithFile("avatar", fileHeader),
    reqws.WithForm("user_id", "123"),
    reqws.WithForm("description", "Profile picture"),
)

API Reference

Client Creation
// NewClient creates a new HTTP client
client := reqws.NewClient(baseURL string, timeout time.Duration) *Client

// WithLogger sets a custom logger
client.WithLogger(logger Logger) *Client
HTTP Method Shortcuts
// Combines method + path in one call
GET(path string) RequestOption
POST(path string) RequestOption
PUT(path string) RequestOption
DELETE(path string) RequestOption
PATCH(path string) RequestOption
HEAD(path string) RequestOption
OPTIONS(path string) RequestOption
Request Options
// HTTP method and path (legacy - use shortcuts above instead)
WithMethod(method string) RequestOption // For custom methods like PROPFIND
WithPath(path string) RequestOption

// Query parameters
WithQueryParam(key, value string) RequestOption
WithQueryParams(params url.Values) RequestOption

// Request body
WithJSON(body interface{}) RequestOption // Explicit JSON body (recommended)
WithBody(body interface{}) RequestOption // Alias for WithJSON

// Headers and authentication
WithHeader(key, value string) RequestOption
WithBearerToken(token string) RequestOption // Auto adds "Bearer " prefix
WithBasicAuth(username, password string) RequestOption // Auto base64 encodes
WithAuth(token string) RequestOption // Generic auth (full header value)

// Form data and file upload
WithForm(key, value string) RequestOption
WithFile(formFieldName string, file *multipart.FileHeader) RequestOption

// Retry configuration
WithRetry(config RetryConfig) RequestOption
WithDefaultRetry() RequestOption

// WebSocket configuration
WithWebSocketAutoReconnect(config WebSocketConfig) RequestOption
WithDefaultWebSocketReconnect() RequestOption

// Security
WithInsecureSkipVerify() RequestOption // ⚠️ Only for testing!

// Middleware/Hooks
WithBeforeRequest(hook RequestHook) RequestOption
WithAfterResponse(hook ResponseHook) RequestOption
WithOnError(hook ErrorHook) RequestOption
Request Methods
// Request executes HTTP request and returns body bytes
// Returns error for non-2xx status codes
Request(ctx context.Context, opts ...RequestOption) ([]byte, error)

// Do returns full Response object
// Does NOT return error for non-2xx status codes (manual checking required)
Do(ctx context.Context, opts ...RequestOption) (*Response, error)

// WebSocketStream establishes WebSocket connection
WebSocketStream(ctx context.Context, sendChan <-chan interface{}, receiveChan chan<- WebSocketResponse, opts ...RequestOption) error

// WebSocketStreamWithReconnect with automatic reconnection
WebSocketStreamWithReconnect(ctx context.Context, sendChan <-chan interface{}, receiveChan chan<- WebSocketResponse, opts ...RequestOption) error
Response Methods
// JSON unmarshals response body to struct
resp.JSON(v interface{}) error

// String returns response body as string
resp.String() string

// Status code helpers
resp.IsSuccess() bool       // 2xx
resp.IsClientError() bool   // 4xx
resp.IsServerError() bool   // 5xx

Configuration Types

RetryConfig
type RetryConfig struct {
    MaxRetries   int           // Maximum retry attempts (default: 3)
    InitialDelay time.Duration // Initial delay (default: 100ms)
    MaxDelay     time.Duration // Maximum delay (default: 5s)
    Multiplier   float64       // Backoff multiplier (default: 2.0)
}
WebSocketConfig
type WebSocketConfig struct {
    AutoReconnect        bool          // Enable auto-reconnection
    MaxReconnectAttempts int           // Max reconnection attempts (0 = infinite)
    ReconnectDelay       time.Duration // Initial reconnection delay (default: 1s)
    MaxReconnectDelay    time.Duration // Maximum reconnection delay (default: 30s)
    ReconnectMultiplier  float64       // Backoff multiplier (default: 2.0)
    OnReconnect          func()        // Callback on each reconnection attempt
}

Comparison with Other Libraries

Feature go-reqws imroc/req net/http
HTTP Requests
WebSocket Support ✅ Built-in Manual setup
Auto Retry ✅ Smart logic Manual
WS Auto-Reconnect ✅ Built-in Manual
Middleware/Hooks Manual
Response Helpers Manual
Complexity ⭐⭐⭐⭐⭐ Simple ⭐⭐⭐ Moderate ⭐⭐ Low-level
Use Case Microservices + Real-time Comprehensive HTTP Full control

When to use go-reqws:

  • You need both HTTP and WebSocket in one library
  • Building microservices with real-time features
  • Want simplicity without sacrificing features
  • Need auto-reconnection for WebSocket

When NOT to use go-reqws:

  • You only need HTTP (use imroc/req or standard net/http)
  • You need advanced HTTP features (HTTP/2 push, etc.)
  • Maximum performance is critical (use lower-level libraries)

Complete Example

package main

import (
    "context"
    "errors"
    "log"
    "time"

    "github.com/gurizzu/go-reqws"
)

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    // Create client with custom logger
    client := reqws.NewClient("https://api.example.com", 30*time.Second)

    // HTTP Request with all features
    resp, err := client.Do(context.Background(),
        // Request configuration - clean and concise!
        reqws.GET("/api/users"),
        reqws.WithQueryParam("status", "active"),
        reqws.WithBearerToken("YOUR_TOKEN"),

        // Retry on failure
        reqws.WithDefaultRetry(),

        // Hooks for logging and metrics
        reqws.WithBeforeRequest(func(req *http.Request) error {
            log.Printf("→ Sending: %s %s", req.Method, req.URL)
            return nil
        }),
        reqws.WithAfterResponse(func(req *http.Request, resp *http.Response) error {
            log.Printf("← Received: %d", resp.StatusCode)
            return nil
        }),
        reqws.WithOnError(func(req *http.Request, err error) {
            log.Printf("✘ Error: %v", err)
        }),
    )

    if err != nil {
        var httpErr *reqws.HTTPError
        if errors.As(err, &httpErr) {
            log.Printf("HTTP Error: %d - %s", httpErr.StatusCode, httpErr.Body)
        }
        log.Fatal(err)
    }

    // Use response helpers
    if !resp.IsSuccess() {
        log.Fatalf("Request failed with status %d", resp.StatusCode)
    }

    var users []User
    if err := resp.JSON(&users); err != nil {
        log.Fatal(err)
    }

    log.Printf("Fetched %d users", len(users))

    // WebSocket with auto-reconnection
    sendChan := make(chan interface{})
    receiveChan := make(chan reqws.WebSocketResponse)

    go func() {
        err := client.WebSocketStreamWithReconnect(context.Background(),
            sendChan, receiveChan,
            reqws.WithPath("/ws/updates"),
            reqws.WithDefaultWebSocketReconnect(),
        )
        if err != nil {
            log.Printf("WebSocket error: %v", err)
        }
    }()

    // Send subscription message
    sendChan <- map[string]string{
        "action":  "subscribe",
        "channel": "user-updates",
    }

    // Receive real-time updates
    for msg := range receiveChan {
        if msg.Error != nil {
            log.Printf("WebSocket error: %v", msg.Error)
            continue
        }
        if msg.Closed {
            log.Println("Connection closed")
            break
        }
        log.Printf("Update received: %v", msg.Data)
    }
}

Security Considerations

TLS Certificate Verification

By default, go-reqws uses secure TLS certificate verification. Only disable it for testing/development:

// ⚠️ INSECURE - Only use for testing!
client.WebSocketStream(ctx, sendChan, receiveChan,
    reqws.WithPath("/ws/stream"),
    reqws.WithInsecureSkipVerify(), // Disables TLS verification
)

Never use WithInsecureSkipVerify() in production! This makes your application vulnerable to man-in-the-middle attacks.

Logging Sensitive Data

Be careful when using hooks to avoid logging sensitive information:

// ❌ BAD - Might log sensitive headers/body
reqws.WithBeforeRequest(func(req *http.Request) error {
    log.Printf("Request: %+v", req) // Could leak auth tokens!
    return nil
})

// ✅ GOOD - Log only non-sensitive data
reqws.WithBeforeRequest(func(req *http.Request) error {
    log.Printf("Request: %s %s", req.Method, req.URL.Path)
    return nil
})

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Development Setup
# Clone repository
git clone https://github.com/gurizzu/go-reqws.git
cd go-reqws

# Run tests
go test -v ./...

# Run with coverage
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Format code
go fmt ./...

# Lint
golangci-lint run

License

MIT License - see LICENSE file for details.

Acknowledgments

Inspired by:

  • imroc/req - Comprehensive Go HTTP client
  • coder/websocket - Excellent WebSocket library
  • Go community for feedback and best practices

Support


Made with ❤️ for the Go community

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents an HTTP/WebSocket client for making requests.

func NewClient

func NewClient(baseURL string, timeout time.Duration) *Client

NewClient creates a new HTTP client with the specified base URL and timeout.

The baseURL should not include a trailing slash. All request paths will be appended to this base URL.

Example:

client := reqws.NewClient("https://api.example.com", 30*time.Second)
body, err := client.Request(ctx, reqws.GET("/users"))

func NewRequests

func NewRequests(baseURL string, timeout time.Duration) *Client

NewRequests is deprecated. Use NewClient instead. Kept for backward compatibility.

func (*Client) Do

func (c *Client) Do(ctx context.Context, opts ...RequestOption) (*Response, error)

Do executes an HTTP request and returns the full Response object with body, headers, and status code. This method gives you full control - it does NOT automatically fail on non-2xx status codes.

Use this when you need: - Access to response headers - Manual handling of different status codes - Response helper methods (JSON, IsSuccess, etc.)

Unlike Request(), this does not return an error for non-2xx status codes. You must manually check resp.IsSuccess() or resp.StatusCode. Supports retry via WithRetry() or WithDefaultRetry() options.

Example:

resp, err := client.Do(ctx,
	reqws.GET("/users/1"),
	reqws.WithBearerToken("token"),
)
if err != nil {
	return err
}
if !resp.IsSuccess() {
	return fmt.Errorf("failed: %d", resp.StatusCode)
}
var user User
resp.JSON(&user)

func (*Client) Request

func (c *Client) Request(ctx context.Context, opts ...RequestOption) ([]byte, error)

Request executes an HTTP request and returns only the response body as bytes. This is the simple method for most use cases - it automatically fails on non-2xx status codes.

Returns an error if the status code is not 2xx. Supports retry via WithRetry() or WithDefaultRetry() options.

Example:

body, err := client.Request(ctx,
	reqws.GET("/users/1"),
	reqws.WithBearerToken("token"),
)

func (*Client) WebSocketStream

func (c *Client) WebSocketStream(ctx context.Context, sendChan <-chan interface{}, receiveChan chan<- WebSocketResponse, opts ...RequestOption) error

WebSocketStream - Persistent connection with channel-based communication

func (*Client) WebSocketStreamWithReconnect

func (c *Client) WebSocketStreamWithReconnect(ctx context.Context, sendChan <-chan interface{}, receiveChan chan<- WebSocketResponse, opts ...RequestOption) error

WebSocketStreamWithReconnect wraps WebSocketStream with automatic reconnection logic. If the connection drops, it will automatically attempt to reconnect with exponential backoff. Use WithWebSocketAutoReconnect() or WithDefaultWebSocketReconnect() to configure reconnection behavior.

func (*Client) WithLogger

func (c *Client) WithLogger(logger Logger) *Client

WithLogger sets a custom logger for the Client. The logger will be used for all HTTP and WebSocket operations. If no logger is provided, logging is disabled by default.

Example:

client := reqws.NewClient("https://api.example.com", 30*time.Second).
	WithLogger(myLogger)

type ErrorHook

type ErrorHook func(req *http.Request, err error)

ErrorHook is a function that runs when an error occurs during the request. It receives the original request and the error that occurred. This hook cannot modify the error, it's primarily for logging/monitoring.

type HTTPError

type HTTPError struct {
	StatusCode int
	Body       []byte
	Message    string
}

HTTPError represents an HTTP error response with a non-2xx status code.

func NewHTTPError

func NewHTTPError(statusCode int, body []byte) *HTTPError

NewHTTPError creates a new HTTPError with the given status code and response body.

func (*HTTPError) Error

func (e *HTTPError) Error() string

type Logger

type Logger interface {
	Debug(msg string, keysAndValues ...interface{})
	Info(msg string, keysAndValues ...interface{})
	Error(msg string, keysAndValues ...interface{})
}

Logger is an interface for logging operations. Users can provide their own implementation (slog, zap, logrus, etc.)

type RequestHook

type RequestHook func(req *http.Request) error

RequestHook is a function that runs before a request is sent. It receives the prepared http.Request and can modify it or return an error to abort the request.

type RequestOption

type RequestOption func(*requestConfig)

func DELETE

func DELETE(path string) RequestOption

DELETE creates a DELETE request to the specified path. This is a shortcut for WithMethod("DELETE") + WithPath(path).

Example:

client.Request(ctx, reqws.DELETE("/users/1"))

func GET

func GET(path string) RequestOption

GET creates a GET request to the specified path. This is a shortcut for WithMethod("GET") + WithPath(path).

Example:

body, err := client.Request(ctx, reqws.GET("/users"))
resp, err := client.Do(ctx, reqws.GET("/users"))
func HEAD(path string) RequestOption

HEAD creates a HEAD request to the specified path. Useful for checking if a resource exists without downloading it.

Example:

resp, err := client.Do(ctx, reqws.HEAD("/users/1"))

func OPTIONS

func OPTIONS(path string) RequestOption

OPTIONS creates an OPTIONS request to the specified path. Useful for CORS preflight requests.

Example:

resp, err := client.Do(ctx, reqws.OPTIONS("/api"))

func PATCH

func PATCH(path string) RequestOption

PATCH creates a PATCH request to the specified path. This is a shortcut for WithMethod("PATCH") + WithPath(path).

Example:

client.Do(ctx, reqws.PATCH("/users/1"), reqws.WithJSON(updates))

func POST

func POST(path string) RequestOption

POST creates a POST request to the specified path. This is a shortcut for WithMethod("POST") + WithPath(path).

Example:

client.Do(ctx, reqws.POST("/users"), reqws.WithJSON(user))

func PUT

func PUT(path string) RequestOption

PUT creates a PUT request to the specified path. This is a shortcut for WithMethod("PUT") + WithPath(path).

Example:

client.Do(ctx, reqws.PUT("/users/1"), reqws.WithJSON(user))

func WithAfterResponse

func WithAfterResponse(hook ResponseHook) RequestOption

WithAfterResponse adds a hook that runs after receiving the HTTP response. Multiple hooks can be added and will be executed in the order they were added. If any hook returns an error, the response is treated as failed.

Use cases: - Log response details - Record metrics (latency, status codes) - Validate response structure - Custom retry logic based on response

func WithAuth

func WithAuth(token string) RequestOption

WithAuth sets the Authorization header with the provided token. The token should include the auth scheme (e.g., "Bearer xxx").

For Bearer tokens specifically, consider using WithBearerToken() instead.

Example:

client.Request(ctx, reqws.GET("/protected"), reqws.WithAuth("Bearer abc123"))

func WithBasicAuth

func WithBasicAuth(username, password string) RequestOption

WithBasicAuth sets the Authorization header with Basic authentication. The credentials will be automatically base64 encoded.

Example:

client.Request(ctx,
	reqws.GET("/protected"),
	reqws.WithBasicAuth("username", "password"),
)

func WithBearerToken

func WithBearerToken(token string) RequestOption

WithBearerToken sets the Authorization header with a Bearer token. This is a convenience method that automatically prepends "Bearer " to the token.

Example:

client.Request(ctx,
	reqws.GET("/protected"),
	reqws.WithBearerToken("abc123"),
)

func WithBeforeRequest

func WithBeforeRequest(hook RequestHook) RequestOption

WithBeforeRequest adds a hook that runs before the HTTP request is sent. Multiple hooks can be added and will be executed in the order they were added. If any hook returns an error, the request is aborted.

Use cases: - Add custom headers - Log request details - Modify request body - Add authentication tokens dynamically

func WithBody

func WithBody(body interface{}) RequestOption

WithBody sets the request body. The body will be automatically marshaled to JSON.

For more explicit JSON handling, consider using WithJSON() instead.

Example:

client.Do(ctx, reqws.POST("/users"), reqws.WithBody(user))

func WithDefaultRetry

func WithDefaultRetry() RequestOption

WithDefaultRetry enables retry with default configuration. - MaxRetries: 3 - InitialDelay: 100ms - MaxDelay: 5s - Multiplier: 2.0 (exponential backoff)

func WithDefaultWebSocketReconnect

func WithDefaultWebSocketReconnect() RequestOption

WithDefaultWebSocketReconnect enables WebSocket auto-reconnection with default configuration. - MaxReconnectAttempts: 10 - ReconnectDelay: 1s - MaxReconnectDelay: 30s - ReconnectMultiplier: 2.0 (exponential backoff)

func WithFile

func WithFile(formFieldName string, file *multipart.FileHeader) RequestOption

WithFile adds a file to the request for multipart/form-data upload. The formFieldName is the name of the form field (defaults to "file" if empty).

Example:

client.Do(ctx,
	reqws.POST("/upload"),
	reqws.WithFile("avatar", fileHeader),
)

func WithForm

func WithForm(key, value string) RequestOption

WithForm adds a form field for multipart/form-data requests. Use this together with WithFile() for file uploads.

Example:

client.Do(ctx,
	reqws.POST("/upload"),
	reqws.WithFile("avatar", fileHeader),
	reqws.WithForm("user_id", "123"),
	reqws.WithForm("description", "Profile picture"),
)

func WithHeader

func WithHeader(key, value string) RequestOption

WithHeader adds a custom HTTP header to the request. Can be called multiple times to add multiple headers.

Example:

client.Request(ctx,
	reqws.GET("/api/data"),
	reqws.WithHeader("X-API-Version", "v1"),
	reqws.WithHeader("X-Request-ID", "12345"),
)

func WithInsecureSkipVerify

func WithInsecureSkipVerify() RequestOption

WithInsecureSkipVerify disables TLS certificate verification. WARNING: This should only be used for testing or development. Using this in production makes your application vulnerable to man-in-the-middle attacks.

func WithJSON

func WithJSON(body interface{}) RequestOption

WithJSON sets the request body as JSON. This is an explicit alias for WithBody() for better code clarity. The body will be marshaled to JSON automatically.

Example:

client.Do(ctx,
	reqws.POST("/users"),
	reqws.WithJSON(map[string]string{
		"name": "John Doe",
		"email": "john@example.com",
	}),
)

func WithMethod

func WithMethod(method string) RequestOption

WithMethod sets a custom HTTP method for the request. For common methods (GET, POST, PUT, DELETE, PATCH), consider using the shortcut functions instead.

Use this for custom or less common HTTP methods like PROPFIND, MKCOL, etc.

Example:

client.Do(ctx, reqws.WithMethod("PROPFIND"), reqws.WithPath("/files"))

func WithOnError

func WithOnError(hook ErrorHook) RequestOption

WithOnError adds a hook that runs when an error occurs. Multiple hooks can be added and will be executed in the order they were added. These hooks cannot modify the error, they're for observability.

Use cases: - Log errors - Send error alerts - Record error metrics - Trace error propagation

func WithPath

func WithPath(path string) RequestOption

WithPath sets the request path. The path is automatically prefixed with "/" if not present.

Note: For common cases, consider using HTTP method shortcuts (GET, POST, etc.) which combine method and path.

Example:

// Legacy approach
client.Request(ctx, reqws.WithMethod("GET"), reqws.WithPath("/users"))

// Better: use shortcut instead
client.Request(ctx, reqws.GET("/users"))

func WithQueryParam

func WithQueryParam(key, value string) RequestOption

WithQueryParam adds a single query parameter to the request URL. Can be called multiple times to add multiple parameters.

Example:

client.Request(ctx,
	reqws.GET("/users"),
	reqws.WithQueryParam("status", "active"),
	reqws.WithQueryParam("limit", "10"),
)

func WithQueryParams

func WithQueryParams(params url.Values) RequestOption

WithQueryParams adds multiple query parameters at once from url.Values. For adding single parameters, use WithQueryParam() instead.

Example:

params := url.Values{}
params.Add("status", "active")
params.Add("limit", "10")
client.Request(ctx, reqws.GET("/users"), reqws.WithQueryParams(params))

func WithRetry

func WithRetry(config RetryConfig) RequestOption

WithRetry enables retry with custom configuration.

func WithWebSocketAutoReconnect

func WithWebSocketAutoReconnect(config WebSocketConfig) RequestOption

WithWebSocketAutoReconnect enables WebSocket auto-reconnection with custom configuration.

type Requests

type Requests = Client

Requests is deprecated. Use Client instead. Kept for backward compatibility.

type Response

type Response struct {
	Body       []byte
	Headers    http.Header
	StatusCode int
}

Response represents an HTTP response with helper methods.

func (*Response) IsClientError

func (r *Response) IsClientError() bool

IsClientError returns true if the status code is 4xx (400-499).

func (*Response) IsServerError

func (r *Response) IsServerError() bool

IsServerError returns true if the status code is 5xx (500-599).

func (*Response) IsSuccess

func (r *Response) IsSuccess() bool

IsSuccess returns true if the status code is 2xx (200-299).

func (*Response) JSON

func (r *Response) JSON(v interface{}) error

JSON unmarshals the response body into the provided value. The value should be a pointer to the target struct.

func (*Response) String

func (r *Response) String() string

String returns the response body as a string.

type ResponseHook

type ResponseHook func(req *http.Request, resp *http.Response) error

ResponseHook is a function that runs after a response is received. It receives both the original request and the response. Return an error to treat the response as failed.

type RetryConfig

type RetryConfig struct {
	MaxRetries   int           // Maximum number of retry attempts (default: 3)
	InitialDelay time.Duration // Initial delay before first retry (default: 100ms)
	MaxDelay     time.Duration // Maximum delay between retries (default: 5s)
	Multiplier   float64       // Backoff multiplier (default: 2.0)
}

RetryConfig defines the configuration for retry behavior.

func DefaultRetryConfig

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns a sensible default retry configuration.

type WebSocketConfig

type WebSocketConfig struct {
	AutoReconnect        bool          // Enable automatic reconnection on disconnect
	MaxReconnectAttempts int           // Maximum number of reconnection attempts (0 = infinite)
	ReconnectDelay       time.Duration // Initial delay before reconnection
	MaxReconnectDelay    time.Duration // Maximum delay between reconnections
	ReconnectMultiplier  float64       // Backoff multiplier for reconnection delay
	OnReconnect          func()        // Callback function called on each reconnection attempt
}

WebSocketConfig defines configuration for WebSocket connections.

func DefaultWebSocketConfig

func DefaultWebSocketConfig() WebSocketConfig

DefaultWebSocketConfig returns a sensible default WebSocket configuration.

type WebSocketError

type WebSocketError struct {
	Reason string
	Err    error
}

WebSocketError represents a WebSocket-specific error.

func NewWebSocketError

func NewWebSocketError(reason string, err error) *WebSocketError

NewWebSocketError creates a new WebSocketError with the given reason and underlying error.

func (*WebSocketError) Error

func (e *WebSocketError) Error() string

func (*WebSocketError) Unwrap

func (e *WebSocketError) Unwrap() error

Unwrap returns the underlying error for error chain support.

type WebSocketResponse

type WebSocketResponse struct {
	Data    interface{}
	RawData []byte
	Error   error
	Closed  bool
}

Directories

Path Synopsis
examples
http_advanced command
websocket_basic command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL