From f3513ccc593abf5b4a6d34b9a8498f83f4f5b983 Mon Sep 17 00:00:00 2001 From: mojatter Date: Sun, 10 Jul 2022 17:07:18 +0900 Subject: [PATCH] Introduce FS.CompressRoot (#1331) * Introduce FS.CompressRoot * Avoid duplicated filepath.FromSlash * Introduce filePathToCompressed * Revert openIndexFile manually * Join root and path, and then calls filepath.FromSlash --- fs.go | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/fs.go b/fs.go index 4bbb3fd671..8491864565 100644 --- a/fs.go +++ b/fs.go @@ -276,6 +276,10 @@ type FS struct { // Brotli encoding is disabled by default. CompressBrotli bool + // Path to the compressed root directory to serve files from. If this value + // is empty, Root is used. + CompressRoot string + // Enables byte range requests if set to true. // // Byte range requests are disabled by default. @@ -388,9 +392,7 @@ func (fs *FS) NewRequestHandler() RequestHandler { return fs.h } -func (fs *FS) initRequestHandler() { - root := fs.Root - +func (fs *FS) normalizeRoot(root string) string { // Serve files from the current working directory if Root is empty or if Root is a relative path. if (!fs.AllowEmptyRoot && len(root) == 0) || (len(root) > 0 && !filepath.IsAbs(root)) { path, err := os.Getwd() @@ -406,6 +408,18 @@ func (fs *FS) initRequestHandler() { for len(root) > 0 && root[len(root)-1] == os.PathSeparator { root = root[:len(root)-1] } + return root +} + +func (fs *FS) initRequestHandler() { + root := fs.normalizeRoot(fs.Root) + + compressRoot := fs.CompressRoot + if len(compressRoot) == 0 { + compressRoot = root + } else { + compressRoot = fs.normalizeRoot(compressRoot) + } cacheDuration := fs.CacheDuration if cacheDuration <= 0 { @@ -430,6 +444,7 @@ func (fs *FS) initRequestHandler() { generateIndexPages: fs.GenerateIndexPages, compress: fs.Compress, compressBrotli: fs.CompressBrotli, + compressRoot: compressRoot, pathNotFound: fs.PathNotFound, acceptByteRange: fs.AcceptByteRange, cacheDuration: cacheDuration, @@ -478,6 +493,7 @@ type fsHandler struct { generateIndexPages bool compress bool compressBrotli bool + compressRoot string acceptByteRange bool cacheDuration time.Duration compressedFileSuffixes map[string]string @@ -780,6 +796,20 @@ func cleanCacheNolock(cache map[string]*fsFile, pendingFiles, filesToRelease []* return pendingFiles, filesToRelease } +func (h *fsHandler) pathToFilePath(path string) string { + return filepath.FromSlash(h.root + path) +} + +func (h *fsHandler) filePathToCompressed(filePath string) string { + if h.root == h.compressRoot { + return filePath + } + if !strings.HasPrefix(filePath, h.root) { + return filePath + } + return filepath.FromSlash(h.compressRoot + filePath[len(h.root):]) +} + func (h *fsHandler) handleRequest(ctx *RequestCtx) { var path []byte if h.pathRewrite != nil { @@ -831,7 +861,7 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) { if !ok { pathStr := string(path) - filePath := filepath.FromSlash(h.root + pathStr) + filePath := h.pathToFilePath(pathStr) var err error ff, err = h.openFSFile(filePath, mustCompress, fileEncoding) @@ -1153,7 +1183,14 @@ func (h *fsHandler) compressAndOpenFSFile(filePath string, fileEncoding string) return h.newFSFile(f, fileInfo, false, "") } - compressedFilePath := filePath + h.compressedFileSuffixes[fileEncoding] + compressedFilePath := h.filePathToCompressed(filePath) + if compressedFilePath != filePath { + if err := os.MkdirAll(filepath.Dir(compressedFilePath), os.ModePerm); err != nil { + return nil, err + } + } + compressedFilePath += h.compressedFileSuffixes[fileEncoding] + absPath, err := filepath.Abs(compressedFilePath) if err != nil { _ = f.Close()