package main import ( "net/http" "time" ) // An HTTPGetter can GET over HTTP type HTTPGetter interface { Get(URL string) (*http.Response, error) } type simpleHTTPGetter struct{} // NewHTTPGetter returns the simplest object that can GET over HTTP func NewHTTPGetter() HTTPGetter { return &simpleHTTPGetter{} } func (g *simpleHTTPGetter) Get(URL string) (*http.Response, error) { return http.Get(URL) } type rateLimitedHTTPGetter struct { tokens chan bool window time.Duration } // NewRateLimitedGetter returns an HTTPGetter that is limited by a // maximal amount of request over a time window func NewRateLimitedGetter(maxRequest uint, window time.Duration) HTTPGetter { return &rateLimitedHTTPGetter{ tokens: make(chan bool, maxRequest), window: window, } } func (g *rateLimitedHTTPGetter) Get(URL string) (*http.Response, error) { g.tokens <- true defer func() { go func() { time.Sleep(g.window) <-g.tokens }() }() return http.Get(URL) }