summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--context.go2
-rw-r--r--modules/caddyhttp/caddyhttp.go2
-rw-r--r--modules/caddyhttp/replacer.go45
-rw-r--r--modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go1
-rw-r--r--modules/caddyhttp/reverseproxy/reverseproxy.go2
-rw-r--r--modules/caddyhttp/routes.go3
-rw-r--r--replacer.go7
-rw-r--r--storage.go3
8 files changed, 56 insertions, 9 deletions
diff --git a/context.go b/context.go
index c29aa1d..d196c71 100644
--- a/context.go
+++ b/context.go
@@ -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"
diff --git a/storage.go b/storage.go
index b325b7b..670a471 100644
--- a/storage.go
+++ b/storage.go
@@ -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