From a63cb3e3fdea70991a95c3f0bc8f3866a5aec6ef Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 27 Jun 2019 13:09:10 -0600 Subject: Implement etag; fix related bugs in encode and templates middlewares --- modules/caddyhttp/templates/templates.go | 33 ++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'modules/caddyhttp/templates') diff --git a/modules/caddyhttp/templates/templates.go b/modules/caddyhttp/templates/templates.go index e329e2e..79bbde6 100644 --- a/modules/caddyhttp/templates/templates.go +++ b/modules/caddyhttp/templates/templates.go @@ -22,9 +22,18 @@ func init() { // Templates is a middleware which execute response bodies as templates. type Templates struct { FileRoot string `json:"file_root,omitempty"` + MIMETypes []string `json:"mime_types,omitempty"` Delimiters []string `json:"delimiters,omitempty"` } +// Provision provisions t. +func (t *Templates) Provision(ctx caddy.Context) error { + if t.MIMETypes == nil { + t.MIMETypes = defaultMIMETypes + } + return nil +} + // Validate ensures t has a valid configuration. func (t *Templates) Validate() error { if len(t.Delimiters) != 0 && len(t.Delimiters) != 2 { @@ -38,8 +47,16 @@ func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy buf.Reset() defer bufPool.Put(buf) + // shouldBuf determines whether to execute templates on this response, + // since generally we will not want to execute for images or CSS, etc. shouldBuf := func(status int) bool { - return strings.HasPrefix(w.Header().Get("Content-Type"), "text/") + ct := w.Header().Get("Content-Type") + for _, mt := range t.MIMETypes { + if strings.Contains(ct, mt) { + return true + } + } + return false } rec := caddyhttp.NewResponseRecorder(w, buf, shouldBuf) @@ -59,9 +76,14 @@ func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy w.Header().Set("Content-Length", strconv.Itoa(buf.Len())) w.Header().Del("Accept-Ranges") // we don't know ranges for dynamically-created content - w.Header().Del("Etag") // don't know a way to quickly generate etag for dynamic content w.Header().Del("Last-Modified") // useless for dynamic content since it's always changing + // we don't know a way to guickly generate etag for dynamic content, + // but we can convert this to a weak etag to kind of indicate that + if etag := w.Header().Get("ETag"); etag != "" { + w.Header().Set("ETag", "W/"+etag) + } + w.WriteHeader(rec.Status()) io.Copy(w, buf) @@ -110,8 +132,15 @@ func (vrw *virtualResponseWriter) Write(data []byte) (int, error) { return vrw.body.Write(data) } +var defaultMIMETypes = []string{ + "text/html", + "text/plain", + "text/markdown", +} + // Interface guards var ( + _ caddy.Provisioner = (*Templates)(nil) _ caddy.Validator = (*Templates)(nil) _ caddyhttp.MiddlewareHandler = (*Templates)(nil) ) -- cgit v1.2.3