From 3f6283b385642c56f34b479d1275095379b062d3 Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Thu, 8 Apr 2021 13:09:12 -0400 Subject: fileserver: Add status code override (#4076) After reading a question about the `handle_response` feature of `reverse_proxy`, I realized that we didn't have a way of serving an arbitrary file with a status code other than 200. This is an issue in situations where you want to serve a custom error page in routes that are not errors, like the aforementioned `handle_response`, where you may want to retain the status code returned by the proxy but write a response with content from a file. This feature is super simple, basically if a status code is configured (can be a status code number, or a placeholder string) then that status will be written out before serving the file - if we write the status code first, then the stdlib won't write its own (only the first HTTP status header wins). --- modules/caddyhttp/fileserver/staticfiles.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'modules/caddyhttp/fileserver/staticfiles.go') diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go index c670788..660e1d1 100644 --- a/modules/caddyhttp/fileserver/staticfiles.go +++ b/modules/caddyhttp/fileserver/staticfiles.go @@ -75,6 +75,12 @@ type FileServer struct { // remove trailing slash from URIs for files. Default is true. CanonicalURIs *bool `json:"canonical_uris,omitempty"` + // Override the status code written when successfully serving a file. + // Particularly useful when explicitly serving a file as display for + // an error, like a 404 page. A placeholder may be used. By default, + // the status code will typically be 200, or 206 for partial content. + StatusCode caddyhttp.WeakString `json:"status_code,omitempty"` + // If pass-thru mode is enabled and a requested file is not found, // it will invoke the next handler in the chain instead of returning // a 404 error. By default, this is false (disabled). @@ -345,6 +351,16 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c return nil } + // if a status code override is configured, write the status code + // before serving the file + if codeStr := fsrv.StatusCode.String(); codeStr != "" { + intVal, err := strconv.Atoi(repl.ReplaceAll(codeStr, "")) + if err != nil { + return caddyhttp.Error(http.StatusInternalServerError, err) + } + w.WriteHeader(intVal) + } + // let the standard library do what it does best; note, however, // that errors generated by ServeContent are written immediately // to the response, so we cannot handle them (but errors there -- cgit v1.2.3