X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/e805640e7904dc282f00be82a2edb53d496a87bb..HEAD:/services/keepproxy/keepproxy.go diff --git a/services/keepproxy/keepproxy.go b/services/keepproxy/keepproxy.go index 2090c50686..97a5ad6592 100644 --- a/services/keepproxy/keepproxy.go +++ b/services/keepproxy/keepproxy.go @@ -23,6 +23,7 @@ import ( "git.arvados.org/arvados.git/sdk/go/health" "git.arvados.org/arvados.git/sdk/go/httpserver" "git.arvados.org/arvados.git/sdk/go/keepclient" + "git.arvados.org/arvados.git/services/keepstore" "github.com/gorilla/mux" lru "github.com/hashicorp/golang-lru" "github.com/prometheus/client_golang/prometheus" @@ -175,13 +176,18 @@ func (h *proxyHandler) checkAuthorizationHeader(req *http.Request) (pass bool, t return true, tok, user } -// We need to make a private copy of the default http transport early -// in initialization, then make copies of our private copy later. It -// won't be safe to copy http.DefaultTransport itself later, because -// its private mutexes might have already been used. (Without this, -// the test suite sometimes panics "concurrent map writes" in -// net/http.(*Transport).removeIdleConnLocked().) -var defaultTransport = *(http.DefaultTransport.(*http.Transport)) +// We can't copy the default http transport because http.Transport has +// a mutex field, so we make our own using the values of the exported +// fields. +var defaultTransport = http.Transport{ + Proxy: http.DefaultTransport.(*http.Transport).Proxy, + DialContext: http.DefaultTransport.(*http.Transport).DialContext, + ForceAttemptHTTP2: http.DefaultTransport.(*http.Transport).ForceAttemptHTTP2, + MaxIdleConns: http.DefaultTransport.(*http.Transport).MaxIdleConns, + IdleConnTimeout: http.DefaultTransport.(*http.Transport).IdleConnTimeout, + TLSHandshakeTimeout: http.DefaultTransport.(*http.Transport).TLSHandshakeTimeout, + ExpectContinueTimeout: http.DefaultTransport.(*http.Transport).ExpectContinueTimeout, +} type proxyHandler struct { http.Handler @@ -195,14 +201,23 @@ type proxyHandler struct { func newHandler(ctx context.Context, kc *keepclient.KeepClient, timeout time.Duration, cluster *arvados.Cluster) (service.Handler, error) { rest := mux.NewRouter() - transport := defaultTransport - transport.DialContext = (&net.Dialer{ - Timeout: keepclient.DefaultConnectTimeout, - KeepAlive: keepclient.DefaultKeepAlive, - DualStack: true, - }).DialContext - transport.TLSClientConfig = arvadosclient.MakeTLSConfig(kc.Arvados.ApiInsecure) - transport.TLSHandshakeTimeout = keepclient.DefaultTLSHandshakeTimeout + // We can't copy the default http transport because + // http.Transport has a mutex field, so we copy the fields + // that we know have non-zero values in http.DefaultTransport. + transport := &http.Transport{ + Proxy: http.DefaultTransport.(*http.Transport).Proxy, + ForceAttemptHTTP2: http.DefaultTransport.(*http.Transport).ForceAttemptHTTP2, + MaxIdleConns: http.DefaultTransport.(*http.Transport).MaxIdleConns, + IdleConnTimeout: http.DefaultTransport.(*http.Transport).IdleConnTimeout, + ExpectContinueTimeout: http.DefaultTransport.(*http.Transport).ExpectContinueTimeout, + DialContext: (&net.Dialer{ + Timeout: keepclient.DefaultConnectTimeout, + KeepAlive: keepclient.DefaultKeepAlive, + DualStack: true, + }).DialContext, + TLSClientConfig: arvadosclient.MakeTLSConfig(kc.Arvados.ApiInsecure), + TLSHandshakeTimeout: keepclient.DefaultTLSHandshakeTimeout, + } cacheQ, err := lru.New2Q(500) if err != nil { @@ -213,7 +228,7 @@ func newHandler(ctx context.Context, kc *keepclient.KeepClient, timeout time.Dur Handler: rest, KeepClient: kc, timeout: timeout, - transport: &transport, + transport: transport, apiTokenCache: &apiTokenCache{ tokens: cacheQ, expireTime: 300, @@ -257,10 +272,9 @@ func (h *proxyHandler) checkLoop(resp http.ResponseWriter, req *http.Request) er } func setCORSHeaders(resp http.ResponseWriter) { - resp.Header().Set("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, OPTIONS") - resp.Header().Set("Access-Control-Allow-Origin", "*") - resp.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Length, Content-Type, X-Keep-Desired-Replicas") - resp.Header().Set("Access-Control-Max-Age", "86486400") + keepstore.SetCORSHeaders(resp) + acam := "Access-Control-Allow-Methods" + resp.Header().Set(acam, resp.Header().Get(acam)+", POST") } type invalidPathHandler struct{} @@ -290,7 +304,6 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) { var err error var status int var expectLength, responseLength int64 - var proxiedURI = "-" logger := ctxlog.FromContext(req.Context()) defer func() { @@ -298,7 +311,6 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) { "locator": locator, "expectLength": expectLength, "responseLength": responseLength, - "proxiedURI": proxiedURI, "err": err, }) if status != http.StatusOK { @@ -307,6 +319,7 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) { }() kc := h.makeKeepClient(req) + kc.DiskCacheSize = keepclient.DiskCacheDisabled var pass bool var tok string @@ -331,9 +344,9 @@ func (h *proxyHandler) Get(resp http.ResponseWriter, req *http.Request) { switch req.Method { case "HEAD": - expectLength, proxiedURI, err = kc.Ask(locator) + expectLength, _, err = kc.Ask(locator) case "GET": - reader, expectLength, proxiedURI, err = kc.Get(locator) + reader, expectLength, _, err = kc.Get(locator) if reader != nil { defer reader.Close() } @@ -406,9 +419,9 @@ func (h *proxyHandler) Put(resp http.ResponseWriter, req *http.Request) { locatorIn := mux.Vars(req)["locator"] // Check if the client specified storage classes - if req.Header.Get("X-Keep-Storage-Classes") != "" { + if req.Header.Get(keepclient.XKeepStorageClasses) != "" { var scl []string - for _, sc := range strings.Split(req.Header.Get("X-Keep-Storage-Classes"), ",") { + for _, sc := range strings.Split(req.Header.Get(keepclient.XKeepStorageClasses), ",") { scl = append(scl, strings.Trim(sc, " ")) } kc.SetStorageClasses(scl) @@ -566,7 +579,7 @@ func (h *proxyHandler) Index(resp http.ResponseWriter, req *http.Request) { } func (h *proxyHandler) makeKeepClient(req *http.Request) *keepclient.KeepClient { - kc := *h.KeepClient + kc := h.KeepClient.Clone() kc.RequestID = req.Header.Get("X-Request-Id") kc.HTTPClient = &proxyClient{ client: &http.Client{ @@ -575,5 +588,5 @@ func (h *proxyHandler) makeKeepClient(req *http.Request) *keepclient.KeepClient }, proto: req.Proto, } - return &kc + return kc }