19362: Merge serveSiteFS into main code path.
authorTom Clegg <tom@curii.com>
Mon, 12 Sep 2022 20:09:20 +0000 (16:09 -0400)
committerTom Clegg <tom@curii.com>
Mon, 12 Sep 2022 20:09:20 +0000 (16:09 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

services/keep-web/handler.go

index 7ac8bc02dbe12a64b1dab4134141c3474bfd5ccb..0eecb1af186c2697e2aed948bc9063f94ddf90da 100644 (file)
@@ -14,7 +14,6 @@ import (
        "net/http"
        "net/url"
        "os"
-       "path/filepath"
        "sort"
        "strconv"
        "strings"
@@ -274,11 +273,6 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                }
        }
 
-       if collectionID == "" && !useSiteFS {
-               http.Error(w, notFoundMessage, http.StatusNotFound)
-               return
-       }
-
        forceReload := false
        if cc := r.Header.Get("Cache-Control"); strings.Contains(cc, "no-cache") || strings.Contains(cc, "must-revalidate") {
                forceReload = true
@@ -319,11 +313,6 @@ 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...
@@ -338,6 +327,25 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                stripParts++
        }
 
+       fsprefix := ""
+       if useSiteFS {
+               if writeMethod[r.Method] {
+                       http.Error(w, errReadOnly.Error(), http.StatusMethodNotAllowed)
+                       return
+               }
+               if len(reqTokens) == 0 {
+                       w.Header().Add("WWW-Authenticate", "Basic realm=\"collections\"")
+                       http.Error(w, unauthorizedMessage, http.StatusUnauthorized)
+                       return
+               }
+               tokens = reqTokens
+       } else if collectionID == "" {
+               http.Error(w, notFoundMessage, http.StatusNotFound)
+               return
+       } else {
+               fsprefix = "by_id/" + collectionID + "/"
+       }
+
        if tokens == nil {
                tokens = reqTokens
                if h.Cluster.Users.AnonymousUserToken != "" {
@@ -393,7 +401,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                        http.Error(w, "cache error: "+err.Error(), http.StatusInternalServerError)
                        return
                }
-               f, err := fs.OpenFile("by_id/"+collectionID, dirOpenMode, 0)
+               f, err := fs.OpenFile(fsprefix, dirOpenMode, 0)
                if errors.As(err, &statusErr) && statusErr.HTTPStatus() == http.StatusForbidden {
                        // collection id is outside token scope
                        validToken[token] = true
@@ -485,12 +493,22 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                return
        }
 
+       if r.Method == http.MethodGet || r.Method == http.MethodHead {
+               targetfnm := fsprefix + strings.Join(pathParts[stripParts:], "/")
+               if fi, err := sessionFS.Stat(targetfnm); err == nil && fi.IsDir() {
+                       if !strings.HasSuffix(r.URL.Path, "/") {
+                               h.seeOtherWithCookie(w, r, r.URL.Path+"/", credentialsOK)
+                       } else {
+                               h.serveDirectory(w, r, fi.Name(), sessionFS, targetfnm, !useSiteFS)
+                       }
+                       return
+               }
+       }
+
        var basename string
        if len(targetPath) > 0 {
                basename = targetPath[len(targetPath)-1]
        }
-       applyContentDispositionHdr(w, r, basename, attachment)
-
        if arvadosclient.PDHMatch(collectionID) && writeMethod[r.Method] {
                http.Error(w, errReadOnly.Error(), http.StatusMethodNotAllowed)
                return
@@ -499,7 +517,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                http.Error(w, "Not permitted", http.StatusForbidden)
                return
        }
-       h.logUploadOrDownload(r, session.arvadosclient, sessionFS, "by_id/"+collectionID+"/"+strings.Join(targetPath, "/"), nil, tokenUser)
+       h.logUploadOrDownload(r, session.arvadosclient, sessionFS, fsprefix+strings.Join(targetPath, "/"), nil, tokenUser)
 
        if writeMethod[r.Method] {
                // Save the collection only if/when all
@@ -516,7 +534,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                // subsequent read requests.
                client := session.client.WithRequestID(r.Header.Get("X-Request-Id"))
                sessionFS = client.SiteFileSystem(session.keepclient)
-               writingDir, err := sessionFS.OpenFile("by_id/"+collectionID, os.O_RDONLY, 0)
+               writingDir, err := sessionFS.OpenFile(fsprefix, os.O_RDONLY, 0)
                if err != nil {
                        http.Error(w, err.Error(), http.StatusInternalServerError)
                        return
@@ -544,11 +562,14 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                                return nil
                        }}
        }
+       if r.Method == http.MethodGet {
+               applyContentDispositionHdr(w, r, basename, attachment)
+       }
        wh := webdav.Handler{
                Prefix: "/" + strings.Join(pathParts[:stripParts], "/"),
                FileSystem: &webdavFS{
                        collfs:        sessionFS,
-                       prefix:        "by_id/" + collectionID + "/",
+                       prefix:        fsprefix,
                        writing:       writeMethod[r.Method],
                        alwaysReadEOF: r.Method == "PROPFIND",
                },
@@ -559,17 +580,6 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                        }
                },
        }
-       if r.Method == http.MethodGet || r.Method == http.MethodHead {
-               targetfnm := "by_id/" + collectionID + "/" + strings.Join(pathParts[stripParts:], "/")
-               if fi, err := sessionFS.Stat(targetfnm); err == nil && fi.IsDir() {
-                       if !strings.HasSuffix(r.URL.Path, "/") {
-                               h.seeOtherWithCookie(w, r, r.URL.Path+"/", credentialsOK)
-                       } else {
-                               h.serveDirectory(w, r, fi.Name(), sessionFS, targetfnm, true)
-                       }
-                       return
-               }
-       }
        wh.ServeHTTP(w, r)
        if r.Method == http.MethodGet && w.WroteStatus() == http.StatusOK {
                wrote := int64(w.WroteBodyBytes())
@@ -609,66 +619,6 @@ func (h *handler) getClients(reqID, token string) (arv *arvadosclient.ArvadosCli
        return
 }
 
-func (h *handler) serveSiteFS(w http.ResponseWriter, r *http.Request, tokens []string, credentialsOK, attachment bool) {
-       if len(tokens) == 0 {
-               w.Header().Add("WWW-Authenticate", "Basic realm=\"collections\"")
-               http.Error(w, unauthorizedMessage, http.StatusUnauthorized)
-               return
-       }
-       if writeMethod[r.Method] {
-               http.Error(w, errReadOnly.Error(), http.StatusMethodNotAllowed)
-               return
-       }
-
-       fs, sess, user, err := h.Cache.GetSession(tokens[0])
-       if err != nil {
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       }
-       f, err := fs.Open(r.URL.Path)
-       if os.IsNotExist(err) {
-               http.Error(w, err.Error(), http.StatusNotFound)
-               return
-       } else if err != nil {
-               http.Error(w, err.Error(), http.StatusInternalServerError)
-               return
-       }
-       defer f.Close()
-       if fi, err := f.Stat(); err == nil && fi.IsDir() && r.Method == "GET" {
-               if !strings.HasSuffix(r.URL.Path, "/") {
-                       h.seeOtherWithCookie(w, r, r.URL.Path+"/", credentialsOK)
-               } else {
-                       h.serveDirectory(w, r, fi.Name(), fs, r.URL.Path, false)
-               }
-               return
-       }
-
-       if !h.userPermittedToUploadOrDownload(r.Method, user) {
-               http.Error(w, "Not permitted", http.StatusForbidden)
-               return
-       }
-       h.logUploadOrDownload(r, sess.arvadosclient, fs, r.URL.Path, nil, user)
-
-       if r.Method == "GET" {
-               _, basename := filepath.Split(r.URL.Path)
-               applyContentDispositionHdr(w, r, basename, attachment)
-       }
-       wh := webdav.Handler{
-               FileSystem: &webdavFS{
-                       collfs:        fs,
-                       writing:       writeMethod[r.Method],
-                       alwaysReadEOF: r.Method == "PROPFIND",
-               },
-               LockSystem: h.webdavLS,
-               Logger: func(_ *http.Request, err error) {
-                       if err != nil {
-                               ctxlog.FromContext(r.Context()).WithError(err).Error("error reported by webdav handler")
-                       }
-               },
-       }
-       wh.ServeHTTP(w, r)
-}
-
 var dirListingTemplate = `<!DOCTYPE HTML>
 <HTML><HEAD>
   <META name="robots" content="NOINDEX">