Resty

Simple HTTP and REST client for Go. Maintains performance through internal use of net/http while providing more user-friendly API. Built-in automatic JSON/XML parsing, OAuth/Bearer authentication, retry functionality, debugging, and middleware support.

HTTP ClientGoRESTMiddlewareAuthenticationJSON

GitHub Overview

go-resty/resty

Simple HTTP, REST, and SSE client library for Go

Stars11,056
Watchers100
Forks764
Created:August 28, 2015
Language:Go
License:MIT License

Topics

backoffcircuit-breakercurl-commanddigest-authenticationgogo-librarygo-restygolanggolang-libraryhacktoberfesthttp-clienthttp-traceload-balancermiddlewareredirectsrest-clientretryservice-discoverysrv-recordsse-client

Star History

go-resty/resty Star History
Data as of: 7/18/2025, 01:38 AM

Library

Resty

Overview

Resty is a "Simple HTTP and REST client library for Go" that has been widely adopted as a native HTTP client in the Go ecosystem, designed as a high-level HTTP library that emphasizes "balance between simplicity and rich functionality." Built as a powerful abstraction on top of the net/http package, it provides chainable APIs, automatic retry functionality, middleware systems, diverse authentication options, and automatic JSON/XML processing. It enables intuitive and efficient HTTP communication for Go developers and is utilized across a wide range of scenarios from REST API consumption to web service development.

Details

Resty 2025 edition (v3 series) continues to evolve as a mature solution for Go HTTP clients. Designed around three main components - Client, Request, and Response - it comprehensively manages the entire HTTP request lifecycle. With thread-safe implementation (using sync.RWMutex) ensuring safe usage from multiple goroutines, it provides enterprise-grade HTTP communication requirements including a rich middleware system, automatic retry functionality, OAuth/Basic/JWT authentication, Server-Sent Events (SSE) support, tracing functionality, and custom DNS resolvers. Compared to net/http, Resty offers improved development efficiency through high-level APIs and rich built-in functionality.

Key Features

  • Chainable API: Intuitive and fluent interface for concise code writing
  • Powerful Middleware System: Customization of request/response processing
  • Automatic Retry Functionality: Configurable retry conditions and backoff strategies
  • Comprehensive Authentication Support: Built-in support for Basic, Bearer, Digest, and OAuth authentication
  • Automatic JSON/XML Processing: Automatic serialization/deserialization of structs
  • Thread-Safe Design: Safe usage in concurrent processing environments

Pros and Cons

Pros

  • Significantly more concise and readable code writing compared to net/http
  • High development efficiency and productivity improvement through rich built-in functionality
  • High customizability through powerful middleware system
  • Robustness through automatic retry and error handling
  • Enterprise-level support through comprehensive authentication options
  • Safety in concurrent processing through thread-safe design

Cons

  • Slightly higher learning cost and abstraction level compared to net/http
  • Minor increase in binary size due to additional external dependencies
  • Low-level control may be limited for very specific HTTP requirements
  • May be overkill when net/http is sufficient for simple use cases
  • Migration cost due to API changes during version upgrades
  • May require understanding of internal implementation during debugging

Reference Pages

Code Examples

Installation and Basic Setup

// Add to go.mod
require resty.dev/v3

// Or install with Go 1.17+
go get resty.dev/v3
package main

import (
    "fmt"
    "resty.dev/v3"
)

// Basic client initialization
func main() {
    // Create client (always use defer Close for resource management)
    client := resty.New()
    defer client.Close()
    
    // Basic configuration
    client.SetBaseURL("https://api.example.com").
        SetTimeout(30 * time.Second).
        SetRetryCount(3).
        SetRetryWaitTime(1 * time.Second).
        SetHeader("User-Agent", "MyApp/1.0").
        SetHeader("Accept", "application/json")
}

// Advanced client configuration
func createAdvancedClient() *resty.Client {
    client := resty.New()
    
    // Enable debug mode
    client.SetDebug(true)
    
    // Proxy configuration
    client.SetProxy("http://proxy.example.com:8080")
    
    // SSL/TLS configuration
    client.SetRootCertificate("/path/to/root/cert.pem").
        SetClientCertificates("/path/to/client.crt", "/path/to/client.key")
    
    // Redirect configuration
    client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(5))
    
    return client
}

Basic Requests (GET/POST/PUT/DELETE)

package main

import (
    "fmt"
    "resty.dev/v3"
    "time"
)

// User data structures
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

type LoginResponse struct {
    Token   string `json:"token"`
    UserID  int    `json:"user_id"`
    Message string `json:"message"`
}

type ErrorResponse struct {
    Error   string `json:"error"`
    Code    int    `json:"code"`
    Details string `json:"details"`
}

func main() {
    client := resty.New()
    defer client.Close()
    
    client.SetBaseURL("https://api.example.com")
    
    // GET request (simple)
    resp, err := client.R().Get("users")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    fmt.Printf("Status: %s\n", resp.Status())
    fmt.Printf("Body: %s\n", resp.String())
    
    // GET request with structured response
    var users []User
    resp, err = client.R().
        SetResult(&users).
        Get("users")
    
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    
    if resp.IsSuccess() {
        fmt.Printf("Users retrieved: %d items\n", len(users))
        for _, user := range users {
            fmt.Printf("User: %s (%s)\n", user.Name, user.Email)
        }
    }
    
    // GET request with query parameters
    var paginatedUsers []User
    resp, err = client.R().
        SetQueryParams(map[string]string{
            "page":     "1",
            "limit":    "10",
            "sort":     "created_at",
            "order":    "desc",
        }).
        SetResult(&paginatedUsers).
        Get("users")
    
    // POST request (login example)
    loginReq := LoginRequest{
        Username: "testuser",
        Password: "secret123",
    }
    
    var loginResp LoginResponse
    var errResp ErrorResponse
    
    resp, err = client.R().
        SetBody(loginReq).
        SetResult(&loginResp).
        SetError(&errResp).
        Post("https://api.example.com/login")
    
    if err != nil {
        fmt.Printf("Network error: %v\n", err)
        return
    }
    
    if resp.IsSuccess() {
        fmt.Printf("Login successful: %s\n", loginResp.Token)
        fmt.Printf("User ID: %d\n", loginResp.UserID)
    } else {
        fmt.Printf("Login failed: %s (Code: %d)\n", errResp.Error, errResp.Code)
    }
    
    // POST request (create user)
    newUser := User{
        Name:  "John Doe",
        Email: "[email protected]",
        Age:   30,
    }
    
    var createdUser User
    resp, err = client.R().
        SetHeader("Authorization", "Bearer "+loginResp.Token).
        SetBody(newUser).
        SetResult(&createdUser).
        SetError(&errResp).
        Post("users")
    
    if resp.IsSuccess() {
        fmt.Printf("User created: ID=%d, Name=%s\n", createdUser.ID, createdUser.Name)
    }
    
    // PUT request (update user)
    updatedData := User{
        ID:    createdUser.ID,
        Name:  "John Smith",
        Email: "[email protected]",
        Age:   31,
    }
    
    resp, err = client.R().
        SetHeader("Authorization", "Bearer "+loginResp.Token).
        SetBody(updatedData).
        SetResult(&createdUser).
        Put(fmt.Sprintf("users/%d", createdUser.ID))
    
    // DELETE request
    resp, err = client.R().
        SetHeader("Authorization", "Bearer "+loginResp.Token).
        Delete(fmt.Sprintf("users/%d", createdUser.ID))
    
    if resp.IsSuccess() {
        fmt.Println("User deleted successfully")
    }
}

// Form data and file operations
func formAndFileExamples() {
    client := resty.New()
    defer client.Close()
    
    // Form data submission
    resp, err := client.R().
        SetFormData(map[string]string{
            "username": "testuser",
            "email":    "[email protected]",
            "category": "premium",
        }).
        Post("https://api.example.com/register")
    
    // File upload
    resp, err = client.R().
        SetFile("document", "/path/to/document.pdf").
        SetFormData(map[string]string{
            "description": "Important document",
            "category":    "legal",
        }).
        SetHeader("Authorization", "Bearer your-token").
        Post("https://api.example.com/upload")
    
    // Multiple file upload
    resp, err = client.R().
        SetFiles(map[string]string{
            "document": "/path/to/document.pdf",
            "image":    "/path/to/image.jpg",
            "data":     "/path/to/data.json",
        }).
        SetFormData(map[string]string{
            "title":       "Multiple files",
            "description": "Batch upload",
        }).
        Post("https://api.example.com/upload/batch")
    
    if err != nil {
        fmt.Printf("Upload error: %v\n", err)
        return
    }
    
    if resp.IsSuccess() {
        fmt.Println("Files uploaded successfully")
    }
}

Authentication and Security Configuration

package main

import (
    "fmt"
    "resty.dev/v3"
    "crypto/tls"
)

// Basic authentication
func basicAuthExample() {
    client := resty.New()
    defer client.Close()
    
    // Client-wide Basic authentication
    client.SetBasicAuth("username", "password")
    
    resp, err := client.R().Get("https://api.example.com/protected")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    
    fmt.Printf("Response: %s\n", resp.String())
    
    // Per-request Basic authentication
    resp, err = client.R().
        SetBasicAuth("user", "pass").
        Get("https://api.example.com/secure")
}

// Bearer Token authentication
func bearerTokenExample() {
    client := resty.New()
    defer client.Close()
    
    // Client-wide Bearer token
    client.SetAuthToken("your-jwt-token")
    
    resp, err := client.R().Get("https://api.example.com/user/profile")
    
    // Per-request Bearer token
    resp, err = client.R().
        SetAuthToken("specific-token").
        Get("https://api.example.com/admin/data")
        
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
}

// Custom authentication scheme
func customAuthExample() {
    client := resty.New()
    defer client.Close()
    
    // API Key authentication
    client.SetHeader("X-API-Key", "your-api-key")
    
    // Custom authentication header
    resp, err := client.R().
        SetHeader("X-Custom-Auth", "custom-token-value").
        SetHeader("X-Client-ID", "your-client-id").
        Get("https://api.example.com/data")
        
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
}

// OAuth 2.0 implementation example
type OAuthTokenResponse struct {
    AccessToken  string `json:"access_token"`
    TokenType    string `json:"token_type"`
    ExpiresIn    int    `json:"expires_in"`
    RefreshToken string `json:"refresh_token"`
}

func oauth2Example() {
    client := resty.New()
    defer client.Close()
    
    // OAuth 2.0 token acquisition
    var tokenResp OAuthTokenResponse
    resp, err := client.R().
        SetBasicAuth("client_id", "client_secret").
        SetFormData(map[string]string{
            "grant_type": "client_credentials",
            "scope":      "read write",
        }).
        SetResult(&tokenResp).
        Post("https://auth.example.com/oauth2/token")
    
    if err != nil || !resp.IsSuccess() {
        fmt.Printf("OAuth token acquisition failed: %v\n", err)
        return
    }
    
    // Use acquired token
    accessToken := tokenResp.AccessToken
    
    var userData interface{}
    resp, err = client.R().
        SetAuthToken(accessToken).
        SetResult(&userData).
        Get("https://api.example.com/user/profile")
    
    if resp.IsSuccess() {
        fmt.Printf("User data: %+v\n", userData)
    }
}

// TLS/SSL detailed configuration
func tlsConfigExample() {
    client := resty.New()
    defer client.Close()
    
    // Custom TLS configuration
    client.SetTLSClientConfig(&tls.Config{
        InsecureSkipVerify: false,                    // Enable certificate verification
        MinVersion:         tls.VersionTLS12,         // Minimum TLS version
        MaxVersion:         tls.VersionTLS13,         // Maximum TLS version
        ServerName:         "api.example.com",        // Server name verification
    })
    
    // Client certificate configuration
    client.SetClientRootCertificate("/path/to/root/ca.crt")
    client.SetClientCertificates("/path/to/client.crt", "/path/to/client.key")
    
    // Disable certificate verification (for development only)
    client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
    
    resp, err := client.R().Get("https://secure-api.example.com/data")
    if err != nil {
        fmt.Printf("TLS connection error: %v\n", err)
        return
    }
    
    fmt.Printf("Secure response: %s\n", resp.String())
}

Middleware System and Advanced Features

package main

import (
    "fmt"
    "time"
    "resty.dev/v3"
)

// Request middleware
func requestMiddlewareExample() {
    client := resty.New()
    defer client.Close()
    
    // Request logging middleware
    client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
        fmt.Printf("Request: %s %s\n", req.Method, req.URL)
        fmt.Printf("Headers: %+v\n", req.Header)
        return nil
    })
    
    // Request timestamp middleware
    client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
        req.SetHeader("X-Request-Time", time.Now().Format(time.RFC3339))
        req.SetHeader("X-Request-ID", generateRequestID())
        return nil
    })
    
    // Response middleware
    client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
        fmt.Printf("Response: %s (%s)\n", resp.Status(), resp.Time())
        fmt.Printf("Response size: %d bytes\n", len(resp.Body()))
        return nil
    })
    
    // Error handling middleware
    client.OnError(func(req *resty.Request, err error) {
        fmt.Printf("Request error: %s %s - %v\n", req.Method, req.URL, err)
    })
    
    resp, err := client.R().Get("https://api.example.com/data")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

// Authentication middleware
func authMiddlewareExample() {
    client := resty.New()
    defer client.Close()
    
    var currentToken string
    
    // Automatic token attachment middleware
    client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
        if currentToken != "" {
            req.SetAuthToken(currentToken)
        }
        return nil
    })
    
    // Token refresh middleware
    client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
        if resp.StatusCode() == 401 {
            fmt.Println("Token expired, refreshing...")
            
            // Token refresh logic
            newToken, err := refreshAuthToken(c)
            if err != nil {
                return err
            }
            
            currentToken = newToken
            fmt.Println("Token refreshed successfully")
        }
        return nil
    })
    
    resp, err := client.R().Get("https://api.example.com/protected/data")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

// Rate limiting middleware
func rateLimitingExample() {
    client := resty.New()
    defer client.Close()
    
    // Rate limiting middleware
    client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
        if resp.StatusCode() == 429 { // Too Many Requests
            retryAfter := resp.Header().Get("Retry-After")
            if retryAfter != "" {
                fmt.Printf("Rate limited, waiting %s seconds\n", retryAfter)
                // Implement wait logic
                time.Sleep(5 * time.Second)
            }
        }
        return nil
    })
    
    // Request counter middleware
    requestCount := 0
    client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
        requestCount++
        req.SetHeader("X-Request-Count", fmt.Sprintf("%d", requestCount))
        return nil
    })
}

// Utility functions
func generateRequestID() string {
    return fmt.Sprintf("req-%d", time.Now().UnixNano())
}

func refreshAuthToken(client *resty.Client) (string, error) {
    var tokenResp struct {
        Token string `json:"access_token"`
    }
    
    resp, err := client.R().
        SetBasicAuth("client_id", "client_secret").
        SetFormData(map[string]string{
            "grant_type": "refresh_token",
            "refresh_token": "stored_refresh_token",
        }).
        SetResult(&tokenResp).
        Post("https://auth.example.com/token")
    
    if err != nil || !resp.IsSuccess() {
        return "", fmt.Errorf("token refresh failed: %v", err)
    }
    
    return tokenResp.Token, nil
}

Error Handling and Retry Functionality

package main

import (
    "fmt"
    "time"
    "resty.dev/v3"
)

// Comprehensive error handling
func errorHandlingExample() {
    client := resty.New()
    defer client.Close()
    
    // Global retry configuration
    client.SetRetryCount(3).
        SetRetryWaitTime(1 * time.Second).
        SetRetryMaxWaitTime(5 * time.Second).
        SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
            // Custom backoff strategy
            return time.Duration(resp.Request.Attempt) * time.Second, nil
        })
    
    // Retry condition configuration
    client.AddRetryCondition(func(r *resty.Response, err error) bool {
        // Retry on network errors
        if err != nil {
            return true
        }
        // Retry on server errors
        if r.StatusCode() >= 500 {
            return true
        }
        // Retry on rate limiting
        if r.StatusCode() == 429 {
            return true
        }
        return false
    })
    
    var result interface{}
    var errorResp struct {
        Error   string `json:"error"`
        Code    int    `json:"code"`
        Message string `json:"message"`
    }
    
    resp, err := client.R().
        SetResult(&result).
        SetError(&errorResp).
        Get("https://api.example.com/unreliable-endpoint")
    
    if err != nil {
        fmt.Printf("Network error: %v\n", err)
        return
    }
    
    switch resp.StatusCode() {
    case 200:
        fmt.Printf("Success: %+v\n", result)
    case 400:
        fmt.Printf("Bad request: %s\n", errorResp.Error)
    case 401:
        fmt.Printf("Unauthorized: %s\n", errorResp.Message)
    case 403:
        fmt.Printf("Forbidden: %s\n", errorResp.Message)
    case 404:
        fmt.Printf("Not found: %s\n", errorResp.Error)
    case 429:
        fmt.Printf("Rate limited: %s\n", errorResp.Message)
    case 500:
        fmt.Printf("Server error: %s\n", errorResp.Error)
    default:
        fmt.Printf("Unexpected status: %d - %s\n", resp.StatusCode(), resp.String())
    }
}

// Custom error handling with detailed information
type APIError struct {
    StatusCode int    `json:"status_code"`
    Error      string `json:"error"`
    Message    string `json:"message"`
    Details    string `json:"details"`
    RequestID  string `json:"request_id"`
}

func (e APIError) String() string {
    return fmt.Sprintf("API Error %d: %s - %s (Request ID: %s)", 
        e.StatusCode, e.Error, e.Message, e.RequestID)
}

func advancedErrorHandling() {
    client := resty.New()
    defer client.Close()
    
    client.SetBaseURL("https://api.example.com")
    
    // Error response processing middleware
    client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {
        if !resp.IsSuccess() {
            var apiError APIError
            if err := resp.Unmarshal(&apiError); err == nil {
                return fmt.Errorf("API error: %s", apiError.String())
            }
            return fmt.Errorf("HTTP error: %d - %s", resp.StatusCode(), resp.String())
        }
        return nil
    })
    
    var users []User
    resp, err := client.R().
        SetResult(&users).
        Get("users")
    
    if err != nil {
        fmt.Printf("Request failed: %v\n", err)
        return
    }
    
    fmt.Printf("Retrieved %d users\n", len(users))
}

// Circuit breaker implementation
type CircuitBreaker struct {
    failureCount int
    threshold    int
    timeout      time.Duration
    lastFailure  time.Time
    state        string // "closed", "open", "half-open"
}

func NewCircuitBreaker(threshold int, timeout time.Duration) *CircuitBreaker {
    return &CircuitBreaker{
        threshold: threshold,
        timeout:   timeout,
        state:     "closed",
    }
}

func (cb *CircuitBreaker) Call(fn func() (*resty.Response, error)) (*resty.Response, error) {
    if cb.state == "open" {
        if time.Since(cb.lastFailure) > cb.timeout {
            cb.state = "half-open"
            fmt.Println("Circuit breaker: half-open state")
        } else {
            return nil, fmt.Errorf("circuit breaker is open")
        }
    }
    
    resp, err := fn()
    
    if err != nil || (resp != nil && resp.StatusCode() >= 500) {
        cb.failureCount++
        cb.lastFailure = time.Now()
        
        if cb.failureCount >= cb.threshold {
            cb.state = "open"
            fmt.Printf("Circuit breaker opened after %d failures\n", cb.failureCount)
        }
        
        return resp, err
    }
    
    // Success - reset circuit breaker
    cb.failureCount = 0
    cb.state = "closed"
    return resp, nil
}

func circuitBreakerExample() {
    client := resty.New()
    defer client.Close()
    
    cb := NewCircuitBreaker(3, 30*time.Second)
    
    for i := 0; i < 10; i++ {
        resp, err := cb.Call(func() (*resty.Response, error) {
            return client.R().Get("https://api.example.com/unreliable")
        })
        
        if err != nil {
            fmt.Printf("Attempt %d failed: %v\n", i+1, err)
        } else {
            fmt.Printf("Attempt %d succeeded: %s\n", i+1, resp.Status())
        }
        
        time.Sleep(1 * time.Second)
    }
}

Performance Optimization and Concurrent Processing

package main

import (
    "fmt"
    "sync"
    "context"
    "time"
    "resty.dev/v3"
)

// Concurrent request processing
func concurrentRequests() {
    client := resty.New()
    defer client.Close()
    
    client.SetBaseURL("https://api.example.com")
    
    urls := []string{
        "users",
        "posts",
        "comments",
        "categories",
        "tags",
    }
    
    // Using sync.WaitGroup for concurrent processing
    var wg sync.WaitGroup
    results := make(chan string, len(urls))
    
    for _, url := range urls {
        wg.Add(1)
        go func(endpoint string) {
            defer wg.Done()
            
            resp, err := client.R().Get(endpoint)
            if err != nil {
                results <- fmt.Sprintf("Error %s: %v", endpoint, err)
                return
            }
            
            results <- fmt.Sprintf("Success %s: %d bytes", endpoint, len(resp.Body()))
        }(url)
    }
    
    // Wait for all requests to complete
    go func() {
        wg.Wait()
        close(results)
    }()
    
    // Collect results
    for result := range results {
        fmt.Println(result)
    }
}

// Controlled concurrent processing with semaphore
func controlledConcurrency() {
    client := resty.New()
    defer client.Close()
    
    client.SetBaseURL("https://api.example.com")
    
    userIDs := make([]int, 50)
    for i := range userIDs {
        userIDs[i] = i + 1
    }
    
    // Limit concurrent requests to 5
    semaphore := make(chan struct{}, 5)
    var wg sync.WaitGroup
    
    for _, userID := range userIDs {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            
            // Acquire semaphore
            semaphore <- struct{}{}
            defer func() { <-semaphore }()
            
            var user User
            resp, err := client.R().
                SetResult(&user).
                Get(fmt.Sprintf("users/%d", id))
            
            if err != nil {
                fmt.Printf("Error getting user %d: %v\n", id, err)
                return
            }
            
            if resp.IsSuccess() {
                fmt.Printf("User %d: %s\n", id, user.Name)
            }
        }(userID)
    }
    
    wg.Wait()
    fmt.Println("All requests completed")
}

// Batch processing with rate limiting
func batchProcessing() {
    client := resty.New()
    defer client.Close()
    
    client.SetBaseURL("https://api.example.com")
    
    userIDs := make([]int, 100)
    for i := range userIDs {
        userIDs[i] = i + 1
    }
    
    batchSize := 10
    delayBetweenBatches := 1 * time.Second
    
    for i := 0; i < len(userIDs); i += batchSize {
        end := i + batchSize
        if end > len(userIDs) {
            end = len(userIDs)
        }
        
        batch := userIDs[i:end]
        processBatch(client, batch)
        
        // Wait between batches to avoid rate limiting
        if end < len(userIDs) {
            time.Sleep(delayBetweenBatches)
        }
        
        fmt.Printf("Batch %d completed: processed %d users\n", i/batchSize+1, len(batch))
    }
}

func processBatch(client *resty.Client, userIDs []int) {
    var wg sync.WaitGroup
    
    for _, userID := range userIDs {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            
            var user User
            resp, err := client.R().
                SetResult(&user).
                Get(fmt.Sprintf("users/%d", id))
            
            if err != nil {
                fmt.Printf("Error: %v\n", err)
                return
            }
            
            if resp.IsSuccess() {
                fmt.Printf("Processed user %d: %s\n", id, user.Name)
            }
        }(userID)
    }
    
    wg.Wait()
}

// Context-based timeout control
func contextTimeoutExample() {
    client := resty.New()
    defer client.Close()
    
    // Create context with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    var result interface{}
    resp, err := client.R().
        SetContext(ctx).
        SetResult(&result).
        Get("https://api.example.com/slow-endpoint")
    
    if err != nil {
        if ctx.Err() == context.DeadlineExceeded {
            fmt.Println("Request timed out")
        } else {
            fmt.Printf("Request error: %v\n", err)
        }
        return
    }
    
    fmt.Printf("Request completed: %s\n", resp.Status())
}

// Connection pool optimization
func optimizedClientConfiguration() *resty.Client {
    client := resty.New()
    
    // Connection pool settings
    client.SetTimeout(30 * time.Second)
    client.SetTransport(&http.Transport{
        MaxIdleConns:        100,               // Maximum idle connections
        MaxIdleConnsPerHost: 20,                // Maximum idle connections per host
        IdleConnTimeout:     90 * time.Second,  // Idle connection timeout
        TLSHandshakeTimeout: 10 * time.Second,  // TLS handshake timeout
        DisableCompression:  false,             // Enable compression
        ForceAttemptHTTP2:   true,             // Prefer HTTP/2
    })
    
    // Keep-alive settings
    client.SetHeader("Connection", "keep-alive")
    
    return client
}