Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 01:00 UTC
| 1 | package httpcaddyfile |
| 2 | |
| 3 | import ( |
| 4 | "regexp" |
| 5 | "strings" |
| 6 | |
| 7 | "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" |
| 8 | ) |
| 9 | |
| 10 | type ComplexShorthandReplacer struct { |
| 11 | search *regexp.Regexp |
| 12 | replace string |
| 13 | } |
| 14 | |
| 15 | type ShorthandReplacer struct { |
| 16 | complex []ComplexShorthandReplacer |
| 17 | simple *strings.Replacer |
| 18 | } |
| 19 | |
| 20 | func NewShorthandReplacer() ShorthandReplacer { |
| 21 | // replace shorthand placeholders (which are convenient |
| 22 | // when writing a Caddyfile) with their actual placeholder |
| 23 | // identifiers or variable names |
| 24 | replacer := strings.NewReplacer(placeholderShorthands()...) |
| 25 | |
| 26 | // these are placeholders that allow a user-defined final |
| 27 | // parameters, but we still want to provide a shorthand |
| 28 | // for those, so we use a regexp to replace |
| 29 | regexpReplacements := []ComplexShorthandReplacer{ |
| 30 | {regexp.MustCompile(`{header\.([\w-]*)}`), "{http.request.header.$1}"}, |
| 31 | {regexp.MustCompile(`{cookie\.([\w-]*)}`), "{http.request.cookie.$1}"}, |
| 32 | {regexp.MustCompile(`{labels\.([\w-]*)}`), "{http.request.host.labels.$1}"}, |
| 33 | {regexp.MustCompile(`{path\.([\w-]*)}`), "{http.request.uri.path.$1}"}, |
| 34 | {regexp.MustCompile(`{file\.([\w-]*)}`), "{http.request.uri.path.file.$1}"}, |
| 35 | {regexp.MustCompile(`{query\.([\w-]*)}`), "{http.request.uri.query.$1}"}, |
| 36 | {regexp.MustCompile(`{re\.([\w-\.]*)}`), "{http.regexp.$1}"}, |
| 37 | {regexp.MustCompile(`{vars\.([\w-]*)}`), "{http.vars.$1}"}, |
| 38 | {regexp.MustCompile(`{rp\.([\w-\.]*)}`), "{http.reverse_proxy.$1}"}, |
| 39 | {regexp.MustCompile(`{resp\.([\w-\.]*)}`), "{http.intercept.$1}"}, |
| 40 | {regexp.MustCompile(`{err\.([\w-\.]*)}`), "{http.error.$1}"}, |
| 41 | {regexp.MustCompile(`{file_match\.([\w-]*)}`), "{http.matchers.file.$1}"}, |
| 42 | } |
| 43 | |
| 44 | return ShorthandReplacer{ |
| 45 | complex: regexpReplacements, |
| 46 | simple: replacer, |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // placeholderShorthands returns a slice of old-new string pairs, |
| 51 | // where the left of the pair is a placeholder shorthand that may |
| 52 | // be used in the Caddyfile, and the right is the replacement. |
| 53 | func placeholderShorthands() []string { |
| 54 | return []string{ |
| 55 | "{host}", "{http.request.host}", |
| 56 | "{hostport}", "{http.request.hostport}", |
| 57 | "{port}", "{http.request.port}", |
| 58 | "{orig_method}", "{http.request.orig_method}", |
| 59 | "{orig_uri}", "{http.request.orig_uri}", |
| 60 | "{orig_path}", "{http.request.orig_uri.path}", |
| 61 | "{orig_dir}", "{http.request.orig_uri.path.dir}", |
| 62 | "{orig_file}", "{http.request.orig_uri.path.file}", |
| 63 | "{orig_query}", "{http.request.orig_uri.query}", |
| 64 | "{orig_?query}", "{http.request.orig_uri.prefixed_query}", |
| 65 | "{method}", "{http.request.method}", |
| 66 | "{uri}", "{http.request.uri}", |
| 67 | "{%uri}", "{http.request.uri_escaped}", |
| 68 | "{path}", "{http.request.uri.path}", |
| 69 | "{%path}", "{http.request.uri.path_escaped}", |
| 70 | "{dir}", "{http.request.uri.path.dir}", |
| 71 | "{file}", "{http.request.uri.path.file}", |
| 72 | "{query}", "{http.request.uri.query}", |
| 73 | "{%query}", "{http.request.uri.query_escaped}", |
| 74 | "{?query}", "{http.request.uri.prefixed_query}", |
| 75 | "{remote}", "{http.request.remote}", |
| 76 | "{remote_host}", "{http.request.remote.host}", |
| 77 | "{remote_port}", "{http.request.remote.port}", |
| 78 | "{scheme}", "{http.request.scheme}", |
| 79 | "{uuid}", "{http.request.uuid}", |
| 80 | "{tls_cipher}", "{http.request.tls.cipher_suite}", |
| 81 | "{tls_version}", "{http.request.tls.version}", |
| 82 | "{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}", |
| 83 | "{tls_client_issuer}", "{http.request.tls.client.issuer}", |
| 84 | "{tls_client_serial}", "{http.request.tls.client.serial}", |
| 85 | "{tls_client_subject}", "{http.request.tls.client.subject}", |
| 86 | "{tls_client_certificate_pem}", "{http.request.tls.client.certificate_pem}", |
| 87 | "{tls_client_certificate_der_base64}", "{http.request.tls.client.certificate_der_base64}", |
| 88 | "{upstream_hostport}", "{http.reverse_proxy.upstream.hostport}", |
| 89 | "{client_ip}", "{http.vars.client_ip}", |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | // ApplyToSegment replaces shorthand placeholder to its full placeholder, understandable by Caddy. |
| 94 | func (s ShorthandReplacer) ApplyToSegment(segment *caddyfile.Segment) { |
| 95 | if segment != nil { |
| 96 | for i := 0; i < len(*segment); i++ { |
| 97 | // simple string replacements |
| 98 | (*segment)[i].Text = s.simple.Replace((*segment)[i].Text) |
| 99 | // complex regexp replacements |
| 100 | for _, r := range s.complex { |
| 101 | (*segment)[i].Text = r.search.ReplaceAllString((*segment)[i].Text, r.replace) |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | } |