14324: Use logrus in Azure driver. Fix Sirupsen->sirupsen in imports
[arvados.git] / services / keep-web / handler.go
index 517ec1a2a26e96967ad50bec925a65b1f6149f6a..b5c11e553c115c872d5ded605e0ad3b54956d406 100644 (file)
@@ -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
@@ -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
@@ -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=") {
@@ -315,7 +326,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
 
        if useSiteFS {
                if tokens == nil {
-                       tokens = auth.NewCredentialsFromHTTPRequest(r).Tokens
+                       tokens = auth.CredentialsFromRequest(r).Tokens
                }
                h.serveSiteFS(w, r, tokens, credentialsOK, attachment)
                return
@@ -337,7 +348,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
 
        if tokens == nil {
                if credentialsOK {
-                       reqTokens = auth.NewCredentialsFromHTTPRequest(r).Tokens
+                       reqTokens = auth.CredentialsFromRequest(r).Tokens
                }
                tokens = append(reqTokens, h.Config.AnonymousTokens...)
        }
@@ -773,6 +784,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(),