X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/49bf45439d31edbaad88a12c5958c03720824ec9..a5cf4e0ea356a7ee06f67fe159484fe20cd8a184:/services/keep-web/handler.go diff --git a/services/keep-web/handler.go b/services/keep-web/handler.go index 02e7cb1858..863b91a7e1 100644 --- a/services/keep-web/handler.go +++ b/services/keep-web/handler.go @@ -25,12 +25,13 @@ import ( "git.curoverse.com/arvados.git/sdk/go/health" "git.curoverse.com/arvados.git/sdk/go/httpserver" "git.curoverse.com/arvados.git/sdk/go/keepclient" - log "github.com/Sirupsen/logrus" + log "github.com/sirupsen/logrus" "golang.org/x/net/webdav" ) type handler struct { Config *Config + MetricsAPI http.Handler clientPool *arvadosclient.ClientPool setupOnce sync.Once healthHandler http.Handler @@ -80,7 +81,7 @@ func (h *handler) setup() { keepclient.RefreshServiceDiscoveryOnSIGHUP() h.healthHandler = &health.Handler{ - Token: h.Config.ManagementToken, + Token: h.Config.cluster.ManagementToken, Prefix: "/_health/", } @@ -90,14 +91,7 @@ func (h *handler) setup() { } func (h *handler) serveStatus(w http.ResponseWriter, r *http.Request) { - status := struct { - cacheStats - Version string - }{ - cacheStats: h.Config.Cache.Stats(), - Version: version, - } - json.NewEncoder(w).Encode(status) + json.NewEncoder(w).Encode(struct{ Version string }{version}) } // updateOnSuccess wraps httpserver.ResponseWriter. If the handler @@ -141,23 +135,34 @@ func (uos *updateOnSuccess) WriteHeader(code int) { } var ( + corsAllowHeadersHeader = strings.Join([]string{ + "Authorization", "Content-Type", "Range", + // WebDAV request headers: + "Depth", "Destination", "If", "Lock-Token", "Overwrite", "Timeout", + }, ", ") writeMethod = map[string]bool{ - "COPY": true, - "DELETE": true, - "MKCOL": true, - "MOVE": true, - "PUT": true, - "RMCOL": true, + "COPY": true, + "DELETE": true, + "LOCK": true, + "MKCOL": true, + "MOVE": true, + "PROPPATCH": true, + "PUT": true, + "RMCOL": true, + "UNLOCK": true, } webdavMethod = map[string]bool{ - "COPY": true, - "DELETE": true, - "MKCOL": true, - "MOVE": true, - "OPTIONS": true, - "PROPFIND": true, - "PUT": true, - "RMCOL": true, + "COPY": true, + "DELETE": true, + "LOCK": true, + "MKCOL": true, + "MOVE": true, + "OPTIONS": true, + "PROPFIND": true, + "PROPPATCH": true, + "PUT": true, + "RMCOL": true, + "UNLOCK": true, } browserMethod = map[string]bool{ "GET": true, @@ -183,6 +188,9 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { if xff := r.Header.Get("X-Forwarded-For"); xff != "" { remoteAddr = xff + "," + remoteAddr } + if xfp := r.Header.Get("X-Forwarded-Proto"); xfp != "" && xfp != "http" { + r.URL.Scheme = xfp + } w := httpserver.WrapResponseWriter(wOrig) defer func() { @@ -209,8 +217,8 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { statusCode = http.StatusMethodNotAllowed return } - w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, Range") - w.Header().Set("Access-Control-Allow-Methods", "COPY, DELETE, GET, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PUT, RMCOL") + w.Header().Set("Access-Control-Allow-Headers", corsAllowHeadersHeader) + w.Header().Set("Access-Control-Allow-Methods", "COPY, DELETE, GET, LOCK, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, RMCOL, UNLOCK") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Max-Age", "86400") statusCode = http.StatusOK @@ -241,9 +249,9 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { var pathToken bool var attachment bool var useSiteFS bool - credentialsOK := h.Config.TrustAllContent + credentialsOK := h.Config.cluster.Collections.TrustAllContent - if r.Host != "" && r.Host == h.Config.AttachmentOnlyHost { + if r.Host != "" && r.Host == h.Config.cluster.Services.WebDAVDownload.ExternalURL.Host { credentialsOK = true attachment = true } else if r.FormValue("disposition") == "attachment" { @@ -256,6 +264,9 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { } else if r.URL.Path == "/status.json" { h.serveStatus(w, r) return + } else if strings.HasPrefix(r.URL.Path, "/metrics") { + h.MetricsAPI.ServeHTTP(w, r) + return } else if siteFSDir[pathParts[0]] { useSiteFS = true } else if len(pathParts) >= 1 && strings.HasPrefix(pathParts[0], "c=") { @@ -272,8 +283,11 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { } else { // /collections/ID/PATH... collectionID = parseCollectionIDFromURL(pathParts[1]) - tokens = h.Config.AnonymousTokens stripParts = 2 + // This path is only meant to work for public + // data. Tokens provided with the request are + // ignored. + credentialsOK = false } } @@ -287,6 +301,10 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { forceReload = true } + if credentialsOK { + reqTokens = auth.CredentialsFromRequest(r).Tokens + } + formToken := r.FormValue("api_token") if formToken != "" && r.Header.Get("Origin") != "" && attachment && r.URL.Query().Get("api_token") == "" { // The client provided an explicit token in the POST @@ -302,7 +320,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { // // * The token isn't embedded in the URL, so we don't // need to worry about bookmarks and copy/paste. - tokens = append(tokens, formToken) + reqTokens = append(reqTokens, formToken) } else if formToken != "" && browserMethod[r.Method] { // The client provided an explicit token in the query // string, or a form in POST body. We must put the @@ -313,6 +331,11 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { return } + if useSiteFS { + h.serveSiteFS(w, r, reqTokens, credentialsOK, attachment) + return + } + targetPath := pathParts[stripParts:] if tokens == nil && len(targetPath) > 0 && strings.HasPrefix(targetPath[0], "t=") { // http://ID.example/t=TOKEN/PATH... @@ -328,15 +351,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { } if tokens == nil { - if credentialsOK { - reqTokens = auth.NewCredentialsFromHTTPRequest(r).Tokens - } - tokens = append(reqTokens, h.Config.AnonymousTokens...) - } - - if useSiteFS { - h.serveSiteFS(w, r, tokens, credentialsOK, attachment) - return + tokens = append(reqTokens, h.Config.cluster.Users.AnonymousUserToken) } if len(targetPath) > 0 && targetPath[0] == "_" { @@ -616,9 +631,9 @@ the entire directory tree with wget, try:

@@ -770,6 +785,7 @@ func (h *handler) seeOtherWithCookie(w http.ResponseWriter, r *http.Request, loc u = newu } redir := (&url.URL{ + Scheme: r.URL.Scheme, Host: r.Host, Path: u.Path, RawQuery: redirQuery.Encode(),