httpclient

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2025 License: MIT Imports: 13 Imported by: 0

README

go-request-client

Go HTTP Request Client Library

A powerful and flexible HTTP client library for Go, inspired by Guzzle PHP. This library provides a simple interface for building HTTP requests, handling responses, and integrating with web services.

Features

  • Simple Interface: Easy-to-use API for building HTTP requests
  • Multiple Request Types: Support for GET, POST, PUT, DELETE, PATCH
  • JSON Support: Built-in JSON request/response handling
  • Form Data: Support for form-encoded data
  • Multipart Uploads: File upload support with multipart/form-data
  • Authentication: Basic authentication support
  • Query Parameters: Easy query string building
  • Headers Management: Flexible header configuration
  • Async Requests: Asynchronous request support with promises
  • Concurrent Requests: Send multiple requests concurrently
  • Middleware Support: Extensible middleware system
  • Timeout Control: Configurable request timeouts
  • Cookie Support: HTTP cookie handling
  • Response Handling: Convenient response methods

Installation

go get github.com/go-request-client

Quick Start

Basic Usage

package main

import (
    "fmt"
    "log"
    "time"
    
    "github.com/go-request-client"
)

func main() {
    // Create a new client
    client := httpclient.NewClient(
        httpclient.WithBaseURL("https://api.example.com"),
        httpclient.WithTimeout(10*time.Second),
    )

    // Send a GET request
    resp, err := client.Get("/users", &httpclient.RequestOptions{
        QueryParams: map[string]string{
            "page":  "1",
            "limit": "10",
        },
        Headers: map[string]string{
            "User-Agent": "MyApp/1.0",
        },
    })

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

    fmt.Printf("Status: %d\n", resp.GetStatusCode())
    fmt.Printf("Body: %s\n", resp.GetBody())
}

POST with JSON

// Create data to send
data := map[string]interface{}{
    "name":  "John Doe",
    "email": "john@example.com",
    "age":   30,
}

// Send POST request with JSON
resp, err := client.Post("/users", &httpclient.RequestOptions{
    JSON: data,
})

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

// Parse JSON response
var result map[string]interface{}
if err := resp.UnmarshalJSON(&result); err != nil {
    log.Fatal(err)
}

fmt.Printf("Created user with ID: %v\n", result["id"])

Form Data

resp, err := client.Post("/login", &httpclient.RequestOptions{
    FormData: map[string]string{
        "username": "john_doe",
        "password": "secret123",
    },
})

File Upload (Multipart)

// Create multipart data
multipartData := httpclient.NewMultipartData()
multipartData.AddField("description", "Profile picture")
multipartData.AddFileFromPath("file", "/path/to/image.jpg")

// Send multipart request
resp, err := client.Post("/upload", &httpclient.RequestOptions{
    Multipart: multipartData,
})

Authentication

// Create client with authentication
client := httpclient.NewClient(
    httpclient.WithBaseURL("https://api.example.com"),
    httpclient.WithAuth("username", "password"),
)

// Or set auth per request
resp, err := client.Get("/protected", &httpclient.RequestOptions{
    Auth: &httpclient.Auth{
        Username: "username",
        Password: "password",
    },
})

Async Requests

// Create async client
asyncClient := httpclient.NewAsyncClient(
    httpclient.WithBaseURL("https://api.example.com"),
)

// Send async request
promise := asyncClient.GetAsync("/users", nil)

// Do other work while request is processing
fmt.Println("Request sent, doing other work...")

// Wait for response
resp, err := promise.Wait()
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Async response: %s\n", resp.GetBody())

Using Promises

promise := asyncClient.GetAsync("/users", nil)

promise.Then(func(resp *httpclient.Response) (*httpclient.Response, error) {
    fmt.Printf("Request succeeded: %d\n", resp.GetStatusCode())
    return resp, nil
}).Catch(func(err error) error {
    fmt.Printf("Request failed: %v\n", err)
    return err
})

promise.Wait()

Concurrent Requests

requests := []httpclient.ConcurrentRequest{
    {Method: "GET", Path: "/users", Options: &httpclient.RequestOptions{}},
    {Method: "GET", Path: "/posts", Options: &httpclient.RequestOptions{}},
    {Method: "GET", Path: "/comments", Options: &httpclient.RequestOptions{}},
}

results := asyncClient.SendConcurrent(requests)

for i, result := range results {
    if result.Error != nil {
        fmt.Printf("Request %d failed: %v\n", i, result.Error)
    } else {
        fmt.Printf("Request %d succeeded: %d\n", i, result.Response.GetStatusCode())
    }
}

With Concurrency Limit

// Send requests with a limit of 5 concurrent requests
results := asyncClient.SendConcurrentWithLimit(requests, 5)

Client Configuration

Client Options

client := httpclient.NewClient(
    // Set base URL for all requests
    httpclient.WithBaseURL("https://api.example.com"),
    
    // Set default timeout
    httpclient.WithTimeout(30*time.Second),
    
    // Set default headers
    httpclient.WithHeaders(map[string]string{
        "User-Agent": "MyApp/1.0",
        "Accept":     "application/json",
    }),
    
    // Set default authentication
    httpclient.WithAuth("username", "password"),
)

Request Options

options := &httpclient.RequestOptions{
    // Query parameters
    QueryParams: map[string]string{
        "page":  "1",
        "limit": "10",
    },
    
    // Headers
    Headers: map[string]string{
        "Authorization": "Bearer token123",
    },
    
    // JSON data
    JSON: map[string]interface{}{
        "name": "John Doe",
    },
    
    // Form data
    FormData: map[string]string{
        "username": "john_doe",
    },
    
    // Custom body
    Body: strings.NewReader("custom body"),
    
    // Timeout for this request
    Timeout: 5 * time.Second,
    
    // Authentication for this request
    Auth: &httpclient.Auth{
        Username: "user",
        Password: "pass",
    },
    
    // Cookies
    Cookies: []*http.Cookie{
        {Name: "session", Value: "abc123"},
    },
    
    // Allow redirects
    AllowRedirects: true,
}

Response Handling

resp, err := client.Get("/users", nil)
if err != nil {
    log.Fatal(err)
}

// Get status code
status := resp.GetStatusCode()

// Get specific header
contentType := resp.GetHeader("Content-Type")

// Get response body as string
body := resp.GetBody()

// Get response body as bytes
bodyBytes := resp.GetBodyBytes()

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

Middleware

The library includes a middleware system for extending client behavior:

// Logging middleware
logger := &httpclient.SimpleLogger{}
loggingMiddleware := httpclient.LoggingMiddleware(logger)

// Retry middleware with exponential backoff
backoff := &httpclient.ExponentialBackoff{
    BaseDelay: 1 * time.Second,
    MaxDelay:  30 * time.Second,
}
retryMiddleware := httpclient.RetryMiddleware(3, backoff)

// Timeout middleware
timeoutMiddleware := httpclient.TimeoutMiddleware(5 * time.Second)

Error Handling

resp, err := client.Get("/users", nil)
if err != nil {
    // Handle network errors, timeouts, etc.
    log.Printf("Request failed: %v", err)
    return
}

// Check HTTP status code
if resp.GetStatusCode() >= 400 {
    log.Printf("HTTP error: %d - %s", resp.GetStatusCode(), resp.GetBody())
    return
}

Testing

Run the tests:

go test ./...

Examples

See the examples/ directory for comprehensive usage examples.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

The Go library maintains the same ease of use while leveraging Go's strengths in concurrency and performance.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AsyncClient

type AsyncClient struct {
	*Client
}

AsyncClient extends Client with async functionality

func NewAsyncClient

func NewAsyncClient(options ...ClientOption) *AsyncClient

NewAsyncClient creates a new async client

func (*AsyncClient) DeleteAsync

func (ac *AsyncClient) DeleteAsync(path string, options *RequestOptions) *Promise

DeleteAsync sends an asynchronous DELETE request

func (*AsyncClient) GetAsync

func (ac *AsyncClient) GetAsync(path string, options *RequestOptions) *Promise

GetAsync sends an asynchronous GET request

func (*AsyncClient) PatchAsync

func (ac *AsyncClient) PatchAsync(path string, options *RequestOptions) *Promise

PatchAsync sends an asynchronous PATCH request

func (*AsyncClient) PostAsync

func (ac *AsyncClient) PostAsync(path string, options *RequestOptions) *Promise

PostAsync sends an asynchronous POST request

func (*AsyncClient) PutAsync

func (ac *AsyncClient) PutAsync(path string, options *RequestOptions) *Promise

PutAsync sends an asynchronous PUT request

func (*AsyncClient) SendAsync

func (ac *AsyncClient) SendAsync(method, path string, options *RequestOptions) *Promise

SendAsync sends an asynchronous request

func (*AsyncClient) SendConcurrent

func (ac *AsyncClient) SendConcurrent(requests []ConcurrentRequest) []ConcurrentResponse

SendConcurrent sends multiple requests concurrently

func (*AsyncClient) SendConcurrentWithLimit

func (ac *AsyncClient) SendConcurrentWithLimit(requests []ConcurrentRequest, limit int) []ConcurrentResponse

SendConcurrentWithLimit sends multiple requests concurrently with a limit

type Auth

type Auth struct {
	Username string
	Password string
}

Auth represents authentication credentials

type BackoffStrategy

type BackoffStrategy interface {
	Delay(attempt int) time.Duration
}

BackoffStrategy interface for retry backoff

type Client

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

Client represents an HTTP client similar to Guzzle

func NewClient

func NewClient(options ...ClientOption) *Client

NewClient creates a new HTTP client

func (*Client) Delete

func (c *Client) Delete(path string, options *RequestOptions) (*Response, error)

Delete sends a DELETE request

func (*Client) Get

func (c *Client) Get(path string, options *RequestOptions) (*Response, error)

Get sends a GET request

func (*Client) Patch

func (c *Client) Patch(path string, options *RequestOptions) (*Response, error)

Patch sends a PATCH request

func (*Client) Post

func (c *Client) Post(path string, options *RequestOptions) (*Response, error)

Post sends a POST request

func (*Client) Put

func (c *Client) Put(path string, options *RequestOptions) (*Response, error)

Put sends a PUT request

func (*Client) Request

func (c *Client) Request(method, path string, options *RequestOptions) (*Response, error)

Request sends an HTTP request

type ClientOption

type ClientOption func(*Client)

ClientOption is a function that configures a client

func WithAuth

func WithAuth(username, password string) ClientOption

WithAuth sets authentication credentials

func WithBaseURL

func WithBaseURL(baseURL string) ClientOption

WithBaseURL sets the base URL for the client

func WithHeaders

func WithHeaders(headers map[string]string) ClientOption

WithHeaders sets default headers for all requests

func WithTimeout

func WithTimeout(timeout time.Duration) ClientOption

WithTimeout sets the timeout for requests

type ConcurrentRequest

type ConcurrentRequest struct {
	Method  string
	Path    string
	Options *RequestOptions
}

ConcurrentRequest represents a concurrent request

type ConcurrentResponse

type ConcurrentResponse struct {
	Index    int
	Response *Response
	Error    error
}

ConcurrentResponse represents a concurrent response

func WaitAll

func WaitAll(promises ...*Promise) []ConcurrentResponse

WaitAll waits for all promises to complete

type ExponentialBackoff

type ExponentialBackoff struct {
	BaseDelay time.Duration
	MaxDelay  time.Duration
}

ExponentialBackoff implements exponential backoff

func (*ExponentialBackoff) Delay

func (eb *ExponentialBackoff) Delay(attempt int) time.Duration

type Handler

type Handler func(*http.Request) (*Response, error)

Handler represents an HTTP handler

type HandlerStack

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

HandlerStack represents a stack of middleware handlers

func NewHandlerStack

func NewHandlerStack(handler Handler) *HandlerStack

NewHandlerStack creates a new handler stack

func (*HandlerStack) Next

func (hs *HandlerStack) Next(req *http.Request) (*Response, error)

Next executes the next middleware in the stack

func (*HandlerStack) Push

func (hs *HandlerStack) Push(middleware Middleware)

Push adds middleware to the stack

func (*HandlerStack) Reset

func (hs *HandlerStack) Reset()

Reset resets the stack position

type Logger

type Logger interface {
	Logf(format string, args ...interface{})
}

Logger interface for logging

type Middleware

type Middleware func(next Handler) Handler

Middleware represents a middleware function

func LoggingMiddleware

func LoggingMiddleware(logger Logger) Middleware

LoggingMiddleware logs request and response information

func RetryMiddleware

func RetryMiddleware(maxRetries int, backoff BackoffStrategy) Middleware

RetryMiddleware retries failed requests

func TimeoutMiddleware

func TimeoutMiddleware(timeout time.Duration) Middleware

TimeoutMiddleware adds timeout to requests

type MultipartData

type MultipartData struct {
	Fields map[string]string
	Files  map[string]*MultipartFile
}

MultipartData represents multipart form data

func NewMultipartData

func NewMultipartData() *MultipartData

NewMultipartData creates a new multipart data container

func (*MultipartData) AddField

func (md *MultipartData) AddField(name, value string)

AddField adds a form field

func (*MultipartData) AddFileFromBytes

func (md *MultipartData) AddFileFromBytes(fieldName, filename string, content []byte)

AddFileFromBytes adds a file from bytes

func (*MultipartData) AddFileFromPath

func (md *MultipartData) AddFileFromPath(fieldName, filePath string) error

AddFileFromPath adds a file from file path

func (*MultipartData) ToReader

func (md *MultipartData) ToReader() (io.Reader, string, error)

ToReader converts multipart data to a reader

type MultipartFile

type MultipartFile struct {
	Path     string
	Filename string
	Content  []byte
}

MultipartFile represents a file to be uploaded

type MultipartRequestOptions

type MultipartRequestOptions struct {
	*RequestOptions
	Multipart *MultipartData
}

MultipartRequestOptions extends RequestOptions with multipart support

func NewMultipartRequestOptions

func NewMultipartRequestOptions() *MultipartRequestOptions

NewMultipartRequestOptions creates new multipart request options

func (*MultipartRequestOptions) AddField

func (mro *MultipartRequestOptions) AddField(name, value string)

AddField adds a form field to multipart data

func (*MultipartRequestOptions) AddFile

func (mro *MultipartRequestOptions) AddFile(fieldName, filePath string) error

AddFile adds a file to multipart data

func (*MultipartRequestOptions) AddFileFromBytes

func (mro *MultipartRequestOptions) AddFileFromBytes(fieldName, filename string, content []byte)

AddFileFromBytes adds a file from bytes to multipart data

type Promise

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

Promise represents an asynchronous request result

func NewPromise

func NewPromise() *Promise

NewPromise creates a new promise

func (*Promise) Catch

func (p *Promise) Catch(fn func(error) error) *Promise

Catch executes a function when the promise is rejected

func (*Promise) Reject

func (p *Promise) Reject(err error)

Reject rejects the promise with an error

func (*Promise) Resolve

func (p *Promise) Resolve(response *Response)

Resolve resolves the promise with a response

func (*Promise) Then

func (p *Promise) Then(fn func(*Response) (*Response, error)) *Promise

Then executes a function when the promise is resolved

func (*Promise) Wait

func (p *Promise) Wait() (*Response, error)

Wait waits for the promise to be resolved or rejected

type RequestOptions

type RequestOptions struct {
	Headers        map[string]string
	QueryParams    map[string]string
	FormData       map[string]string
	JSON           interface{}
	Body           io.Reader
	Timeout        time.Duration
	Auth           *Auth
	Cookies        []*http.Cookie
	AllowRedirects bool
	Multipart      *MultipartData
}

RequestOptions represents options for HTTP requests

type Response

type Response struct {
	*http.Response
	Body []byte
}

Response represents an HTTP response

func (*Response) GetBody

func (r *Response) GetBody() string

GetBody returns the response body as string

func (*Response) GetBodyBytes

func (r *Response) GetBodyBytes() []byte

GetBodyBytes returns the response body as bytes

func (*Response) GetHeader

func (r *Response) GetHeader(name string) string

GetHeader returns a header value

func (*Response) GetStatusCode

func (r *Response) GetStatusCode() int

GetStatusCode returns the HTTP status code

func (*Response) UnmarshalJSON

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

UnmarshalJSON unmarshals the response body as JSON

type SimpleLogger

type SimpleLogger struct{}

SimpleLogger implements Logger interface

func (*SimpleLogger) Logf

func (sl *SimpleLogger) Logf(format string, args ...interface{})

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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