import (
"bytes"
+ "context"
"crypto/tls"
"encoding/json"
"fmt"
"regexp"
"strings"
"time"
+
+ "git.curoverse.com/arvados.git/sdk/go/httpserver"
)
// A Client is an HTTP client with an API endpoint and a set of
KeepServiceURIs []string `json:",omitempty"`
dd *DiscoveryDocument
+
+ ctx context.Context
}
// The default http.Client used by a Client with Insecure==true and
}
}
-// Do adds authentication headers and then calls (*http.Client)Do().
+var reqIDGen = httpserver.IDGenerator{Prefix: "req-"}
+
+// Do adds Authorization and X-Request-Id headers and then calls
+// (*http.Client)Do().
func (c *Client) Do(req *http.Request) (*http.Response, error) {
if c.AuthToken != "" {
req.Header.Add("Authorization", "OAuth2 "+c.AuthToken)
}
+
+ reqid, ok := c.context().Value(contextKeyRequestID).(string)
+ if !ok {
+ reqid = reqIDGen.Next()
+ }
+ if req.Header.Get("X-Request-Id") == "" {
+ if req.Header == nil {
+ req.Header = http.Header{}
+ }
+ req.Header.Set("X-Request-Id", reqid)
+ }
return c.httpClient().Do(req)
}
return bytes.NewBufferString(v.Encode())
}
+type contextKey string
+
+var contextKeyRequestID contextKey = "X-Request-Id"
+
+func (c *Client) WithRequestID(reqid string) *Client {
+ cc := *c
+ cc.ctx = context.WithValue(cc.context(), contextKeyRequestID, reqid)
+ return &cc
+}
+
+func (c *Client) context() context.Context {
+ if c.ctx == nil {
+ return context.Background()
+ }
+ return c.ctx
+}
+
func (c *Client) httpClient() *http.Client {
switch {
case c.Client != nil:
gen := &IDGenerator{Prefix: "req-"}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.Header.Get("X-Request-Id") == "" {
+ if req.Header == nil {
+ req.Header = http.Header{}
+ }
req.Header.Set("X-Request-Id", gen.Next())
}
h.ServeHTTP(w, req)
}
applyContentDispositionHdr(w, r, basename, attachment)
- client := &arvados.Client{
+ client := (&arvados.Client{
APIHost: arv.ApiServer,
AuthToken: arv.ApiToken,
Insecure: arv.ApiInsecure,
- }
+ }).WithRequestID(r.Header.Get("X-Request-Id"))
fs, err := collection.FileSystem(client, kc)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- client := &arvados.Client{
+ client := (&arvados.Client{
APIHost: arv.ApiServer,
AuthToken: arv.ApiToken,
Insecure: arv.ApiInsecure,
- }
+ }).WithRequestID(r.Header.Get("X-Request-Id"))
fs := client.SiteFileSystem(kc)
f, err := fs.Open(r.URL.Path)
if os.IsNotExist(err) {
}
func (srv *server) Start() error {
- srv.Handler = &handler{Config: srv.Config}
+ srv.Handler = httpserver.AddRequestIDs(&handler{Config: srv.Config})
srv.Addr = srv.Config.Listen
return srv.Server.Start()
}