mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 16:30:01 +08:00
feat: handle using root as the path of file server (#4255)
This commit is contained in:
@@ -3,18 +3,19 @@ package fileserver
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Middleware returns a middleware that serves files from the given file system.
|
||||
func Middleware(path string, fs http.FileSystem) func(http.HandlerFunc) http.HandlerFunc {
|
||||
fileServer := http.FileServer(fs)
|
||||
pathWithTrailSlash := ensureTrailingSlash(path)
|
||||
pathWithoutTrailSlash := ensureNoTrailingSlash(path)
|
||||
canServe := createServeChecker(path, fs)
|
||||
|
||||
return func(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, pathWithTrailSlash) {
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, pathWithoutTrailSlash)
|
||||
if canServe(r) {
|
||||
r.URL.Path = r.URL.Path[len(pathWithoutTrailSlash):]
|
||||
fileServer.ServeHTTP(w, r)
|
||||
} else {
|
||||
next(w, r)
|
||||
@@ -23,6 +24,44 @@ func Middleware(path string, fs http.FileSystem) func(http.HandlerFunc) http.Han
|
||||
}
|
||||
}
|
||||
|
||||
func createFileChecker(fs http.FileSystem) func(string) bool {
|
||||
var lock sync.RWMutex
|
||||
fileChecker := make(map[string]bool)
|
||||
|
||||
return func(path string) bool {
|
||||
lock.RLock()
|
||||
exist, ok := fileChecker[path]
|
||||
lock.RUnlock()
|
||||
if ok {
|
||||
return exist
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
file, err := fs.Open(path)
|
||||
exist = err == nil
|
||||
fileChecker[path] = exist
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_ = file.Close()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func createServeChecker(path string, fs http.FileSystem) func(r *http.Request) bool {
|
||||
pathWithTrailSlash := ensureTrailingSlash(path)
|
||||
fileChecker := createFileChecker(fs)
|
||||
|
||||
return func(r *http.Request) bool {
|
||||
return r.Method == http.MethodGet &&
|
||||
strings.HasPrefix(r.URL.Path, pathWithTrailSlash) &&
|
||||
fileChecker(r.URL.Path[len(pathWithTrailSlash):])
|
||||
}
|
||||
}
|
||||
|
||||
func ensureTrailingSlash(path string) string {
|
||||
if strings.HasSuffix(path, "/") {
|
||||
return path
|
||||
|
||||
Reference in New Issue
Block a user