Awesome Go

fast-shot

CategoryNetworking
SubcategoryHTTP Clients
Stars126

Hit your API targets with rapid-fire precision using Go's fastest and simple HTTP Client

About fast-shot

Fast Shot is a robust, feature-rich, and highly configurable HTTP client for Go. Crafted with modern Go practices in mind, it offers a fluent, chainable API that allows for clean, idiomatic code.

Table of Contents

Why Fast Shot?

  • Fluent & Chainable API: Write expressive, readable, and flexible HTTP client code.
  • Ease of Use: Reduce boilerplate, making HTTP requests as straightforward as possible.
  • Rich Features: From headers to query parameters and JSON support, Fast Shot covers your needs.
  • Advanced Retry Mechanism: Built-in support for retries with various backoff strategies.

Features 🌟

  • Fluent and chainable API for clean, expressive code
  • Comprehensive HTTP method support (GET, POST, PUT, DELETE, etc.)
  • Flexible authentication options (Bearer Token, Basic Auth, Custom)
  • Easy manipulation of headers, cookies, and query parameters
  • Advanced retry mechanism with customizable backoff strategies
  • Pre-request and post-response hooks for observability and custom logic
  • Client-side load balancing for improved reliability
  • JSON request and response support
  • XML request and response support
  • Timeout and redirect control
  • Proxy support
  • Extensible and customizable for specific needs
  • Well-tested and production-ready

Installation 🔧

Fast Shot requires Go 1.27 or later. To install it, run:

go get github.com/opus-domini/fast-shot

Quick Start 🚀

Here's how you can make a simple POST using Fast Shot:

package main

import (
    "fmt"
    fastshot "github.com/opus-domini/fast-shot"
    "github.com/opus-domini/fast-shot/constant/mime"
)

func main() {
    client := fastshot.NewClient("https://api.example.com").
        Auth().BearerToken("your_token_here").
        Build()

    payload := map[string]any{
        "key1": "value1",
        "key2": "value2",
    }

    response, err := client.POST("/endpoint").
        Header().AddAccept(mime.JSON).
        Body().AsJSON(payload).
        Send()

    // Check for request send problems.
    if err != nil {
        panic(err) // (¬_¬")
    }

    // Check for (4xx || 5xx) errors response.
    if response.Status().IsError() {
        panic(response.Body().AsString()) // ¯\_(ツ)_/¯
    }

    // Decode straight into a typed value (Go 1.27 generic method).
    result, err := response.Body().AsJSON[map[string]any]()

    // Congrats! Do something awesome with the result (¬‿¬)
    fmt.Println(result)
}

Advanced Usage 🤖

Fluent API

Easily chain multiple settings in a single line:

client := fastshot.NewClient("https://api.example.com").
    Auth().BearerToken("your-bearer-token").
    Header().Add("My-Header", "My-Value").
    Config().SetTimeout(30 * time.Second).
    Build()

Advanced Retry Mechanism

Handle transient failures with customizable backoff strategies:

client.POST("/resource").
    Retry().SetExponentialBackoff(2 * time.Second, 5, 2.0).
    Send()

This new retry feature supports:

  • Constant backoff
  • Exponential backoff
  • Full jitter for both constant and exponential backoff
  • Custom retry conditions
  • Maximum delay setting

Request Hooks

Inject custom logic before sending requests and after receiving responses. Useful for logging, metrics, tracing, request signing, and audit logs:

client := fastshot.NewClient("https://api.example.com").
    Hook().OnBeforeRequest(func(req *http.Request) error {
        req.Header.Set("X-Request-ID", uuid.New().String()) // stdlib uuid, Go 1.27+
        return nil
    }).
    Hook().OnAfterResponse(func(req *http.Request, resp *http.Response) {
        log.Printf("%s %s → %d", req.Method, req.URL, resp.StatusCode)
    }).
    Build()

Hooks can also be set per-request:

client.GET("/resource").
    Hook().OnBeforeRequest(func(req *http.Request) error {
        // Only for this request
        return nil
    }).
    Send()

Key behaviors:

  • Client hooks run before request hooks (same ordering as headers and cookies)
  • Hooks run on every attempt, including retries
  • A before-request hook returning an error aborts the request
  • After-response hooks are observational and do not return errors

Generic Response Decoding (Go 1.27)

Skip the pre-allocated destination and decode straight into a typed value:

type User struct {
    Name string `json:"name"`
}

user, err := response.Body().AsJSON[User]()
// also available: response.Body().AsXML[User]()

Pluggable JSON Codec (encoding/json/v2)

Bodies are encoded/decoded with the standard encoding/json/v2 (Go 1.27+): strict, interoperable defaults — invalid UTF-8, duplicate object keys, and trailing data are rejected.

Need the lenient encoding/json (v1) semantics? Opt in:

client := fastshot.NewClient("https://api.example.com").
    Config().SetJSONCodec(fastshot.NewJSONv1Codec()).
    Build()

Bring your own codec by implementing fastshot.JSONCodec (Encode/Decode funcs).

Out-of-the-Box Support for Client Load Balancing

Effortlessly manage multiple endpoints:

client := fastshot.NewClientLoadBalancer([]string{
    "https://api1.example.com",
    "https://api2.example.com",
    "https://api3.example.com",
    }).
    Config().SetTimeout(time.Second * 10).
    Build()

This feature allows you to distribute network traffic across several servers, enhancing the performance and reliability of your applications.

Authentication

Fast Shot supports various types of authentication:

// Bearer Token
builder.Auth().BearerToken("your-bearer-token")

// Basic Authentication
builder.Auth().BasicAuth("username", "password")

// Custom Authentication
builder.Auth().Set("custom-authentication-header")

Custom Headers and Cookies

Add your own headers and cookies effortlessly:

// Add Custom Header
builder.Header().
    Add("header", "value")

// Add Multiple Custom Headers
builder.Header().
    AddAll(map[header.Type]string{
        "key1": "value1",
        "key2": "value2",
        "key3": "value3",
    })

// Add Custom Cookie
builder.Cookie().
    Add(&http.Cookie{Name: "session_id", Value: "id"})

Advanced Configurations

Control every aspect of the HTTP client:

// Set Timeout
builder.Config().
    SetTimeout(time.Second * 30)

// Set Follow Redirect
builder.Config().
    SetFollowRedirects(false)

// Set Custom Transport
builder.Config().
    SetCustomTransport(myCustomTransport)

// Set Proxy
builder.Config().
    SetProxy("http://my-proxy-server:port")

Response Handling

Extract information from the response with ease:

// Fluent response status check
response.Status()

// Easy response body access and conversion
response.Body()

// Get response headers to inspect
response.Header()

// Get response cookies for further processing 
response.Cookie()

// Get raw response if needed
response.Raw()

// and more...

Contributing 🤝

We welcome contributions to Fast Shot! Here's how you can contribute:

  1. Fork the repository
  2. Create a new branch for your feature or bug fix
  3. Write your code and tests
  4. Ensure all tests pass
  5. Submit a pull request

Please make sure to update tests as appropriate and adhere to the existing coding style.

For more detailed information, check out our CONTRIBUTING.md file.

Frequently Asked Questions

What is fast-shot?

fast-shot is a Networking library for the Go programming language. Hit your API targets with rapid-fire precision using Go's fastest and simple HTTP Client

How do I install fast-shot?

Install fast-shot with the Go module system using `go get opus-domini/fast-shot`. Check the repository for the current installation instructions.

What category does fast-shot belong to?

fast-shot is listed under Networking, specifically HTTP Clients.

← Back to HTTP Clients