feat: browser cache directives
parent
603203848a
commit
190cb99a79
|
@ -94,7 +94,7 @@ export default {
|
||||||
// reload the image when the file is replaced
|
// reload the image when the file is replaced
|
||||||
const key = Date.parse(this.modified);
|
const key = Date.parse(this.modified);
|
||||||
|
|
||||||
return `${baseURL}/api/preview/thumb/${path}?auth=${this.jwt}&inline=true&k=${key}`;
|
return `${baseURL}/api/preview/thumb/${path}?k=${key}&inline=true`;
|
||||||
},
|
},
|
||||||
isThumbsEnabled() {
|
isThumbsEnabled() {
|
||||||
return enableThumbs;
|
return enableThumbs;
|
||||||
|
|
|
@ -12,6 +12,8 @@ export function parseToken(token) {
|
||||||
|
|
||||||
const data = JSON.parse(Base64.decode(parts[1]));
|
const data = JSON.parse(Base64.decode(parts[1]));
|
||||||
|
|
||||||
|
document.cookie = `auth=${token}; path=/`;
|
||||||
|
|
||||||
localStorage.setItem("jwt", token);
|
localStorage.setItem("jwt", token);
|
||||||
store.commit("setJWT", token);
|
store.commit("setJWT", token);
|
||||||
store.commit("setUser", data.user);
|
store.commit("setUser", data.user);
|
||||||
|
@ -81,6 +83,8 @@ export async function signup(username, password) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
|
document.cookie = "auth=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/";
|
||||||
|
|
||||||
store.commit("setJWT", "");
|
store.commit("setJWT", "");
|
||||||
store.commit("setUser", null);
|
store.commit("setUser", null);
|
||||||
localStorage.setItem("jwt", null);
|
localStorage.setItem("jwt", null);
|
||||||
|
|
|
@ -414,7 +414,7 @@ export default {
|
||||||
window.removeEventListener("scroll", this.scrollEvent);
|
window.removeEventListener("scroll", this.scrollEvent);
|
||||||
window.removeEventListener("resize", this.windowsResize);
|
window.removeEventListener("resize", this.windowsResize);
|
||||||
|
|
||||||
if (!this.user.perm.create) return;
|
if (this.user && !this.user.perm.create) return;
|
||||||
document.removeEventListener("dragover", this.preventDefault);
|
document.removeEventListener("dragover", this.preventDefault);
|
||||||
document.removeEventListener("dragenter", this.dragEnter);
|
document.removeEventListener("dragenter", this.dragEnter);
|
||||||
document.removeEventListener("dragleave", this.dragLeave);
|
document.removeEventListener("dragleave", this.dragLeave);
|
||||||
|
|
|
@ -175,11 +175,9 @@ export default {
|
||||||
if (this.req.type === "image" && !this.fullSize) {
|
if (this.req.type === "image" && !this.fullSize) {
|
||||||
return `${baseURL}/api/preview/big${url.encodePath(
|
return `${baseURL}/api/preview/big${url.encodePath(
|
||||||
this.req.path
|
this.req.path
|
||||||
)}?auth=${this.jwt}&k=${key}`;
|
)}?k=${key}`;
|
||||||
}
|
}
|
||||||
return `${baseURL}/api/raw${url.encodePath(this.req.path)}?auth=${
|
return `${baseURL}/api/raw${url.encodePath(this.req.path)}?k=${key}`;
|
||||||
this.jwt
|
|
||||||
}&k=${key}`;
|
|
||||||
},
|
},
|
||||||
raw() {
|
raw() {
|
||||||
return `${this.previewUrl}&inline=true`;
|
return `${this.previewUrl}&inline=true`;
|
||||||
|
@ -257,7 +255,7 @@ export default {
|
||||||
|
|
||||||
if (this.req.subtitles) {
|
if (this.req.subtitles) {
|
||||||
this.subtitles = this.req.subtitles.map(
|
this.subtitles = this.req.subtitles.map(
|
||||||
(sub) => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`
|
(sub) => `${baseURL}/api/raw${sub}?inline=true`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
http/auth.go
11
http/auth.go
|
@ -48,11 +48,16 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auth := r.URL.Query().Get("auth")
|
auth := r.URL.Query().Get("auth")
|
||||||
if auth == "" {
|
if auth != "" && strings.Count(auth, ".") == 2 {
|
||||||
return "", request.ErrNoTokenInRequest
|
return auth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return auth, nil
|
cookie, _ := r.Cookie("auth")
|
||||||
|
if cookie != nil && strings.Count(cookie.Value, ".") == 2 {
|
||||||
|
return cookie.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", request.ErrNoTokenInRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
func withUser(fn handleFunc) handleFunc {
|
func withUser(fn handleFunc) handleFunc {
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (d *data) Check(path string) bool {
|
||||||
|
|
||||||
func handle(fn handleFunc, prefix string, store *storage.Storage, server *settings.Server) http.Handler {
|
func handle(fn handleFunc, prefix string, store *storage.Storage, server *settings.Server) http.Handler {
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Cache-Control", "no-cache")
|
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||||
|
|
||||||
settings, err := store.Settings.Get()
|
settings, err := store.Settings.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -79,6 +79,11 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, imgSvc ImgServic
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isFresh := checkEtag(w, r, file.ModTime.Unix(), file.Size)
|
||||||
|
if isFresh {
|
||||||
|
return http.StatusNotModified, nil
|
||||||
|
}
|
||||||
|
|
||||||
cacheKey := previewCacheKey(file.Path, file.ModTime.Unix(), previewSize)
|
cacheKey := previewCacheKey(file.Path, file.ModTime.Unix(), previewSize)
|
||||||
cachedFile, ok, err := fileCache.Load(r.Context(), cacheKey)
|
cachedFile, ok, err := fileCache.Load(r.Context(), cacheKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -204,6 +204,11 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files.
|
||||||
}
|
}
|
||||||
|
|
||||||
func rawFileHandler(w http.ResponseWriter, r *http.Request, file *files.FileInfo) (int, error) {
|
func rawFileHandler(w http.ResponseWriter, r *http.Request, file *files.FileInfo) (int, error) {
|
||||||
|
isFresh := checkEtag(w, r, file.ModTime.Unix(), file.Size)
|
||||||
|
if isFresh {
|
||||||
|
return http.StatusNotModified, nil
|
||||||
|
}
|
||||||
|
|
||||||
fd, err := file.Fs.Open(file.Path)
|
fd, err := file.Fs.Open(file.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -109,6 +110,9 @@ func getStaticHandlers(store *storage.Storage, server *settings.Server, assetsFs
|
||||||
return http.StatusNotFound, nil
|
return http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxAge = 86400 // 1 day
|
||||||
|
w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%v", maxAge))
|
||||||
|
|
||||||
if d.settings.Branding.Files != "" {
|
if d.settings.Branding.Files != "" {
|
||||||
if strings.HasPrefix(r.URL.Path, "img/") {
|
if strings.HasPrefix(r.URL.Path, "img/") {
|
||||||
fPath := filepath.Join(d.settings.Branding.Files, r.URL.Path)
|
fPath := filepath.Join(d.settings.Branding.Files, r.URL.Path)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package http
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
@ -66,3 +67,11 @@ func stripPrefix(prefix string, h http.Handler) http.Handler {
|
||||||
h.ServeHTTP(w, r2)
|
h.ServeHTTP(w, r2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkEtag(w http.ResponseWriter, r *http.Request, fTime, fSize int64) bool {
|
||||||
|
etag := fmt.Sprintf("%x%x", fTime, fSize)
|
||||||
|
w.Header().Set("Cache-Control", "private")
|
||||||
|
w.Header().Set("Etag", etag)
|
||||||
|
|
||||||
|
return r.Header.Get("If-None-Match") == etag
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue