mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
templates: Properly propagate response status code (fixes #1841)
Benchmarks with wrk showed no noticeable performance impact
This commit is contained in:
parent
22b835b9f4
commit
54c65cb025
2 changed files with 28 additions and 5 deletions
|
@ -195,6 +195,28 @@ func (rb *ResponseBuffer) ReadFrom(src io.Reader) (int64, error) {
|
|||
return rb.Buffer.ReadFrom(src)
|
||||
}
|
||||
|
||||
// StatusCodeWriter returns an http.ResponseWriter that always
|
||||
// writes the status code stored in rb from when a response
|
||||
// was buffered to it.
|
||||
func (rb *ResponseBuffer) StatusCodeWriter(w http.ResponseWriter) http.ResponseWriter {
|
||||
return forcedStatusCodeWriter{w, rb}
|
||||
}
|
||||
|
||||
// forcedStatusCodeWriter is used to force a status code when
|
||||
// writing the header. It uses the status code saved on rb.
|
||||
// This is useful if passing a http.ResponseWriter into
|
||||
// http.ServeContent because ServeContent hard-codes 2xx status
|
||||
// codes. If we buffered the response, we force that status code
|
||||
// instead.
|
||||
type forcedStatusCodeWriter struct {
|
||||
http.ResponseWriter
|
||||
rb *ResponseBuffer
|
||||
}
|
||||
|
||||
func (fscw forcedStatusCodeWriter) WriteHeader(int) {
|
||||
fscw.ResponseWriter.WriteHeader(fscw.rb.status)
|
||||
}
|
||||
|
||||
// respBufPool is used for io.CopyBuffer when ResponseBuffer
|
||||
// is configured to stream a response.
|
||||
var respBufPool = &sync.Pool{
|
||||
|
|
|
@ -40,7 +40,7 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
|||
if reqExt == "" {
|
||||
// request has no extension, so check response Content-Type
|
||||
ct := mime.TypeByExtension(ext)
|
||||
if strings.Contains(header.Get("Content-Type"), ct) {
|
||||
if ct != "" && strings.Contains(header.Get("Content-Type"), ct) {
|
||||
return true
|
||||
}
|
||||
} else if reqExt == ext {
|
||||
|
@ -96,13 +96,14 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
|||
// set the actual content length now that the template was executed
|
||||
w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))
|
||||
|
||||
// get the modification time in preparation to ServeContent
|
||||
// get the modification time in preparation for http.ServeContent
|
||||
modTime, _ := time.Parse(http.TimeFormat, w.Header().Get("Last-Modified"))
|
||||
|
||||
// at last, write the rendered template to the response
|
||||
http.ServeContent(w, r, templateName, modTime, bytes.NewReader(buf.Bytes()))
|
||||
// at last, write the rendered template to the response; make sure to use
|
||||
// use the proper status code, since ServeContent hard-codes 2xx codes...
|
||||
http.ServeContent(rb.StatusCodeWriter(w), r, templateName, modTime, bytes.NewReader(buf.Bytes()))
|
||||
|
||||
return http.StatusOK, nil
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return t.Next.ServeHTTP(w, r)
|
||||
|
|
Loading…
Reference in a new issue