Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
httpcaddyfile: Shorthands for parameterized placeholders (#3305)
* httpcaddyfile: Add shorthands for parameterized placeholders httpcaddyfile: Now with regexp instead httpcaddyfile: Allow dashes, gofmt httpcaddyfile: Compile regexp only once httpcaddyfile: Cleanup struct httpcaddyfile: Optimize the replacers, pull out of the loop httpcaddyfile: Add `{port}` shorthand * httpcaddyfile: Switch `r.` to `re.`
Francis Lavoie committed
May 11, 2020 at 18:50 UTC
ea7e4b4024f34fd53f8b8f7b5effb353b36cf8e8
2 files changed
+92
-24
caddyconfig/httpcaddyfile/httptype.go
+46
-24
@@ -18,6 +18,7 @@ import (
18
"encoding/json"
19
"fmt"
20
"reflect"
21
+ "regexp"
22
"sort"
23
"strconv"
24
"strings"
@@ -71,34 +72,55 @@ func (st ServerType) Setup(inputServerBlocks []caddyfile.ServerBlock,
72
return nil, warnings, err
73
}
74
75
+ // replace shorthand placeholders (which are
76
+ // convenient when writing a Caddyfile) with
77
+ // their actual placeholder identifiers or
78
+ // variable names
79
+ replacer := strings.NewReplacer(
80
+ "{dir}", "{http.request.uri.path.dir}",
81
+ "{file}", "{http.request.uri.path.file}",
82
+ "{host}", "{http.request.host}",
83
+ "{hostport}", "{http.request.hostport}",
84
+ "{port}", "{http.request.port}",
85
+ "{method}", "{http.request.method}",
86
+ "{path}", "{http.request.uri.path}",
87
+ "{query}", "{http.request.uri.query}",
88
+ "{remote}", "{http.request.remote}",
89
+ "{remote_host}", "{http.request.remote.host}",
90
+ "{remote_port}", "{http.request.remote.port}",
91
+ "{scheme}", "{http.request.scheme}",
92
+ "{uri}", "{http.request.uri}",
93
+ "{tls_cipher}", "{http.request.tls.cipher_suite}",
94
+ "{tls_version}", "{http.request.tls.version}",
95
+ "{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
96
+ "{tls_client_issuer}", "{http.request.tls.client.issuer}",
97
+ "{tls_client_serial}", "{http.request.tls.client.serial}",
98
+ "{tls_client_subject}", "{http.request.tls.client.subject}",
99
+ )
100
+
101
+ // these are placeholders that allow a user-defined final
102
+ // parameters, but we still want to provide a shorthand
103
+ // for those, so we use a regexp to replace
104
+ regexpReplacements := []struct {
105
+ search *regexp.Regexp
106
+ replace string
107
+ }{
108
+ {regexp.MustCompile(`{query\.([\w-]*)}`), "{http.request.uri.query.$1}"},
109
+ {regexp.MustCompile(`{labels\.([\w-]*)}`), "{http.request.host.labels.$1}"},
110
+ {regexp.MustCompile(`{header\.([\w-]*)}`), "{http.request.header.$1}"},
111
+ {regexp.MustCompile(`{path\.([\w-]*)}`), "{http.request.uri.path.$1}"},
112
+ {regexp.MustCompile(`{re\.([\w-]*)\.([\w-]*)}`), "{http.regexp.$1.$2}"},
113
+ }
114
+
115
for _, sb := range originalServerBlocks {
75
- // replace shorthand placeholders (which are
76
- // convenient when writing a Caddyfile) with
77
- // their actual placeholder identifiers or
78
- // variable names
79
- replacer := strings.NewReplacer(
80
- "{dir}", "{http.request.uri.path.dir}",
81
- "{file}", "{http.request.uri.path.file}",
82
- "{host}", "{http.request.host}",
83
- "{hostport}", "{http.request.hostport}",
84
- "{method}", "{http.request.method}",
85
- "{path}", "{http.request.uri.path}",
86
- "{query}", "{http.request.uri.query}",
87
- "{remote}", "{http.request.remote}",
88
- "{remote_host}", "{http.request.remote.host}",
89
- "{remote_port}", "{http.request.remote.port}",
90
- "{scheme}", "{http.request.scheme}",
91
- "{uri}", "{http.request.uri}",
92
- "{tls_cipher}", "{http.request.tls.cipher_suite}",
93
- "{tls_version}", "{http.request.tls.version}",
94
- "{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
95
- "{tls_client_issuer}", "{http.request.tls.client.issuer}",
96
- "{tls_client_serial}", "{http.request.tls.client.serial}",
97
- "{tls_client_subject}", "{http.request.tls.client.subject}",
98
- )
116
for _, segment := range sb.block.Segments {
117
for i := 0; i < len(segment); i++ {
118
+ // simple string replacements
119
segment[i].Text = replacer.Replace(segment[i].Text)
120
+ // complex regexp replacements
121
+ for _, r := range regexpReplacements {
122
+ segment[i].Text = r.search.ReplaceAllString(segment[i].Text, r.replace)
123
+ }
124
}
125
}
126
caddytest/integration/caddyfile_adapt_test.go
+46
@@ -539,3 +539,49 @@ func TestLogRollDays(t *testing.T) {
539
}
540
}`)
541
}
542
+
543
+func TestShorthandParameterizedPlaceholders(t *testing.T) {
544
+ caddytest.AssertAdapt(t, `
545
+ localhost:80
546
+ respond * "{header.content-type} {labels.0} {query.p} {path.0} {re.name.0}"
547
+ `, "caddyfile", `{
548
+ "apps": {
549
+ "http": {
550
+ "servers": {
551
+ "srv0": {
552
+ "listen": [
553
+ ":80"
554
+ ],
555
+ "routes": [
556
+ {
557
+ "match": [
558
+ {
559
+ "host": [
560
+ "localhost"
561
+ ]
562
+ }
563
+ ],
564
+ "handle": [
565
+ {
566
+ "handler": "subroute",
567
+ "routes": [
568
+ {
569
+ "handle": [
570
+ {
571
+ "body": "{http.request.header.content-type} {http.request.host.labels.0} {http.request.uri.query.p} {http.request.uri.path.0} {http.regexp.name.0}",
572
+ "handler": "static_response"
573
+ }
574
+ ]
575
+ }
576
+ ]
577
+ }
578
+ ],
579
+ "terminal": true
580
+ }
581
+ ]
582
+ }
583
+ }
584
+ }
585
+ }
586
+}`)
587
+}