diff options
| -rw-r--r-- | context.go | 2 | ||||
| -rw-r--r-- | modules/caddyhttp/caddyhttp.go | 2 | ||||
| -rw-r--r-- | modules/caddyhttp/replacer.go | 45 | ||||
| -rw-r--r-- | modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go | 1 | ||||
| -rw-r--r-- | modules/caddyhttp/reverseproxy/reverseproxy.go | 2 | ||||
| -rw-r--r-- | modules/caddyhttp/routes.go | 3 | ||||
| -rw-r--r-- | replacer.go | 7 | ||||
| -rw-r--r-- | storage.go | 3 | 
8 files changed, 56 insertions, 9 deletions
@@ -30,7 +30,7 @@ import (  // with care and wrapped with derivation functions from the  // standard context package only if you don't need the Caddy  // specific features. These contexts are cancelled when the -// lifetime of the modules loaded from it are over. +// lifetime of the modules loaded from it is over.  //  // Use NewContext() to get a valid value (but most modules will  // not actually need to do this). diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 410b42c..191f803 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -348,7 +348,7 @@ func (app *App) automaticHTTPS() error {  				})  			// manage their certificates -			log.Printf("[INFO] Enabling automatic HTTPS certificates for %v", domainsForCerts) +			log.Printf("[INFO] Enabling automatic TLS certificate management for %v", domainsForCerts)  			err := tlsApp.Manage(domainsForCerts)  			if err != nil {  				return fmt.Errorf("%s: managing certificate for %s: %s", srvName, domains, err) diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go index d4baa3f..205e4ed 100644 --- a/modules/caddyhttp/replacer.go +++ b/modules/caddyhttp/replacer.go @@ -19,6 +19,7 @@ import (  	"net"  	"net/http"  	"net/textproto" +	"net/url"  	"path"  	"strconv"  	"strings" @@ -59,6 +60,15 @@ func addHTTPVarsToReplacer(repl caddy.Replacer, req *http.Request, w http.Respon  			}  			switch key { +			case "http.request.method": +				return req.Method, true +			case "http.request.scheme": +				if req.TLS != nil { +					return "https", true +				} +				return "http", true +			case "http.request.proto": +				return req.Proto, true  			case "http.request.host":  				host, _, err := net.SplitHostPort(req.Host)  				if err != nil { @@ -81,13 +91,8 @@ func addHTTPVarsToReplacer(repl caddy.Replacer, req *http.Request, w http.Respon  			case "http.request.remote.port":  				_, port, _ := net.SplitHostPort(req.RemoteAddr)  				return port, true -			case "http.request.method": -				return req.Method, true -			case "http.request.scheme": -				if req.TLS != nil { -					return "https", true -				} -				return "http", true + +			// current URI, including any internal rewrites  			case "http.request.uri":  				return req.URL.RequestURI(), true  			case "http.request.uri.path": @@ -106,6 +111,32 @@ func addHTTPVarsToReplacer(repl caddy.Replacer, req *http.Request, w http.Respon  					qs = "?" + qs  				}  				return qs, true + +			// original URI, before any internal changes +			case "http.request.orig_uri": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				return u.RequestURI(), true +			case "http.request.orig_uri.path": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				return u.Path, true +			case "http.request.orig_uri.path.file": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				_, file := path.Split(u.Path) +				return file, true +			case "http.request.orig_uri.path.dir": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				dir, _ := path.Split(u.Path) +				return dir, true +			case "http.request.orig_uri.query": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				return u.RawQuery, true +			case "http.request.orig_uri.query_string": +				u, _ := req.Context().Value(OriginalURLCtxKey).(url.URL) +				qs := u.Query().Encode() +				if qs != "" { +					qs = "?" + qs +				} +				return qs, true  			}  			// hostname labels diff --git a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go index 9df6585..eaf1f86 100644 --- a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go +++ b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go @@ -110,6 +110,7 @@ func (t Transport) RoundTrip(r *http.Request) (*http.Response, error) {  	fcgiBackend, err := DialContext(ctx, network, address)  	if err != nil { +		// TODO: wrap in a special error type if the dial failed, so retries can happen if enabled  		return nil, fmt.Errorf("dialing backend: %v", err)  	}  	// fcgiBackend gets closed when response body is closed (see clientCloser) diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index a733d68..45c0690 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -243,6 +243,8 @@ func (h *Handler) Cleanup() error {  		close(h.HealthChecks.Active.stopChan)  	} +	// TODO: Close keepalive connections on reload? https://github.com/caddyserver/caddy/pull/2507/files#diff-70219fd88fe3f36834f474ce6537ed26R762 +  	// remove hosts from our config from the pool  	for _, upstream := range h.Upstreams {  		hosts.Delete(upstream.dialInfo.String()) diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go index 9dca107..550b14e 100644 --- a/modules/caddyhttp/routes.go +++ b/modules/caddyhttp/routes.go @@ -141,6 +141,9 @@ func (routes RouteList) BuildCompositeRoute(req *http.Request) Handler {  func wrapMiddleware(mh MiddlewareHandler) Middleware {  	return func(next HandlerFunc) HandlerFunc {  		return func(w http.ResponseWriter, r *http.Request) error { +			// TODO: We could wait to evaluate matchers here, just eval +			// the next matcher and choose the next route... +  			// TODO: This is where request tracing could be implemented; also  			// see below to trace the responder as well  			// TODO: Trace a diff of the request, would be cool too! see what changed since the last middleware (host, headers, URI...) diff --git a/replacer.go b/replacer.go index d7beeab..420259b 100644 --- a/replacer.go +++ b/replacer.go @@ -19,6 +19,7 @@ import (  	"path/filepath"  	"runtime"  	"strings" +	"time"  )  // Replacer can replace values in strings. @@ -156,11 +157,17 @@ func globalDefaultReplacements(key string) (string, bool) {  		return runtime.GOOS, true  	case "system.arch":  		return runtime.GOARCH, true +	case "time.now.common_log": +		return nowFunc().Format("02/Jan/2006:15:04:05 -0700"), true  	}  	return "", false  } +// nowFunc is a variable so tests can change it +// in order to obtain a deterministic time. +var nowFunc = time.Now +  // ReplacerCtxKey is the context key for a replacer.  const ReplacerCtxKey CtxKey = "replacer" @@ -59,3 +59,6 @@ func dataDir() string {  	}  	return filepath.Join(baseDir, "caddy")  } + +// TODO: Consider using Go 1.13's os.UserConfigDir() (https://golang.org/pkg/os/#UserConfigDir) +// if we are going to store the last-loaded config anywhere  | 
