Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce FS.CompressRoot #1331

Merged
merged 5 commits into from Jul 10, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 41 additions & 14 deletions fs.go
Expand Up @@ -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.
Expand Down Expand Up @@ -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()
Expand All @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -478,6 +493,7 @@ type fsHandler struct {
generateIndexPages bool
compress bool
compressBrotli bool
compressRoot string
acceptByteRange bool
cacheDuration time.Duration
compressedFileSuffixes map[string]string
Expand Down Expand Up @@ -834,19 +850,19 @@ func (h *fsHandler) handleRequest(ctx *RequestCtx) {
filePath := filepath.FromSlash(h.root + pathStr)

var err error
ff, err = h.openFSFile(filePath, mustCompress, fileEncoding)
ff, err = h.openFSFile(pathStr, filePath, mustCompress, fileEncoding)
if mustCompress && err == errNoCreatePermission {
ctx.Logger().Printf("insufficient permissions for saving compressed file for %q. Serving uncompressed file. "+
"Allow write access to the directory with this file in order to improve fasthttp performance", filePath)
mustCompress = false
ff, err = h.openFSFile(filePath, mustCompress, fileEncoding)
ff, err = h.openFSFile(pathStr, filePath, mustCompress, fileEncoding)
}
if err == errDirIndexRequired {
if !hasTrailingSlash {
ctx.RedirectBytes(append(path, '/'), StatusFound)
return
}
ff, err = h.openIndexFile(ctx, filePath, mustCompress, fileEncoding)
ff, err = h.openIndexFile(ctx, pathStr, filePath, mustCompress, fileEncoding)
if err != nil {
ctx.Logger().Printf("cannot open dir index %q: %v", filePath, err)
ctx.Error("Directory index is forbidden", StatusForbidden)
Expand Down Expand Up @@ -1012,10 +1028,11 @@ func ParseByteRange(byteRange []byte, contentLength int) (startPos, endPos int,
return startPos, endPos, nil
}

func (h *fsHandler) openIndexFile(ctx *RequestCtx, dirPath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
func (h *fsHandler) openIndexFile(ctx *RequestCtx, path, dirPath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
for _, indexName := range h.indexNames {
indexFilePath := dirPath + "/" + indexName
ff, err := h.openFSFile(indexFilePath, mustCompress, fileEncoding)
indexPath := path + "/" + indexName
indexFilePath := filepath.Join(dirPath, indexName)
ff, err := h.openFSFile(indexPath, indexFilePath, mustCompress, fileEncoding)
if err == nil {
return ff, nil
}
Expand Down Expand Up @@ -1130,7 +1147,7 @@ const (
fsMaxCompressibleFileSize = 8 * 1024 * 1024
)

func (h *fsHandler) compressAndOpenFSFile(filePath string, fileEncoding string) (*fsFile, error) {
func (h *fsHandler) compressAndOpenFSFile(path, filePath string, fileEncoding string) (*fsFile, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you come up wit ha better name for path here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which do you think better?

f, err := os.Open(filePath)
if err != nil {
return nil, err
Expand All @@ -1153,7 +1170,17 @@ func (h *fsHandler) compressAndOpenFSFile(filePath string, fileEncoding string)
return h.newFSFile(f, fileInfo, false, "")
}

compressedFilePath := filePath + h.compressedFileSuffixes[fileEncoding]
var compressedFilePath string
if h.root == h.compressRoot {
compressedFilePath = filePath
} else {
compressedFilePath = filepath.FromSlash(h.compressRoot + path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is filepath.FromSlash needed here while it isn't for h.root?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. 5f432d9

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()
Expand Down Expand Up @@ -1232,7 +1259,7 @@ func (h *fsHandler) newCompressedFSFile(filePath string, fileEncoding string) (*
return h.newFSFile(f, fileInfo, true, fileEncoding)
}

func (h *fsHandler) openFSFile(filePath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
func (h *fsHandler) openFSFile(path string, filePath string, mustCompress bool, fileEncoding string) (*fsFile, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you come up wit ha better name for path here?

filePathOriginal := filePath
if mustCompress {
filePath += h.compressedFileSuffixes[fileEncoding]
Expand All @@ -1241,7 +1268,7 @@ func (h *fsHandler) openFSFile(filePath string, mustCompress bool, fileEncoding
f, err := os.Open(filePath)
if err != nil {
if mustCompress && os.IsNotExist(err) {
return h.compressAndOpenFSFile(filePathOriginal, fileEncoding)
return h.compressAndOpenFSFile(path, filePathOriginal, fileEncoding)
}
return nil, err
}
Expand Down Expand Up @@ -1275,7 +1302,7 @@ func (h *fsHandler) openFSFile(filePath string, mustCompress bool, fileEncoding
// The compressed file became stale. Re-create it.
_ = f.Close()
_ = os.Remove(filePath)
return h.compressAndOpenFSFile(filePathOriginal, fileEncoding)
return h.compressAndOpenFSFile(path, filePathOriginal, fileEncoding)
}
}

Expand Down