mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-13 22:36:27 +03:00
file_server: Optional pass_thru mode
If enabled, will call the next handler in the chain instead of returning a 404.
This commit is contained in:
parent
1228dd7d93
commit
b43e986a52
2 changed files with 24 additions and 7 deletions
|
@ -34,7 +34,7 @@ type Browse struct {
|
|||
template *template.Template
|
||||
}
|
||||
|
||||
func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *http.Request) error {
|
||||
func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
|
||||
// navigation on the client-side gets messed up if the
|
||||
// URL doesn't end in a trailing slash because hrefs like
|
||||
// "/b/c" on a path like "/a" end up going to "/b/c" instead
|
||||
|
@ -59,7 +59,7 @@ func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *ht
|
|||
case os.IsPermission(err):
|
||||
return caddyhttp.Error(http.StatusForbidden, err)
|
||||
case os.IsNotExist(err):
|
||||
return caddyhttp.Error(http.StatusNotFound, err)
|
||||
return fsrv.notFound(w, r, next)
|
||||
case err != nil:
|
||||
return caddyhttp.Error(http.StatusInternalServerError, err)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ type FileServer struct {
|
|||
IndexNames []string `json:"index_names,omitempty"`
|
||||
Browse *Browse `json:"browse,omitempty"`
|
||||
CanonicalURIs *bool `json:"canonical_uris,omitempty"`
|
||||
PassThru bool `json:"pass_thru,omitempty"` // if 404, call next handler instead
|
||||
}
|
||||
|
||||
// CaddyModule returns the Caddy module information.
|
||||
|
@ -87,7 +88,7 @@ func (fsrv *FileServer) Provision(ctx caddy.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ caddyhttp.Handler) error {
|
||||
func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
|
||||
repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
|
||||
|
||||
filesToHide := fsrv.transformHidePaths(repl)
|
||||
|
@ -101,7 +102,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd
|
|||
if err != nil {
|
||||
err = mapDirOpenError(err, filename)
|
||||
if os.IsNotExist(err) {
|
||||
return caddyhttp.Error(http.StatusNotFound, err)
|
||||
return fsrv.notFound(w, r, next)
|
||||
} else if os.IsPermission(err) {
|
||||
return caddyhttp.Error(http.StatusForbidden, err)
|
||||
}
|
||||
|
@ -144,17 +145,20 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd
|
|||
// to browse or return an error
|
||||
if info.IsDir() {
|
||||
if fsrv.Browse != nil && !fileHidden(filename, filesToHide) {
|
||||
return fsrv.serveBrowse(filename, w, r)
|
||||
return fsrv.serveBrowse(filename, w, r, next)
|
||||
}
|
||||
return caddyhttp.Error(http.StatusNotFound, nil)
|
||||
return fsrv.notFound(w, r, next)
|
||||
}
|
||||
|
||||
// TODO: maybe there should be a way to serve the next handler
|
||||
// instead of returning 404 if a file is not found?
|
||||
|
||||
// TODO: content negotiation (brotli sidecar files, etc...)
|
||||
|
||||
// one last check to ensure the file isn't hidden (we might
|
||||
// have changed the filename from when we last checked)
|
||||
if fileHidden(filename, filesToHide) {
|
||||
return caddyhttp.Error(http.StatusNotFound, nil)
|
||||
return fsrv.notFound(w, r, next)
|
||||
}
|
||||
|
||||
// if URL canonicalization is enabled, we need to enforce trailing
|
||||
|
@ -172,6 +176,10 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd
|
|||
// open the file
|
||||
file, err := fsrv.openFile(filename, w)
|
||||
if err != nil {
|
||||
if herr, ok := err.(caddyhttp.HandlerError); ok &&
|
||||
herr.StatusCode == http.StatusNotFound {
|
||||
return fsrv.notFound(w, r, next)
|
||||
}
|
||||
return err // error is already structured
|
||||
}
|
||||
defer file.Close()
|
||||
|
@ -336,6 +344,15 @@ func fileHidden(filename string, hide []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// notFound returns a 404 error or, if pass-thru is enabled,
|
||||
// it calls the next handler in the chain.
|
||||
func (fsrv *FileServer) notFound(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
|
||||
if fsrv.PassThru {
|
||||
return next.ServeHTTP(w, r)
|
||||
}
|
||||
return caddyhttp.Error(http.StatusNotFound, nil)
|
||||
}
|
||||
|
||||
// calculateEtag produces a strong etag by default, although, for
|
||||
// efficiency reasons, it does not actually consume the contents
|
||||
// of the file to make a hash of all the bytes. ¯\_(ツ)_/¯
|
||||
|
|
Loading…
Reference in a new issue