summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/replacer.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-05-14 14:14:05 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-05-14 14:14:05 -0600
commitf9d93ead4ef6e099ba7e00318dce6509b0f1eda4 (patch)
treeb14b418475d25c1aa4d13cb53b5e162054570483 /modules/caddyhttp/replacer.go
parent8ae0d6a509fd1b871457cf742369af04346933a8 (diff)
Rename and export some types, other minor changes
Diffstat (limited to 'modules/caddyhttp/replacer.go')
-rw-r--r--modules/caddyhttp/replacer.go80
1 files changed, 50 insertions, 30 deletions
diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go
index 644cfc1..1fd3428 100644
--- a/modules/caddyhttp/replacer.go
+++ b/modules/caddyhttp/replacer.go
@@ -5,18 +5,31 @@ import (
"net/http"
"os"
"strings"
+
+ "bitbucket.org/lightcodelabs/caddy2"
)
// Replacer can replace values in strings based
// on a request and/or response writer. The zero
-// Replacer is not valid; it must be initialized
-// within this package.
+// Replacer is not valid; use NewReplacer() to
+// initialize one.
type Replacer struct {
req *http.Request
resp http.ResponseWriter
custom map[string]string
}
+// NewReplacer makes a new Replacer, initializing all necessary
+// fields. The request and response writer are optional, but
+// necessary for most replacements to work.
+func NewReplacer(req *http.Request, rw http.ResponseWriter) *Replacer {
+ return &Replacer{
+ req: req,
+ resp: rw,
+ custom: make(map[string]string),
+ }
+}
+
// Map sets a custom variable mapping to a value.
func (r *Replacer) Map(variable, value string) {
r.custom[variable] = value
@@ -48,51 +61,58 @@ func (r *Replacer) replaceAll(input, empty string, mapping map[string]string) st
func (r *Replacer) defaults() map[string]string {
m := map[string]string{
- "request.host": func() string {
+ "system.hostname": func() string {
+ // OK if there is an error; just return empty string
+ name, _ := os.Hostname()
+ return name
+ }(),
+ }
+
+ if r.req != nil {
+ m["request.host"] = func() string {
host, _, err := net.SplitHostPort(r.req.Host)
if err != nil {
return r.req.Host // OK; there probably was no port
}
return host
- }(),
- "request.hostport": r.req.Host, // may include both host and port
- "request.method": r.req.Method,
- "request.port": func() string {
+ }()
+ m["request.hostport"] = r.req.Host // may include both host and port
+ m["request.method"] = r.req.Method
+ m["request.port"] = func() string {
// if there is no port, there will be an error; in
// that case, port is the empty string anyway
_, port, _ := net.SplitHostPort(r.req.Host)
return port
- }(),
- "request.scheme": func() string {
+ }()
+ m["request.scheme"] = func() string {
if r.req.TLS != nil {
return "https"
}
return "http"
- }(),
- "request.uri": r.req.URL.RequestURI(),
- "system.hostname": func() string {
- // OK if there is an error; just return empty string
- name, _ := os.Hostname()
- return name
- }(),
- }
+ }()
+ m["request.uri"] = r.req.URL.RequestURI()
+ m["request.uri.path"] = r.req.URL.Path
- // TODO: why should header fields, cookies, and query params get special treatment like this?
- // maybe they should be scoped by words like "request.header." just like everything else.
- for field, vals := range r.req.Header {
- m[">"+strings.ToLower(field)] = strings.Join(vals, ",")
- }
- for field, vals := range r.resp.Header() {
- m["<"+strings.ToLower(field)] = strings.Join(vals, ",")
- }
- for _, cookie := range r.req.Cookies() {
- m["~"+cookie.Name] = cookie.Value
- }
- for param, vals := range r.req.URL.Query() {
- m["?"+param] = strings.Join(vals, ",")
+ // TODO: why should header fields, cookies, and query params get special treatment like this?
+ // maybe they should be scoped by words like "request.header." just like everything else.
+ for field, vals := range r.req.Header {
+ m[">"+strings.ToLower(field)] = strings.Join(vals, ",")
+ }
+ for field, vals := range r.resp.Header() {
+ m["<"+strings.ToLower(field)] = strings.Join(vals, ",")
+ }
+ for _, cookie := range r.req.Cookies() {
+ m["~"+cookie.Name] = cookie.Value
+ }
+ for param, vals := range r.req.URL.Query() {
+ m["?"+param] = strings.Join(vals, ",")
+ }
}
return m
}
const phOpen, phClose = "{", "}"
+
+// ReplacerCtxKey is the context key for the request's replacer.
+const ReplacerCtxKey caddy2.CtxKey = "replacer"