From a458544d9f6e6aaf72aeab0454acfa482880d3d6 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 16 Oct 2019 15:18:02 -0600 Subject: [PATCH] Minor enhancements/fixes to rewrite directive and template virt req's --- README.md | 11 +++++++---- modules/caddyhttp/rewrite/caddyfile.go | 3 +++ modules/caddyhttp/templates/tplcontext.go | 20 +++++++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7aaf57ed6..84b79e822 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Please file issues to propose new features and report bugs, and after the bug or Requirements: - [Go 1.13 or newer](https://golang.org/dl/) -- Make sure you do not disable [Go modules](https://github.com/golang/go/wiki/Modules) (`export GO111MODULE=auto`) +- Do NOT disable [Go modules](https://github.com/golang/go/wiki/Modules) (`export GO111MODULE=auto`) Download the `v2` source code: @@ -120,10 +120,10 @@ Caddy 2 can be configured with a Caddyfile, much like in v1, for example: ```plain example.com -templates -encode gzip zstd try_files {path}.html {path} -reverse_proxy /api localhost:9005 +encode gzip zstd +reverse_proxy /api localhost:9005 +php_fastcgi /blog unix//path/to/socket file_server ``` @@ -199,6 +199,7 @@ The following is a non-comprehensive list of significant improvements over Caddy - TLS Session Ticket Ephemeral Keys (STEKs) can be rotated in a cluster for increased performance (no other web server does this either!) - Ability to select a specific certificate per ClientHello given multiple qualifying certificates - Provide TLS certificates without persisting them to disk; keep private keys entirely in memory + - Certificate management at startup is now asynchronous and much easier to use through machine reboots and in unsupervised settings - All-new HTTP server core - Listeners can be configured for any network type, address, and port range - Customizable TLS connection policies @@ -218,6 +219,8 @@ The following is a non-comprehensive list of significant improvements over Caddy - Done away with URL-rewriting hacks often needed in Caddy 1 - Highly descriptive/traceable errors - Very flexible error handling, with the ability to specify a whole list of routes just for error cases + - The proxy has numerous improvements, including dynamic backends and more configurable health checks + - FastCGI support integrated with the reverse proxy - More control over automatic HTTPS: disable entirely, disable only HTTP->HTTPS redirects, disable only cert management, and for certain names, etc. - Use Starlark to build custom, dynamic HTTP handlers at request-time - We are finding that -- on average -- Caddy 2's Starlark handlers are ~1.25-2x faster than NGINX+Lua. diff --git a/modules/caddyhttp/rewrite/caddyfile.go b/modules/caddyhttp/rewrite/caddyfile.go index cb65d434d..a1fc87400 100644 --- a/modules/caddyhttp/rewrite/caddyfile.go +++ b/modules/caddyhttp/rewrite/caddyfile.go @@ -31,6 +31,9 @@ func init() { func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { var rewr Rewrite for h.Next() { + if !h.NextArg() { + return nil, h.ArgErr() + } rewr.URI = h.Val() if h.NextArg() { return nil, h.ArgErr() diff --git a/modules/caddyhttp/templates/tplcontext.go b/modules/caddyhttp/templates/tplcontext.go index 40d137079..e3909b242 100644 --- a/modules/caddyhttp/templates/tplcontext.go +++ b/modules/caddyhttp/templates/tplcontext.go @@ -22,6 +22,7 @@ import ( "net" "net/http" "path" + "strconv" "strings" "sync" @@ -79,8 +80,18 @@ func (c templateContext) Include(filename string, args ...interface{}) (template // are NOT escaped, so you should only include trusted resources. // If it is not trusted, be sure to use escaping functions yourself. func (c templateContext) HTTPInclude(uri string) (template.HTML, error) { - if c.Req.Header.Get(recursionPreventionHeader) == "1" { - return "", fmt.Errorf("virtual request cycle") + // prevent virtual request loops by counting how many levels + // deep we are; and if we get too deep, return an error + recursionCount := 1 + if numStr := c.Req.Header.Get(recursionPreventionHeader); numStr != "" { + num, err := strconv.Atoi(numStr) + if err != nil { + return "", fmt.Errorf("parsing %s: %v", recursionPreventionHeader, err) + } + if num >= 3 { + return "", fmt.Errorf("virtual request cycle") + } + recursionCount = num + 1 } buf := bufPool.Get().(*bytes.Buffer) @@ -91,7 +102,10 @@ func (c templateContext) HTTPInclude(uri string) (template.HTML, error) { if err != nil { return "", err } - virtReq.Header.Set(recursionPreventionHeader, "1") + virtReq.Host = c.Req.Host + virtReq.Header = c.Req.Header.Clone() + virtReq.Trailer = c.Req.Trailer.Clone() + virtReq.Header.Set(recursionPreventionHeader, strconv.Itoa(recursionCount)) vrw := &virtualResponseWriter{body: buf, header: make(http.Header)} server := c.Req.Context().Value(caddyhttp.ServerCtxKey).(http.Handler)