Go net.Conn bandwidth limiter.
Only depends on the standard library.
go get github.com/linkdata/bwlimit
Ticker must be created with bwlimit.NewTicker(). The zero-value Ticker is not supported.
Limits are enforced in 100ms slices with fractional carry-over between slices, so very low limits are accurate over time but can still be bursty at slice boundaries.
After calling Limiter.Stop(), bandwidth metrics (Count and Rate) are no longer updated.
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"time"
"github.com/linkdata/bwlimit"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello world!"))
}))
defer srv.Close()
// limit reads to 100 bytes/sec, unlimited writes
lim := bwlimit.NewLimiter(100, 0)
defer lim.Stop()
// clone the default transport so this change is local to this client
tp := http.DefaultTransport.(*http.Transport).Clone()
tp.DialContext = lim.Wrap(nil).DialContext
client := &http.Client{Transport: tp}
// make a request and time it
now := time.Now()
resp, err := client.Get(srv.URL)
elapsed := time.Since(now)
if err == nil {
defer resp.Body.Close()
var body []byte
if body, err = io.ReadAll(resp.Body); err == nil {
fmt.Printf("%v %v %q\n", elapsed >= time.Second, lim.Reads.Count.Load() > 100, string(body))
}
}
}