diff options
author | 2022-07-18 12:55:06 +0200 | |
---|---|---|
committer | 2022-07-18 12:55:06 +0200 | |
commit | c3b6a5b0f9976c861042d03b7fc124d566b9209f (patch) | |
tree | 17076ac4484d339b4eeae90a5e37c1f7c9d6b638 /internal/web/base.go | |
parent | [chore] move dialer inside new (#715) (diff) | |
download | gotosocial-c3b6a5b0f9976c861042d03b7fc124d566b9209f.tar.xz |
[feature] Implement `cache-control` and etags for static assets (#711)
* start working on etag stuff
* add + use cache middleware
* generate etags on the fly
* remove unused field
* clean up filepath
* add license headers to cache files
* add attachgroup function to router interface
* move cache into web module
* rename a couple things
* remove attachStaticFS function from router
* rename + tidy up a few things
* mount assets filesystem
* create assetsFileInfoCache
* update comment
* simplify hash
* fix string fmt
* skip last mod chk, prefer strong etags w/long cache
* move base handler to its own file
this matches the modules in the api folder
* generate new etag if file was modified
* wrap strong etag in quotation marks as per spec
* clarify logic in avatar search
* make hashing a little niftier
Diffstat (limited to 'internal/web/base.go')
-rw-r--r-- | internal/web/base.go | 157 |
1 files changed, 0 insertions, 157 deletions
diff --git a/internal/web/base.go b/internal/web/base.go index 8e7e539f6..27e7d41c1 100644 --- a/internal/web/base.go +++ b/internal/web/base.go @@ -19,89 +19,14 @@ package web import ( - "errors" - "fmt" - "io/ioutil" "net/http" - "path/filepath" - "strings" "github.com/gin-gonic/gin" "github.com/superseriousbusiness/gotosocial/internal/api" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/gtserror" - "github.com/superseriousbusiness/gotosocial/internal/processing" - "github.com/superseriousbusiness/gotosocial/internal/router" - "github.com/superseriousbusiness/gotosocial/internal/uris" ) -const ( - confirmEmailPath = "/" + uris.ConfirmEmailPath - tokenParam = "token" - usernameKey = "username" - statusIDKey = "status" - profilePath = "/@:" + usernameKey - statusPath = profilePath + "/statuses/:" + statusIDKey -) - -// Module implements the api.ClientModule interface for web pages. -type Module struct { - processor processing.Processor - assetsPath string - adminPath string - defaultAvatars []string -} - -// New returns a new api.ClientModule for web pages. -func New(processor processing.Processor) (api.ClientModule, error) { - assetsBaseDir := config.GetWebAssetBaseDir() - if assetsBaseDir == "" { - return nil, fmt.Errorf("%s cannot be empty and must be a relative or absolute path", config.WebAssetBaseDirFlag()) - } - - assetsPath, err := filepath.Abs(assetsBaseDir) - if err != nil { - return nil, fmt.Errorf("error getting absolute path of %s: %s", assetsBaseDir, err) - } - - defaultAvatarsPath := filepath.Join(assetsPath, "default_avatars") - defaultAvatarFiles, err := ioutil.ReadDir(defaultAvatarsPath) - if err != nil { - return nil, fmt.Errorf("error reading default avatars at %s: %s", defaultAvatarsPath, err) - } - - defaultAvatars := []string{} - for _, f := range defaultAvatarFiles { - // ignore directories - if f.IsDir() { - continue - } - - // ignore files bigger than 50kb - if f.Size() > 50000 { - continue - } - - extension := strings.TrimPrefix(strings.ToLower(filepath.Ext(f.Name())), ".") - - // take only files with simple extensions - switch extension { - case "svg", "jpeg", "jpg", "gif", "png": - defaultAvatarPath := fmt.Sprintf("/assets/default_avatars/%s", f.Name()) - defaultAvatars = append(defaultAvatars, defaultAvatarPath) - default: - continue - } - } - - return &Module{ - processor: processor, - assetsPath: assetsPath, - adminPath: filepath.Join(assetsPath, "admin"), - defaultAvatars: defaultAvatars, - }, nil -} - func (m *Module) baseHandler(c *gin.Context) { host := config.GetHost() instance, err := m.processor.InstanceGet(c.Request.Context(), host) @@ -114,85 +39,3 @@ func (m *Module) baseHandler(c *gin.Context) { "instance": instance, }) } - -// TODO: abstract the {admin, user}panel handlers in some way -func (m *Module) AdminPanelHandler(c *gin.Context) { - host := config.GetHost() - instance, err := m.processor.InstanceGet(c.Request.Context(), host) - if err != nil { - api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet) - return - } - - c.HTML(http.StatusOK, "frontend.tmpl", gin.H{ - "instance": instance, - "stylesheets": []string{ - "/assets/Fork-Awesome/css/fork-awesome.min.css", - "/assets/dist/panels-admin-style.css", - }, - "javascript": []string{ - "/assets/dist/bundle.js", - "/assets/dist/admin-panel.js", - }, - }) -} - -func (m *Module) UserPanelHandler(c *gin.Context) { - host := config.GetHost() - instance, err := m.processor.InstanceGet(c.Request.Context(), host) - if err != nil { - api.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet) - return - } - - c.HTML(http.StatusOK, "frontend.tmpl", gin.H{ - "instance": instance, - "stylesheets": []string{ - "/assets/Fork-Awesome/css/fork-awesome.min.css", - "/assets/dist/_colors.css", - "/assets/dist/base.css", - "/assets/dist/panels-user-style.css", - }, - "javascript": []string{ - "/assets/dist/bundle.js", - "/assets/dist/user-panel.js", - }, - }) -} - -// Route satisfies the RESTAPIModule interface -func (m *Module) Route(s router.Router) error { - // serve static files from assets dir at /assets - s.AttachStaticFS("/assets", fileSystem{http.Dir(m.assetsPath)}) - - s.AttachHandler(http.MethodGet, "/admin", m.AdminPanelHandler) - // redirect /admin/ to /admin - s.AttachHandler(http.MethodGet, "/admin/", func(c *gin.Context) { - c.Redirect(http.StatusMovedPermanently, "/admin") - }) - - s.AttachHandler(http.MethodGet, "/user", m.UserPanelHandler) - // redirect /settings/ to /settings - s.AttachHandler(http.MethodGet, "/user/", func(c *gin.Context) { - c.Redirect(http.StatusMovedPermanently, "/user") - }) - - // serve front-page - s.AttachHandler(http.MethodGet, "/", m.baseHandler) - - // serve profile pages at /@username - s.AttachHandler(http.MethodGet, profilePath, m.profileGETHandler) - - // serve statuses - s.AttachHandler(http.MethodGet, statusPath, m.threadGETHandler) - - // serve email confirmation page at /confirm_email?token=whatever - s.AttachHandler(http.MethodGet, confirmEmailPath, m.confirmEmailGETHandler) - - // 404 handler - s.AttachNoRouteHandler(func(c *gin.Context) { - api.ErrorHandler(c, gtserror.NewErrorNotFound(errors.New(http.StatusText(http.StatusNotFound))), m.processor.InstanceGet) - }) - - return nil -} |