summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--caddytest/integration/caddyfile_adapt/file_server_status.txt112
-rw-r--r--modules/caddyhttp/fileserver/caddyfile.go12
-rw-r--r--modules/caddyhttp/fileserver/staticfiles.go16
3 files changed, 140 insertions, 0 deletions
diff --git a/caddytest/integration/caddyfile_adapt/file_server_status.txt b/caddytest/integration/caddyfile_adapt/file_server_status.txt
new file mode 100644
index 0000000..ede1f4a
--- /dev/null
+++ b/caddytest/integration/caddyfile_adapt/file_server_status.txt
@@ -0,0 +1,112 @@
+localhost
+
+root * /srv
+
+handle /nope* {
+ file_server {
+ status 403
+ }
+}
+
+handle /custom-status* {
+ file_server {
+ status {env.CUSTOM_STATUS}
+ }
+}
+----------
+{
+ "apps": {
+ "http": {
+ "servers": {
+ "srv0": {
+ "listen": [
+ ":443"
+ ],
+ "routes": [
+ {
+ "match": [
+ {
+ "host": [
+ "localhost"
+ ]
+ }
+ ],
+ "handle": [
+ {
+ "handler": "subroute",
+ "routes": [
+ {
+ "handle": [
+ {
+ "handler": "vars",
+ "root": "/srv"
+ }
+ ]
+ },
+ {
+ "group": "group2",
+ "handle": [
+ {
+ "handler": "subroute",
+ "routes": [
+ {
+ "handle": [
+ {
+ "handler": "file_server",
+ "hide": [
+ "./Caddyfile"
+ ],
+ "status_code": "{env.CUSTOM_STATUS}"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "match": [
+ {
+ "path": [
+ "/custom-status*"
+ ]
+ }
+ ]
+ },
+ {
+ "group": "group2",
+ "handle": [
+ {
+ "handler": "subroute",
+ "routes": [
+ {
+ "handle": [
+ {
+ "handler": "file_server",
+ "hide": [
+ "./Caddyfile"
+ ],
+ "status_code": 403
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "match": [
+ {
+ "path": [
+ "/nope*"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "terminal": true
+ }
+ ]
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go
index 2ba53f2..447f481 100644
--- a/modules/caddyhttp/fileserver/caddyfile.go
+++ b/modules/caddyhttp/fileserver/caddyfile.go
@@ -40,6 +40,7 @@ func init() {
// index <files...>
// browse [<template_file>]
// precompressed <formats...>
+// status <status>
// }
//
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
@@ -65,21 +66,25 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
if len(fsrv.Hide) == 0 {
return nil, h.ArgErr()
}
+
case "index":
fsrv.IndexNames = h.RemainingArgs()
if len(fsrv.IndexNames) == 0 {
return nil, h.ArgErr()
}
+
case "root":
if !h.Args(&fsrv.Root) {
return nil, h.ArgErr()
}
+
case "browse":
if fsrv.Browse != nil {
return nil, h.Err("browsing is already configured")
}
fsrv.Browse = new(Browse)
h.Args(&fsrv.Browse.TemplateFile)
+
case "precompressed":
var order []string
for h.NextArg() {
@@ -100,6 +105,13 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
order = append(order, h.Val())
}
fsrv.PrecompressedOrder = order
+
+ case "status":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ fsrv.StatusCode = caddyhttp.WeakString(h.Val())
+
default:
return nil, h.Errf("unknown subdirective '%s'", h.Val())
}
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