@marcel91200 / caddy Mirror · read-only / commits / b43e986a
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

file_server: Optional pass_thru mode

If enabled, will call the next handler in the chain instead of returning a 404.

Matthew Holt committed Nov 15, 2019 at 17:32 UTC b43e986a526c9de83c04c29bc530f1d711a40997
2 files changed +24 -7
modules/caddyhttp/fileserver/browse.go
+2 -2
@@ -34,7 +34,7 @@ type Browse struct {
34 template *template.Template
35 }
36
37 -func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *http.Request) error {
37 +func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
38 // navigation on the client-side gets messed up if the
39 // URL doesn't end in a trailing slash because hrefs like
40 // "/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
59 case os.IsPermission(err):
60 return caddyhttp.Error(http.StatusForbidden, err)
61 case os.IsNotExist(err):
62 - return caddyhttp.Error(http.StatusNotFound, err)
62 + return fsrv.notFound(w, r, next)
63 case err != nil:
64 return caddyhttp.Error(http.StatusInternalServerError, err)
65 }
modules/caddyhttp/fileserver/staticfiles.go
+22 -5
@@ -47,6 +47,7 @@ type FileServer struct {
47 IndexNames []string `json:"index_names,omitempty"`
48 Browse *Browse `json:"browse,omitempty"`
49 CanonicalURIs *bool `json:"canonical_uris,omitempty"`
50 + PassThru bool `json:"pass_thru,omitempty"` // if 404, call next handler instead
51 }
52
53 // CaddyModule returns the Caddy module information.
@@ -87,7 +88,7 @@ func (fsrv *FileServer) Provision(ctx caddy.Context) error {
88 return nil
89 }
90
90 -func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ caddyhttp.Handler) error {
91 +func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
92 repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
93
94 filesToHide := fsrv.transformHidePaths(repl)
@@ -101,7 +102,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd
102 if err != nil {
103 err = mapDirOpenError(err, filename)
104 if os.IsNotExist(err) {
104 - return caddyhttp.Error(http.StatusNotFound, err)
105 + return fsrv.notFound(w, r, next)
106 } else if os.IsPermission(err) {
107 return caddyhttp.Error(http.StatusForbidden, err)
108 }
@@ -144,17 +145,20 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd
145 // to browse or return an error
146 if info.IsDir() {
147 if fsrv.Browse != nil && !fileHidden(filename, filesToHide) {
147 - return fsrv.serveBrowse(filename, w, r)
148 + return fsrv.serveBrowse(filename, w, r, next)
149 }
149 - return caddyhttp.Error(http.StatusNotFound, nil)
150 + return fsrv.notFound(w, r, next)
151 }
152
153 + // TODO: maybe there should be a way to serve the next handler
154 + // instead of returning 404 if a file is not found?
155 +
156 // TODO: content negotiation (brotli sidecar files, etc...)
157
158 // one last check to ensure the file isn't hidden (we might
159 // have changed the filename from when we last checked)
160 if fileHidden(filename, filesToHide) {
157 - return caddyhttp.Error(http.StatusNotFound, nil)
161 + return fsrv.notFound(w, r, next)
162 }
163
164 // 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
176 // open the file
177 file, err := fsrv.openFile(filename, w)
178 if err != nil {
179 + if herr, ok := err.(caddyhttp.HandlerError); ok &&
180 + herr.StatusCode == http.StatusNotFound {
181 + return fsrv.notFound(w, r, next)
182 + }
183 return err // error is already structured
184 }
185 defer file.Close()
@@ -336,6 +344,15 @@ func fileHidden(filename string, hide []string) bool {
344 return false
345 }
346
347 +// notFound returns a 404 error or, if pass-thru is enabled,
348 +// it calls the next handler in the chain.
349 +func (fsrv *FileServer) notFound(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
350 + if fsrv.PassThru {
351 + return next.ServeHTTP(w, r)
352 + }
353 + return caddyhttp.Error(http.StatusNotFound, nil)
354 +}
355 +
356 // calculateEtag produces a strong etag by default, although, for
357 // efficiency reasons, it does not actually consume the contents
358 // of the file to make a hash of all the bytes. ¯\_(ツ)_/¯