METANOIA/metadata/client.go

67 lines
1.8 KiB
Go

package metadata
import (
"fmt"
"git.gammaspectra.live/S.O.N.G/METANOIA/utilities"
"net/http"
"runtime"
"time"
)
//DefaultUserAgent Follows most identification rules (Like for Musicbrainz, or Discogs)
var DefaultUserAgent = fmt.Sprintf("Mozilla/5.0 (compatible; METANOIA/%s; +https://git.gammaspectra.live/S.O.N.G/METANOIA) golang/%s (%s; %s; net/http; %s)", utilities.Version, runtime.Version(), runtime.GOOS, runtime.GOARCH, runtime.Compiler)
var defaultCacheStore CacheStore
type CachingClient struct {
context string
client *http.Client
throttler <-chan time.Time
}
type CacheStore interface {
Get(request *http.Request) (*http.Response, error)
Set(request *http.Request, response *http.Response) (*http.Response, error)
}
func SetCacheStore(store CacheStore) {
defaultCacheStore = store
}
func NewCachingClient(context string, rateLimit time.Duration) *CachingClient {
return &CachingClient{
context: context,
client: http.DefaultClient,
throttler: time.Tick(rateLimit),
}
}
func (c *CachingClient) Request(req *http.Request, lifetime time.Duration) (*http.Response, error) {
if req.Header == nil || req.UserAgent() == "" {
if req.Header == nil {
req.Header = make(http.Header)
}
req.Header.Set("User-Agent", DefaultUserAgent)
}
if defaultCacheStore != nil {
response, err := defaultCacheStore.Get(req)
if err == nil && response != nil {
timestamp, _ := time.ParseInLocation(time.UnixDate, response.Request.Header.Get("X-Fetched-At"), time.UTC)
if timestamp.Add(lifetime).After(time.Now()) {
return response, nil
}
}
}
<-c.throttler
response, err := c.client.Do(req)
if defaultCacheStore != nil && err == nil {
req.Header.Set("X-Fetched-At", time.Now().UTC().Format(time.UnixDate))
response, err = defaultCacheStore.Set(req, response)
}
return response, err
}