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
fileserver: Better handling of HTTP status override (#4132)
Francis Lavoie committed
Apr 29, 2021 at 02:01 UTC
3a1e81dbf6587d2e886529d55e7a02eabeaa7c47
1 file changed
+30
-16
modules/caddyhttp/fileserver/staticfiles.go
+30
-16
@@ -18,7 +18,6 @@ import (
18
"bytes"
19
"fmt"
20
"html/template"
21
- "io"
21
weakrand "math/rand"
22
"mime"
23
"net/http"
@@ -333,32 +332,33 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
332
}
333
}
334
336
- // if this handler exists in an error context (i.e. is
337
- // part of a handler chain that is supposed to handle
338
- // a previous error), we have to serve the content
339
- // manually in order to write the correct status code
335
+ var statusCodeOverride int
336
+
337
+ // if this handler exists in an error context (i.e. is part of a
338
+ // handler chain that is supposed to handle a previous error),
339
+ // we should set status code to the one from the error instead
340
+ // of letting http.ServeContent set the default (usually 200)
341
if reqErr, ok := r.Context().Value(caddyhttp.ErrorCtxKey).(error); ok {
341
- statusCode := http.StatusInternalServerError
342
+ statusCodeOverride = http.StatusInternalServerError
343
if handlerErr, ok := reqErr.(caddyhttp.HandlerError); ok {
344
if handlerErr.StatusCode > 0 {
344
- statusCode = handlerErr.StatusCode
345
+ statusCodeOverride = handlerErr.StatusCode
346
}
347
}
347
- w.WriteHeader(statusCode)
348
- if r.Method != http.MethodHead {
349
- _, _ = io.Copy(w, file)
350
- }
351
- return nil
348
}
349
354
- // if a status code override is configured, write the status code
355
- // before serving the file
350
+ // if a status code override is configured, run the replacer on it
351
if codeStr := fsrv.StatusCode.String(); codeStr != "" {
357
- intVal, err := strconv.Atoi(repl.ReplaceAll(codeStr, ""))
352
+ statusCodeOverride, err = strconv.Atoi(repl.ReplaceAll(codeStr, ""))
353
if err != nil {
354
return caddyhttp.Error(http.StatusInternalServerError, err)
355
}
361
- w.WriteHeader(intVal)
356
+ }
357
+
358
+ // if we do have an override from the previous two parts, then
359
+ // we wrap the response writer to intercept the WriteHeader call
360
+ if statusCodeOverride > 0 {
361
+ w = statusOverrideResponseWriter{ResponseWriter: w, code: statusCodeOverride}
362
}
363
364
// let the standard library do what it does best; note, however,
@@ -557,6 +557,20 @@ func redirect(w http.ResponseWriter, r *http.Request, to string) error {
557
return nil
558
}
559
560
+// statusOverrideResponseWriter intercepts WriteHeader calls
561
+// to instead write the HTTP status code we want instead
562
+// of the one http.ServeContent will use by default (usually 200)
563
+type statusOverrideResponseWriter struct {
564
+ http.ResponseWriter
565
+ code int
566
+}
567
+
568
+// WriteHeader intercepts calls by the stdlib to WriteHeader
569
+// to instead write the HTTP status code we want.
570
+func (wr statusOverrideResponseWriter) WriteHeader(int) {
571
+ wr.ResponseWriter.WriteHeader(wr.code)
572
+}
573
+
574
var defaultIndexNames = []string{"index.html", "index.txt"}
575
576
var bufPool = sync.Pool{