An enhanced HTTP client for Go

Overview

Heimdall

Build Status

Description

Heimdall is an HTTP client that helps your application make a large number of requests, at scale. With Heimdall, you can:

  • Use a hystrix-like circuit breaker to control failing requests
  • Add synchronous in-memory retries to each request, with the option of setting your own retrier strategy
  • Create clients with different timeouts for every request

All HTTP methods are exposed as a fluent interface.

Installation

go get -u github.com/gojektech/heimdall/v6

Usage

Importing the package

This package can be used by adding the following import statement to your .go files.

import "github.com/gojektech/heimdall/v6/httpclient" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/gojektech/heimdall/httpclient" // with go modules disabled

Making a simple GET request

The below example will print the contents of the google home page:

// Create a new HTTP client with a default timeout
timeout := 1000 * time.Millisecond
client := httpclient.NewClient(httpclient.WithHTTPTimeout(timeout))

// Use the clients GET method to create and execute the request
res, err := client.Get("http://google.com", nil)
if err != nil{
	panic(err)
}

// Heimdall returns the standard *http.Response object
body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))

You can also use the *http.Request object with the http.Do interface :

timeout := 1000 * time.Millisecond
client := httpclient.NewClient(httpclient.WithHTTPTimeout(timeout))

// Create an http.Request instance
req, _ := http.NewRequest(http.MethodGet, "http://google.com", nil)
// Call the `Do` method, which has a similar interface to the `http.Do` method
res, err := client.Do(req)
if err != nil {
	panic(err)
}

body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))

Creating a hystrix-like circuit breaker

To import hystrix package of heimdall.

import "github.com/gojektech/heimdall/v6/hystrix" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/gojektech/heimdall/hystrix" // with go modules disabled

You can use the hystrix.NewClient function to create a client wrapped in a hystrix-like circuit breaker:

// Create a new hystrix-wrapped HTTP client with the command name, along with other required options
client := hystrix.NewClient(
	hystrix.WithHTTPTimeout(10 * time.Millisecond),
	hystrix.WithCommandName("google_get_request"),
	hystrix.WithHystrixTimeout(1000 * time.Millisecond),
	hystrix.WithMaxConcurrentRequests(30),
	hystrix.WithErrorPercentThreshold(20),
	hystrix.WithStatsDCollector("localhost:8125", "myapp.hystrix"),
)

// The rest is the same as the previous example

In the above example, there are two timeout values used: one for the hystrix configuration, and one for the HTTP client configuration. The former determines the time at which hystrix should register an error, while the latter determines when the client itself should return a timeout error. Unless you have any special requirements, both of these would have the same values.

You can choose to export hystrix metrics to a statsD collector with the hystrix.WithStatsDCollector(<statsd addr>, <metrics-prefix>) option when initializing the client as shown above.

Creating a hystrix-like circuit breaker with fallbacks

You can use the hystrix.NewClient function to create a client wrapped in a hystrix-like circuit breaker by passing in your own custom fallbacks:

The fallback function will trigger when your code returns an error, or whenever it is unable to complete based on a variety of health checks.

How your fallback function should look like you should pass in a function whose signature looks like following

func(err error) error {
    // your logic for handling the error/outage condition
    return err
}

Example

// Create a new fallback function
fallbackFn := func(err error) error {
    _, err := http.Post("post_to_channel_two")
    return err
}

timeout := 10 * time.Millisecond

// Create a new hystrix-wrapped HTTP client with the fallbackFunc as fall-back function
client := hystrix.NewClient(
	hystrix.WithHTTPTimeout(timeout),
	hystrix.WithCommandName("MyCommand"),
	hystrix.WithHystrixTimeout(1100 * time.Millisecond),
	hystrix.WithMaxConcurrentRequests(100),
	hystrix.WithErrorPercentThreshold(20),
	hystrix.WithSleepWindow(10),
	hystrix.WithRequestVolumeThreshold(10),
	hystrix.WithFallbackFunc(fallbackFn),
})

// The rest is the same as the previous example

In the above example, the fallbackFunc is a function which posts to channel two in case posting to channel one fails.

Creating an HTTP client with a retry mechanism

// First set a backoff mechanism. Constant backoff increases the backoff at a constant rate
backoffInterval := 2 * time.Millisecond
// Define a maximum jitter interval. It must be more than 1*time.Millisecond
maximumJitterInterval := 5 * time.Millisecond

backoff := heimdall.NewConstantBackoff(backoffInterval, maximumJitterInterval)

// Create a new retry mechanism with the backoff
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
	httpclient.WithHTTPTimeout(timeout),
	httpclient.WithRetrier(retrier),
	httpclient.WithRetryCount(4),
)

// The rest is the same as the first example

Or create client with exponential backoff

// First set a backoff mechanism. Exponential Backoff increases the backoff at a exponential rate

initalTimeout := 2*time.Millisecond            // Inital timeout
maxTimeout := 9*time.Millisecond               // Max time out
exponentFactor := 2                            // Multiplier
maximumJitterInterval := 2*time.Millisecond    // Max jitter interval. It must be more than 1*time.Millisecond

backoff := heimdall.NewExponentialBackoff(initalTimeout, maxTimeout, exponentFactor, maximumJitterInterval)

// Create a new retry mechanism with the backoff
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
	httpclient.WithHTTPTimeout(timeout),
	httpclient.WithRetrier(retrier),
	httpclient.WithRetryCount(4),
)

// The rest is the same as the first example

This will create an HTTP client which will retry every 500 milliseconds incase the request fails. The library also comes with an Exponential Backoff

Custom retry mechanisms

Heimdall supports custom retry strategies. To do this, you will have to implement the Backoff interface:

type Backoff interface {
	Next(retry int) time.Duration
}

Let's see an example of creating a client with a linearly increasing backoff time:

First, create the backoff mechanism:

type linearBackoff struct {
	backoffInterval int
}

func (lb *linearBackoff) Next(retry int) time.Duration{
	if retry <= 0 {
		return 0 * time.Millisecond
	}
	return time.Duration(retry * lb.backoffInterval) * time.Millisecond
}

This will create a backoff mechanism, where the retry time will increase linearly for each retry attempt. We can use this to create the client, just like the last example:

backoff := &linearBackoff{100}
retrier := heimdall.NewRetrier(backoff)

timeout := 1000 * time.Millisecond
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client := httpclient.NewClient(
	httpclient.WithHTTPTimeout(timeout),
	httpclient.WithRetrier(retrier),
	httpclient.WithRetryCount(4),
)

// The rest is the same as the first example

Heimdall also allows you to simply pass a function that returns the retry timeout. This can be used to create the client, like:

linearRetrier := NewRetrierFunc(func(retry int) time.Duration {
	if retry <= 0 {
		return 0 * time.Millisecond
	}
	return time.Duration(retry) * time.Millisecond
})

timeout := 1000 * time.Millisecond
client := httpclient.NewClient(
	httpclient.WithHTTPTimeout(timeout),
	httpclient.WithRetrier(linearRetrier),
	httpclient.WithRetryCount(4),
)

Custom HTTP clients

Heimdall supports custom HTTP clients. This is useful if you are using a client imported from another library and/or wish to implement custom logging, cookies, headers etc for each request that you make with your client.

Under the hood, the httpClient struct now accepts Doer, which is the standard interface implemented by HTTP clients (including the standard library's net/*http.Client)

Let's say we wish to add authorization headers to all our requests.

We can define our client myHTTPClient

type myHTTPClient struct {
	client http.Client
}

func (c *myHTTPClient) Do(request *http.Request) (*http.Response, error) {
	request.SetBasicAuth("username", "passwd")
	return c.client.Do(request)
}

And set this with httpclient.NewClient(httpclient.WithHTTPClient(&myHTTPClient{client: http.DefaultClient}))

Now, each sent request will have the Authorization header to use HTTP basic authentication with the provided username and password.

This can be done for the hystrix client as well

client := httpclient.NewClient(
	httpclient.WithHTTPClient(&myHTTPClient{
		client: http.Client{Timeout: 25 * time.Millisecond},
	}),
)

// The rest is the same as the first example

Plugins

To add a plugin to an existing client, use the AddPlugin method of the client.

An example, with the request logger plugin:

// import "github.com/gojektech/heimdall/v6/plugins"

client := heimdall.NewHTTPClient(timeout)
requestLogger := plugins.NewRequestLogger(nil, nil)
client.AddPlugin(requestLogger)
// use the client as before

req, _ := http.NewRequest(http.MethodGet, "http://google.com", nil)
res, err := client.Do(req)
if err != nil {
	panic(err)
}
// This will log:
//23/Jun/2018 12:48:04 GET http://google.com 200 [412ms]
// to STDOUT

A plugin is an interface whose methods get called during key events in a requests lifecycle:

  • OnRequestStart is called just before the request is made
  • OnRequestEnd is called once the request has successfully executed
  • OnError is called is the request failed

Each method is called with the request object as an argument, with OnRequestEnd, and OnError additionally being called with the response and error instances respectively. For a simple example on how to write plugins, look at the request logger plugin.

Documentation

Further documentation can be found on pkg.go.dev

FAQ

Can I replace the standard Go HTTP client with Heimdall?

Yes, you can. Heimdall implements the standard HTTP Do method, along with useful wrapper methods that provide all the functionality that a regular Go HTTP client provides.


When should I use Heimdall?

If you are making a large number of HTTP requests, or if you make requests among multiple distributed nodes, and wish to make your systems more fault tolerant, then Heimdall was made for you.

Heimdall makes use of multiple mechanisms to make HTTP requests more fault tolerant:

  1. Retries - If a request fails, Heimdall retries behind the scenes, and returns the result if one of the retries are successful.
  2. Circuit breaking - If Heimdall detects that too many of your requests are failing, or that the number of requests sent are above a configured threshold, then it "opens the circuit" for a short period of time, which prevents any more requests from being made. This gives your downstream systems time to recover.

So does this mean that I shouldn't use Heimdall for small scale applications?

Although Heimdall was made keeping large scale systems in mind, it's interface is simple enough to be used for any type of systems. In fact, we use it for our pet projects as well. Even if you don't require retries or circuit breaking features, the simpler HTTP client provides sensible defaults with a simpler interface, and can be upgraded easily should the need arise.


Can I contribute to make Heimdall better?

Please do! We are looking for any kind of contribution to improve Heimdalls core funtionality and documentation. When in doubt, make a PR!

License

Copyright 2018-2020, GO-JEK Tech (http://gojek.tech)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Issues
  • Implement Functional Options

    Implement Functional Options

    Hello,

    As proposed in here #31, the following implements functional options into the library. This is a breaking change and should probably increase the major version. A few things to consider:

    New package names

    Why?

    I started to have name conflicts with the options that were common to both clients since both of them are in the root folder of the project. Here is an example of the issue:

    
    httpClient := heimdall.NewHTTPClient(
    	heimdall.WithHTTPTimeout(10), 
    	heimdall.WithRetryCount(4),
    )
    
    hystrixClient := heimdall.NewHystrixHTTPClient(
    	heimdall.WithHTTPTimeout(10), // This name cannot be the same
    	heimdall.WithRetryCount(4),// This name cannot be the same
    	heimdall.WithHystrixTimeout(1100),
    )
    
    

    For this reason, I thought it would be more elegant to have the client implementations in their own package. I called them httpclient (to avoid conflict with the http package) and hystrix

    Now the usage looks like:

    	httpClient := httpclient.NewClient(
    		httpclient.WithHTTPTimeout(timeout),
    		httpclient.WithRetryCount(2),
    	)
    
    	hystrixClient := hystrix.NewClient(
    		hystrix.WithHTTPTimeout(timeout),
    		hystrix.WithCommandName("MyCommand"),
    		hystrix.WithHystrixTimeout(1100),
    		hystrix.WithMaxConcurrentRequests(100),
    		hystrix.WithErrorPercentThreshold(25),
    		hystrix.WithSleepWindow(10),
    		hystrix.WithRequestVolumeThreshold(10),
    	)
    

    Returning concrete types

    Now I started to return concrete types on the constructors of the clients and to make sure the compiler can identify if we are implementing the interface I added this line.

    var _ heimdall.Client = (*Client)(nil)
    

    If you don't like the packaging strategy please let me know and we can try to find a solution.

    Thanks!

    opened by italolelis 9
  • Improve Do methods

    Improve Do methods

    [This PR is more a proposal than anything else]

    Hi!

    This PR aims at simplifying the Do methods for both httpClient and hystrixHTTPClient. It also introduce multi-errors for the hystrixHTTPClient.

    The reasons why this PR is a proposal more than anything are:

    • it changes the way errors are returned by the the hystrixHTTPClient,
    • it may slightly break retro-compatibility in case the client would want to use a non-nil response together with a non-nil error. As explained in detail here this might be the case in Go 1.

    Let me know what you think 😉

    opened by vthiery 6
  • Add jitter for constant backoff

    Add jitter for constant backoff

    As you're answering questions, I've created this small PR for the jitter requirement.

    Currently, it's adding a random time (<= MAX) to the given backoff time. We can discuss if you want a different way for this.

    opened by pravj 6
  • while creating new client use time.Duration

    while creating new client use time.Duration

    func NewHTTPClient(timeoutInMilliseconds int) Client in http_client accepts int but could be time.Duration, so its flexible

    it could be a heimdall.Config{...} so we could add more later.

    help wanted good first issue 
    opened by devdinu 6
  • Allow creating retrier with a function

    Allow creating retrier with a function

    This PR allows you to create a Retrier without creating a struct to satisfy the interface, just a function. Similar to http.Handler and http.HandlerFunc

    Example:

    linearRetrier := NewRetrierFunc(func(retry int) time.Duration {
    	if retry <= 0 {
    		return 0 * time.Millisecond
    	}
    	return time.Duration(retry) * time.Millisecond
    })
    client := heimdall.NewHTTPClient(timeout)
    client.SetRetrier(retrier)
    
    opened by medakk 5
  • allow custom http client

    allow custom http client

    this pr is an attempt at allowing custom http clients (#20)

    We can set a custom http client now using SetCustomHTTPClient

    	client.SetCustomHTTPClient(&myHTTPClient{
    		client: http.Client{Timeout: 25 * time.Millisecond}})
    

    The custom client needs to implement the Doer interface which is also implemented by the http.Client in stdlib.

    opened by darshanime 5
  • Incorrect formula for exponential backoff

    Incorrect formula for exponential backoff

    Need to change the first plus sign here to a multiplication:

    https://github.com/gojek/heimdall/blob/16e67fd885aa9cb5b9d2257936e8e8c301eba52a/backoff.go#L63

    Exponential backoff with exponent factor 2 should be initialBackoff * 2^n.

    opened by btamadio 4
  • fix issue #79: add /v6 module import suffix

    fix issue #79: add /v6 module import suffix

    @sohamkamani I've added /v6 import suffix to resolve issue #79 introduced with v5.1.0 release with https://github.com/gojek/heimdall/pull/40.

    According to https://github.com/golang/go/wiki/Modules#why-must-major-version-numbers-appear-in-import-paths the major version must present in import paths.

    If you wish, I could do it in v5 module, to fix the buggy v5.1.0 version, but it's strongly recommended to increase major version after adopting go modules: https://github.com/golang/go/wiki/Modules#incrementing-the-major-version-when-first-adopting-modules-with-v2-packages, so I've made it v6.

    And please have a look at https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher In short, there could be some problems with godep users with major go.mod in master. So we could introduce better compatibility with v6 subdirectory for non-gomod users. But if you dropped Gopkg.toml support, maybe it's unnecessary.

    Let's discuss an fix it ASAP to have better go.mod support 🙇

    opened by mwf 4
  • Cannot import v5.1.0 due to

    Cannot import v5.1.0 due to "non optimal" go.mod

    I am using go1.14. I tried to import v5.1.0 with this command:

    go get -u github.com/gojek/[email protected]
    

    and it gave me this error:

    go get github.com/gojek/[email protected]: github.com/gojek/[email protected]: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v5
    

    As stated in go mod wiki page, any package with major version larger than v0 and v1 must include its major version in the module name.

    So the statement here module github.com/gojektech/heimdall should be appended with /v5 so that it would become module github.com/gojektech/heimdall/v5.

    I don't know whether this change would broke backward compatibility for imports. Example: will import "github.com/gojektech/heimdall/httpclient" be changed to import "github.com/gojektech/heimdall/v5/httpclient" and all will be ok?

    If all is OK I can make a PR to this.

    opened by gunturaf 4
  • heimdall response returns 200 status but return data in stream format

    heimdall response returns 200 status but return data in stream format

    Current Working Code which having Raw http and heimdallHttpClient (internal Api) the below gist code having both success case and error case

    https://gist.github.com/MuthukumarHelios/79ef131001a9f8fb5b2b4232c63c6b50

    opened by MuthukumarHelios 4
  • when a POST operation returns >= 500 the retry fails

    when a POST operation returns >= 500 the retry fails

    apparently it's because the request body is already read and not restored before retrying

    here's a possible solution https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361

    and it's likely happening here:

    https://github.com/gojektech/heimdall/blob/master/hystrix/hystrix_client.go#L152

    opened by dcu 4
  • fix bug & some optimize

    fix bug & some optimize

    1. add unit tests TestHTTPClientGetRetriesOnTimeout
    2. fix issue #89/#94: retrier called even with 0 retry count and time sleep will be called even when the retries are exhausted
    3. Cancel the retry sleep if the request context is canceled or the deadline exceeded

    some proposal:

    1. an interface or option through which we can customize the retry policy (check error check resp.StatusCode)
    2. some times, we need to know the number of retries and responses when the retrier called. Is any idea about this? I implemented a version using the existing method, but it was not very good get the retry times
    type Plugin interface {
    	OnRequestStart(*http.Request)
    	OnRequestEnd(*http.Request, *http.Response)
    	// the response struct contains the request. add a attempt num when the err handler?
    	OnError(*http.Response, error, int)   
    }
    
    opened by Panlq 0
  • feat: Support for fallbacks with context

    feat: Support for fallbacks with context

    Hi Gojek Team!

    The fallback function provided by heimdall's Hystrix Client doesn't support context.Context.

    While going through afex/hystrix-go, I found that it does support a fallback function with context:

    type fallbackFuncC func(context.Context, error) error
    

    Link: https://github.com/afex/hystrix-go/blob/master/hystrix/hystrix.go#L13 This can be used alongwith DoC() instead of Do()

    func DoC(ctx context.Context, name string, run runFuncC, fallback fallbackFuncC) error {
    

    Link: https://github.com/afex/hystrix-go/blob/master/hystrix/hystrix.go#L217

    This is however a breaking change. Let me know if there's other way.

    Thanks!

    opened by psrajat 0
  • hystrix POST with retry returns

    hystrix POST with retry returns "http: ContentLength=... with Body length 0"

    It looks like the retries with POST used in a hystrix client run into some error related to the request being already used. Error returned from http call is "{"status":"Post "http://localhost:8080/sampleLookup": http: ContentLength=14 with Body length 0"}", which seems incorrect - we shouldn't run into an issue of request being reused several times.

    Did anyone encounter this?

    Thanks!

    Source code following, curl command under the code.

    package main
    
    import (
    	"bytes"
    	"encoding/json"
    	"io/ioutil"
    	"log"
    	"net/http"
    	"time"
    
    	hystrix "github.com/gojek/heimdall/v7/hystrix"
    )
    
    type SampleRequest struct {
    	String string `json:"string"`
    }
    
    type SampleResponse struct {
    	Status string `json:"status"`
    }
    
    func initialEndpoint(w http.ResponseWriter, r *http.Request) {
    	var sampleRequest SampleRequest
    
    	// hystrix client
    	client := hystrix.NewClient(
    		hystrix.WithHystrixTimeout(1000*time.Millisecond),
    		hystrix.WithRetryCount(3),
    	)
    
    	// request buffer
    	var buf bytes.Buffer
    	_ = json.NewEncoder(&buf).Encode(sampleRequest)
    
    	// send request
    	headers := http.Header{}
    	headers.Set("Content-Type", "application/json")
    	res, err := client.Post("http://localhost:8080/sampleLookup", &buf, headers)
    
    	// interpret response
    	if err != nil {
    		sampleResponse := SampleResponse{
    			Status: err.Error(),
    		}
    		json.NewEncoder(w).Encode(sampleResponse)
    		return
    	}
    	body, _ := ioutil.ReadAll(res.Body)
    	json.NewEncoder(w).Encode(body)
    	res.Body.Close()
    }
    
    // just wait for 3 sec
    func sampleLookup(w http.ResponseWriter, r *http.Request) {
    	time.Sleep(3 * time.Second)
    	json.NewEncoder(w).Encode(SampleResponse{
    		Status: "ok",
    	})
    }
    
    // start server with 2 endpoints
    func main() {
    	http.HandleFunc("/initialEndpoint", initialEndpoint)
    	http.HandleFunc("/sampleLookup", sampleLookup)
    	log.Fatal(http.ListenAndServe(":8080", nil))
    }
    
    

    Curl command:

    curl --location --request GET 'http://localhost:8080/initialEndpoint' \
    --header 'Content-Type: text/plain' \
    --data-raw '{
        "String": "some value"
    }'
    
    opened by sebastian-popa 0
  • The target all includes setup to install golint, goveralls before executing build and coverage

    The target all includes setup to install golint, goveralls before executing build and coverage

    Expected: The command make executes successfully.

    Actual: The command make fails with /bin/sh: 1: goveralls: not found

    make-doesnt-download-goveralls

    Potential reason: The Makefile has the .PHONY target: all that may execute the targets: build, test, coverage. However, the command make fails as the prerequisites are not downloaded before executing the targets.

    What changes were made in the PR:

    1. Removed unnecessary strings attached with the .PHONY target.
    2. Added the target setup in the all target so that golint and goveralls are installed before executing the build and coverage targets.
    opened by Biswajee 0
  • One extra sleep at the end of the retry loop in client.Do func

    One extra sleep at the end of the retry loop in client.Do func

    I am using exponential backoff with a retry count of n. I see that after n retries, the sleep before continue https://github.com/gojek/heimdall/blob/master/httpclient/client.go#L159 blocks one last time before coming out of the loop.

    Is this expected?

    opened by sayan-mitra 0
Releases(v7.0.0)
Owner
Gojek
SuperApp from Southeast Asia
Gojek
An enhanced HTTP client for Go

Heimdall Description Installation Usage Making a simple GET request Creating a hystrix-like circuit breaker Creating a hystrix-like circuit breaker wi

Gojek 2.3k Jun 30, 2022
Http client call for golang http api calls

httpclient-call-go This library is used to make http calls to different API services Install Package go get

pzenteno 14 Mar 8, 2022
fhttp is a fork of net/http that provides an array of features pertaining to the fingerprint of the golang http client.

fhttp The f stands for flex. fhttp is a fork of net/http that provides an array of features pertaining to the fingerprint of the golang http client. T

Flexagon 61 Jun 10, 2022
Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http

fasthttp Fast HTTP implementation for Go. Currently fasthttp is successfully used by VertaMedia in a production serving up to 200K rps from more than

Aliaksandr Valialkin 17.9k Jun 26, 2022
Speak HTTP like a local. (the simple, intuitive HTTP console, golang version)

http-gonsole This is the Go port of the http-console. Speak HTTP like a local Talking to an HTTP server with curl can be fun, but most of the time it'

mattn 65 Jul 14, 2021
NATS HTTP Round Tripper - This is a Golang http.RoundTripper that uses NATS as a transport.

This is a Golang http.RoundTripper that uses NATS as a transport. Included is a http.RoundTripper for clients, a server that uses normal HTTP Handlers and any existing http handler mux and a Caddy Server transport.

R.I.Pienaar 75 Jun 14, 2022
Simple HTTP package that wraps net/http

Simple HTTP package that wraps net/http

Kris 0 Jan 17, 2022
Http-conection - A simple example of how to establish a HTTP connection using Golang

A simple example of how to establish a HTTP connection using Golang

Jonathan Gonzaga 0 Feb 1, 2022
Full-featured, plugin-driven, extensible HTTP client toolkit for Go

gentleman Full-featured, plugin-driven, middleware-oriented toolkit to easily create rich, versatile and composable HTTP clients in Go. gentleman embr

Tom 957 Jun 22, 2022
Enriches the standard go http client with retry functionality.

httpRetry Enriches the standard go http client with retry functionality using a wrapper around the Roundtripper interface. The advantage of this libra

Alexander Gehres 20 May 10, 2022
http client for golang

Request HTTP client for golang, Inspired by Javascript-axios Python-request. If you have experience about axios or requests, you will love it. No 3rd

Monaco.HappyHacking 206 Jun 24, 2022
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Go Resty 6.3k Jun 26, 2022
A nicer interface for golang stdlib HTTP client

rq A nicer interface for golang stdlib HTTP client Documents rq: here client: here jar: here Why? Because golang HTTP client is a pain in the a... Fea

Ddo 40 Jan 23, 2022
A Go HTTP client library for creating and sending API requests

Sling Sling is a Go HTTP client library for creating and sending API requests. Slings store HTTP Request properties to simplify sending requests and d

Dalton Hubble 1.5k Jun 29, 2022
a Go HTTP client with timeouts

go-httpclient requires Go 1.1+ as of v0.4.0 the API has been completely re-written for Go 1.1 (for a Go 1.0.x compatible release see 1adef50) Provides

Matt Reiferson 290 Sep 7, 2021
GoRequest -- Simplified HTTP client ( inspired by nodejs SuperAgent )

GoRequest GoRequest -- Simplified HTTP client ( inspired by famous SuperAgent lib in Node.js ) "Shooting Requests like a Machine Gun" - Gopher Sending

Theeraphol Wattanavekin 3.2k Jun 28, 2022
gout to become the Swiss Army Knife of the http client @^^@---> gout 是http client领域的瑞士军刀,小巧,强大,犀利。具体用法可看文档,如使用迷惑或者API用得不爽都可提issues

gout gout 是go写的http 客户端,为提高工作效率而开发 构架 feature 支持设置 GET/PUT/DELETE/PATH/HEAD/OPTIONS 支持设置请求 http header(可传 struct,map,array,slice 等类型) 支持设置 URL query(可

guonaihong 1k Jun 24, 2022
Retry, Race, All, Some, etc strategies for http.Client calls

reqstrategy Package reqstrategy provides functions for coordinating http.Client calls. It wraps typical call strategies like making simultaneous reque

Sergiy Yavorsky 11 Apr 30, 2021
Go Supertest is minimalize HTTP Client Testing only for Gin Framework

Go Supertest is minimalize HTTP Client Testing only for Gin Framework, inspired by Supertest package library HTTP Client Testing for Express.js Framework.

Restu Wahyu Saputra 6 May 22, 2022