@marcel91200 / caddy Mirror · read-only / commits / 3a1e81db
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

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{