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

Fix deferred header ops

Matthew Holt committed May 20, 2019 at 22:00 UTC b84cb058484e7900d60324da1289d319c77f5447
2 files changed +24 -10
modules/caddyhttp/headers/headers.go
+18 -6
@@ -17,16 +17,16 @@ func init() {
17
18 // Headers is a middleware which can mutate HTTP headers.
19 type Headers struct {
20 - Request HeaderOps
21 - Response RespHeaderOps
20 + Request HeaderOps `json:"request"`
21 + Response RespHeaderOps `json:"response"`
22 }
23
24 // HeaderOps defines some operations to
25 // perform on HTTP headers.
26 type HeaderOps struct {
27 - Add http.Header
28 - Set http.Header
29 - Delete []string
27 + Add http.Header `json:"add"`
28 + Set http.Header `json:"set"`
29 + Delete []string `json:"delete"`
30 }
31
32 // RespHeaderOps is like HeaderOps, but
@@ -67,10 +67,22 @@ func apply(ops HeaderOps, hdr http.Header) {
67 // operations until WriteHeader is called.
68 type responseWriterWrapper struct {
69 *caddyhttp.ResponseWriterWrapper
70 - headerOps HeaderOps
70 + headerOps HeaderOps
71 + wroteHeader bool
72 +}
73 +
74 +func (rww *responseWriterWrapper) Write(d []byte) (int, error) {
75 + if !rww.wroteHeader {
76 + rww.WriteHeader(http.StatusOK)
77 + }
78 + return rww.ResponseWriterWrapper.Write(d)
79 }
80
81 func (rww *responseWriterWrapper) WriteHeader(status int) {
82 + if rww.wroteHeader {
83 + return
84 + }
85 + rww.wroteHeader = true
86 apply(rww.headerOps, rww.ResponseWriterWrapper.Header())
87 rww.ResponseWriterWrapper.WriteHeader(status)
88 }
modules/caddyhttp/staticresp.go
+6 -4
@@ -17,7 +17,7 @@ func init() {
17
18 // Static implements a simple responder for static responses.
19 type Static struct {
20 - StatusCode int `json:"status_code"`
20 + StatusCode int `json:"status_code"` // TODO: should we turn this into a string so that only one field is needed? (string allows replacements)
21 StatusCodeStr string `json:"status_code_str"`
22 Headers http.Header `json:"headers"`
23 Body string `json:"body"`
@@ -30,7 +30,7 @@ func (s Static) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
30 // close the connection after responding
31 r.Close = s.Close
32
33 - // set all headers, with replacements
33 + // set all headers
34 for field, vals := range s.Headers {
35 field = repl.ReplaceAll(field, "")
36 for i := range vals {
@@ -39,7 +39,7 @@ func (s Static) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
39 w.Header()[field] = vals
40 }
41
42 - // write the headers with a status code
42 + // get the status code
43 statusCode := s.StatusCode
44 if statusCode == 0 && s.StatusCodeStr != "" {
45 intVal, err := strconv.Atoi(repl.ReplaceAll(s.StatusCodeStr, ""))
@@ -50,9 +50,11 @@ func (s Static) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
50 if statusCode == 0 {
51 statusCode = http.StatusOK
52 }
53 +
54 + // write headers
55 w.WriteHeader(statusCode)
56
55 - // write the response body, with replacements
57 + // write response body
58 if s.Body != "" {
59 fmt.Fprint(w, repl.ReplaceAll(s.Body, ""))
60 }