Skip to content

Commit

Permalink
Merge pull request #113 from infosiftr/User-Agent
Browse files Browse the repository at this point in the history
Add `User-Agent` to all our outgoing requests
  • Loading branch information
tianon authored Feb 3, 2025
2 parents 4e6eabf + 5adcfa5 commit bf729c6
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
7 changes: 7 additions & 0 deletions registry/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ func Client(host string, opts *ociclient.Options) (ociregistry.Interface, error)
clientOptions.Transport = http.DefaultTransport
}

// make sure we set User-Agent explicitly; this is first so that everything else has an explicit layer at the bottom setting User-Agent so we don't miss any requests
// IMPORTANT: this wrapper stays first! (https://github.com/cue-labs/oci/issues/37#issuecomment-2628321222)
clientOptions.Transport = &userAgentRoundTripper{
roundTripper: clientOptions.Transport,
userAgent: "https://github.com/docker-library/meta-scripts", // TODO allow this to be modified via environment variable
}

// if we have a rate limiter configured for this registry, shim it in
if limiter, ok := registryRateLimiters[host]; ok {
clientOptions.Transport = &rateLimitedRetryingRoundTripper{
Expand Down
31 changes: 31 additions & 0 deletions registry/user-agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package registry

// https://github.com/docker-library/meta-scripts/issues/111
// https://github.com/cue-labs/oci/issues/37

import (
"fmt"
"maps"
"net/http"
)

// an implementation of [net/http.RoundTripper] that transparently injects User-Agent (as a wrapper around another [net/http.RoundTripper])
type userAgentRoundTripper struct {
roundTripper http.RoundTripper
userAgent string
}

func (d *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
// if d is nil or if d.roundTripper is nil, we'll just let the runtime panic because those are both 100% coding errors in the consuming code

if d.userAgent == "" {
// arguably we could `panic` here too since this is *also* a coding error, but it'd be pretty reasonable to source this from an environment variable so `panic` is perhaps a bit user-hostile
return nil, fmt.Errorf("missing userAgent in userAgentRoundTripper! (request %s)", req.URL)
}

// https://github.com/cue-lang/cue/blob/0a43336cccf3b6fc632e976912d74fb2c9670557/internal/cueversion/transport.go#L27-L34
reqClone := *req
reqClone.Header = maps.Clone(reqClone.Header)
reqClone.Header.Set("User-Agent", d.userAgent)
return d.roundTripper.RoundTrip(&reqClone)
}

0 comments on commit bf729c6

Please sign in to comment.