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
Improve docs, especially w.r.t. placeholders and template actions
Matthew Holt committed
Dec 29, 2019 at 13:16 UTC
fdabac51a8c8801840679a24e371f23013b021bb
8 files changed
+265
-63
caddy.go
+4
-1
@@ -506,7 +506,7 @@ func goModule(mod *debug.Module) *debug.Module {
506
// TODO: track related Go issue: https://github.com/golang/go/issues/29228
507
// once that issue is fixed, we should just be able to use bi.Main... hopefully.
508
for _, dep := range bi.Deps {
509
- if dep.Path == "github.com/caddyserver/caddy/v2" {
509
+ if dep.Path == ImportPath {
510
return dep
511
}
512
}
@@ -543,3 +543,6 @@ var (
543
// path, for converting /id/ paths to /config/ paths.
544
rawCfgIndex map[string]string
545
)
546
+
547
+// ImportPath is the package import path for Caddy core.
548
+const ImportPath = "github.com/caddyserver/caddy/v2"
modules.go
+4
-4
@@ -75,16 +75,16 @@ type ModuleInfo struct {
75
// label is the module name, and the labels before that constitute
76
// the namespace (or scope).
77
//
78
-// Thus, a module ID has the form: <namespace>.<id>
78
+// Thus, a module ID has the form: <namespace>.<name>
79
//
80
// An ID with no dot has the empty namespace, which is appropriate
81
// for app modules (these are "top-level" modules that Caddy core
82
// loads and runs).
83
//
84
-// Module IDs should be lowercase and use underscore (_) instead of
84
+// Module IDs should be lowercase and use underscores (_) instead of
85
// spaces.
86
//
87
-// Example valid names:
87
+// Examples of valid IDs:
88
// - http
89
// - http.handlers.file_server
90
// - caddy.logging.encoders.json
@@ -92,7 +92,7 @@ type ModuleID string
92
93
// Namespace returns the namespace (or scope) portion of a module ID,
94
// which is all but the last label of the ID. If the ID has only one
95
-// label, then
95
+// label, then the namespace is empty.
96
func (id ModuleID) Namespace() string {
97
lastDot := strings.LastIndex(string(id), ".")
98
if lastDot < 0 {
modules/caddyhttp/caddyhttp.go
+41
-1
@@ -44,7 +44,47 @@ func init() {
44
}
45
}
46
47
-// App is a robust, flexible HTTP server for Caddy.
47
+// App is a robust, production-ready HTTP server.
48
+//
49
+// HTTPS is enabled by default if host matchers with qualifying names are used
50
+// in any of routes; certificates are automatically provisioned and renewed.
51
+// Additionally, automatic HTTPS will also enable HTTPS for servers that listen
52
+// only on the HTTPS port but which do not have any TLS connection policies
53
+// defined by adding a good, default TLS connection policy.
54
+//
55
+// In HTTP routes, additional placeholders are available:
56
+//
57
+// Placeholder | Description
58
+// ------------|---------------
59
+// `{http.request.cookie.*}` | HTTP request cookie
60
+// `{http.request.header.*}` | Specific request header field
61
+// `{http.request.host.labels.*}` | Request host labels (0-based from right); e.g. for foo.example.com: 0=com, 1=example, 2=foo
62
+// `{http.request.host}` | The host part of the request's Host header
63
+// `{http.request.hostport}` | The host and port from the request's Host header
64
+// `{http.request.method}` | The request method
65
+// `{http.request.orig.method}` | The request's original method
66
+// `{http.request.orig.path.dir}` | The request's original directory
67
+// `{http.request.orig.path.file}` | The request's original filename
68
+// `{http.request.orig.uri.path}` | The request's original path
69
+// `{http.request.orig.uri.query_string}` | The request's original full query string (with `?`)
70
+// `{http.request.orig.uri.query}` | The request's original query string (without `?`)
71
+// `{http.request.orig.uri}` | The request's original URI
72
+// `{http.request.port}` | The port part of the request's Host header
73
+// `{http.request.proto}` | The protocol of the request
74
+// `{http.request.remote.host}` | The host part of the remote client's address
75
+// `{http.request.remote.port}` | The port part of the remote client's address
76
+// `{http.request.remote}` | The address of the remote client
77
+// `{http.request.scheme}` | The request scheme
78
+// `{http.request.uri.path.*}` | Parts of the path, split by `/` (0-based from left)
79
+// `{http.request.uri.path.dir}` | The directory, excluding leaf filename
80
+// `{http.request.uri.path.file}` | The filename of the path, excluding directory
81
+// `{http.request.uri.path}` | The path component of the request URI
82
+// `{http.request.uri.query_string}` | The full query string (with `?`)
83
+// `{http.request.uri.query.*}` | Individual query string value
84
+// `{http.request.uri.query}` | The query string (without `?`)
85
+// `{http.request.uri}` | The full request URI
86
+// `{http.response.header.*}` | Specific response header field
87
+// `{http.vars.*}` | Custom variables in the HTTP handler chain
88
type App struct {
89
// HTTPPort specifies the port to use for HTTP (as opposed to HTTPS),
90
// which is used when setting up HTTP->HTTPS redirects or ACME HTTP
modules/caddyhttp/fileserver/matcher.go
+11
-1
@@ -33,10 +33,20 @@ func init() {
33
34
// MatchFile is an HTTP request matcher that can match
35
// requests based upon file existence.
36
+//
37
+// Upon matching, two new placeholders will be made
38
+// available:
39
+//
40
+// - `{http.matchers.file.relative}` The root-relative
41
+// path of the file. This is often useful when rewriting
42
+// requests.
43
+// - `{http.matchers.file.absolute}` The absolute path
44
+// of the matched file.
45
type MatchFile struct {
46
// The root directory, used for creating absolute
47
// file paths, and required when working with
39
- // relative paths; if not specified, the current
48
+ // relative paths; if not specified, `{http.vars.root}`
49
+ // will be used, if set; otherwise, the current
50
// directory is assumed. Accepts placeholders.
51
Root string `json:"root,omitempty"`
52
modules/caddyhttp/matchers.go
+40
-5
@@ -40,6 +40,12 @@ type (
40
MatchPath []string
41
42
// MatchPathRE matches requests by a regular expression on the URI's path.
43
+ //
44
+ // Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}`
45
+ // where `name` is the regular expression's name, and `capture_group` is either
46
+ // the named or positional capture group from the expression itself. If no name
47
+ // is given, then the placeholder omits the name: `{http.regexp.capture_group}`
48
+ // (potentially leading to collisions).
49
MatchPathRE struct{ MatchRegexp }
50
51
// MatchMethod matches requests by the method.
@@ -52,6 +58,12 @@ type (
58
MatchHeader http.Header
59
60
// MatchHeaderRE matches requests by a regular expression on header fields.
61
+ //
62
+ // Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}`
63
+ // where `name` is the regular expression's name, and `capture_group` is either
64
+ // the named or positional capture group from the expression itself. If no name
65
+ // is given, then the placeholder omits the name: `{http.regexp.capture_group}`
66
+ // (potentially leading to collisions).
67
MatchHeaderRE map[string]*MatchRegexp
68
69
// MatchProtocol matches requests by protocol.
@@ -65,6 +77,8 @@ type (
77
}
78
79
// MatchNegate matches requests by negating its matchers' results.
80
+ // To use, simply specify a set of matchers like you normally would;
81
+ // the only difference is that their result will be negated.
82
MatchNegate struct {
83
MatchersRaw caddy.ModuleMap `json:"-" caddy:"namespace=http.matchers"`
84
@@ -624,11 +638,26 @@ func (m MatchStarlarkExpr) Match(r *http.Request) bool {
638
}
639
640
// MatchRegexp is an embeddable type for matching
627
-// using regular expressions.
641
+// using regular expressions. It adds placeholders
642
+// to the request's replacer.
643
type MatchRegexp struct {
629
- Name string `json:"name,omitempty"`
630
- Pattern string `json:"pattern"`
644
+ // A unique name for this regular expression. Optional,
645
+ // but useful to prevent overwriting captures from other
646
+ // regexp matchers.
647
+ Name string `json:"name,omitempty"`
648
+
649
+ // The regular expression to evaluate, in RE2 syntax,
650
+ // which is the same general syntax used by Go, Perl,
651
+ // and Python. For details, see
652
+ // [Go's regexp package](https://golang.org/pkg/regexp/).
653
+ // Captures are accessible via placeholders. Unnamed
654
+ // capture groups are exposed as their numeric, 1-based
655
+ // index, while named capture groups are available by
656
+ // the capture group name.
657
+ Pattern string `json:"pattern"`
658
+
659
compiled *regexp.Regexp
660
+ phPrefix string
661
}
662
663
// Provision compiles the regular expression.
@@ -638,6 +667,10 @@ func (mre *MatchRegexp) Provision(caddy.Context) error {
667
return fmt.Errorf("compiling matcher regexp %s: %v", mre.Pattern, err)
668
}
669
mre.compiled = re
670
+ mre.phPrefix = regexpPlaceholderPrefix
671
+ if mre.Name != "" {
672
+ mre.phPrefix += "." + mre.Name
673
+ }
674
return nil
675
}
676
@@ -661,14 +694,14 @@ func (mre *MatchRegexp) Match(input string, repl *caddy.Replacer) bool {
694
695
// save all capture groups, first by index
696
for i, match := range matches {
664
- key := fmt.Sprintf("http.regexp.%s.%d", mre.Name, i)
697
+ key := fmt.Sprintf("%s.%d", mre.phPrefix, i)
698
repl.Set(key, match)
699
}
700
701
// then by name
702
for i, name := range mre.compiled.SubexpNames() {
703
if i != 0 && name != "" {
671
- key := fmt.Sprintf("http.regexp.%s.%s", mre.Name, name)
704
+ key := fmt.Sprintf("%s.%s", mre.phPrefix, name)
705
repl.Set(key, matches[i])
706
}
707
}
@@ -752,6 +785,8 @@ func (rm ResponseMatcher) matchHeaders(hdr http.Header) bool {
785
786
var wordRE = regexp.MustCompile(`\w+`)
787
788
+const regexpPlaceholderPrefix = "http.regexp"
789
+
790
// Interface guards
791
var (
792
_ RequestMatcher = (*MatchHost)(nil)
modules/caddyhttp/reverseproxy/reverseproxy.go
+10
-15
@@ -41,24 +41,19 @@ func init() {
41
}
42
43
// Handler implements a highly configurable and production-ready reverse proxy.
44
+//
45
// Upon proxying, this module sets the following placeholders (which can be used
46
// both within and after this handler):
47
//
47
-// {http.reverse_proxy.upstream.address}
48
-// The full address to the upstream as given in the config
49
-// {http.reverse_proxy.upstream.hostport}
50
-// The host:port of the upstream
51
-// {http.reverse_proxy.upstream.host}
52
-// The host of the upstream
53
-// {http.reverse_proxy.upstream.port}
54
-// The port of the upstream
55
-// {http.reverse_proxy.upstream.requests}
56
-// The approximate current number of requests to the upstream
57
-// {http.reverse_proxy.upstream.max_requests}
58
-// The maximum approximate number of requests allowed to the upstream
59
-// {http.reverse_proxy.upstream.fails}
60
-// The number of recent failed requests to the upstream
61
-//
48
+// Placeholder | Description
49
+// ------------|-------------
50
+// `{http.reverse_proxy.upstream.address}` | The full address to the upstream as given in the config
51
+// `{http.reverse_proxy.upstream.hostport}` | The host:port of the upstream
52
+// `{http.reverse_proxy.upstream.host}` | The host of the upstream
53
+// `{http.reverse_proxy.upstream.port}` | The port of the upstream
54
+// `{http.reverse_proxy.upstream.requests}` | The approximate current number of requests to the upstream
55
+// `{http.reverse_proxy.upstream.max_requests}` | The maximum approximate number of requests allowed to the upstream
56
+// `{http.reverse_proxy.upstream.fails}` | The number of recent failed requests to the upstream
57
type Handler struct {
58
// Configures the method of transport for the proxy. A transport
59
// is what performs the actual "round trip" to the backend.
modules/caddyhttp/server.go
+8
-35
@@ -33,39 +33,9 @@ import (
33
34
// Server describes an HTTP server.
35
type Server struct {
36
- // Socket interfaces to which to bind listeners. Caddy network
37
- // addresses have the following form:
38
- //
39
- // network/address
40
- //
41
- // The network part is anything that [Go's `net` package](https://golang.org/pkg/net/)
42
- // recognizes, and is optional. The default network is `tcp`. If
43
- // a network is specified, a single forward slash `/` is used to
44
- // separate the network and address portions.
45
- //
46
- // The address part may be any of these forms:
47
- //
48
- // - `host`
49
- // - `host:port`
50
- // - `:port`
51
- // - `/path/to/unix/socket`
52
- //
53
- // The host may be any hostname, resolvable domain name, or IP address.
54
- // The port may be a single value (`:8080`) or a range (`:8080-8085`).
55
- // A port range will be multiplied into singular addresses. Not all
56
- // config parameters accept port ranges, but Listen does.
57
- //
58
- // Valid examples:
59
- //
60
- // :8080
61
- // 127.0.0.1:8080
62
- // localhost:8080
63
- // localhost:8080-8085
64
- // tcp/localhost:8080
65
- // tcp/localhost:8080-8085
66
- // udp/localhost:9005
67
- // unix//path/to/socket
68
- //
36
+ // Socket addresses to which to bind listeners. Accepts
37
+ // [network addresses](/docs/conventions#network-addresses)
38
+ // that may include port ranges.
39
Listen []string `json:"listen,omitempty"`
40
41
// How long to allow a read from a client's upload. Setting this
@@ -105,12 +75,15 @@ type Server struct {
75
// The error routes work exactly like the normal routes.
76
Errors *HTTPErrorConfig `json:"errors,omitempty"`
77
108
- // How to handle TLS connections.
78
+ // How to handle TLS connections. At least one policy is
79
+ // required to enable HTTPS on this server if automatic
80
+ // HTTPS is disabled or does not apply.
81
TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies,omitempty"`
82
83
// AutoHTTPS configures or disables automatic HTTPS within this server.
84
// HTTPS is enabled automatically and by default when qualifying names
113
- // are present in a Host matcher.
85
+ // are present in a Host matcher and/or when the server is listening
86
+ // only on the HTTPS port.
87
AutoHTTPS *AutoHTTPSConfig `json:"automatic_https,omitempty"`
88
89
// MaxRehandles is the maximum number of times to allow a
modules/caddyhttp/templates/templates.go
+147
-1
@@ -29,7 +29,153 @@ func init() {
29
caddy.RegisterModule(Templates{})
30
}
31
32
-// Templates is a middleware which execute response bodies as templates.
32
+// Templates is a middleware which executes response bodies as Go templates.
33
+// The syntax is documented in the Go standard library's
34
+// [text/template package](https://golang.org/pkg/text/template/).
35
+//
36
+// [All Sprig functions](https://masterminds.github.io/sprig/) are supported.
37
+//
38
+// In addition to the standard functions and Sprig functions, Caddy adds
39
+// extra functions and data that are available to a template:
40
+//
41
+// ##### **`.Args`**
42
+//
43
+// Access arguments passed to this page/context, for example as the result of a `include`.
44
+//
45
+// ```
46
+// {{.Args 0}} // first argument
47
+// ```
48
+//
49
+// ##### `.Cookie`
50
+//
51
+// Gets the value of a cookie by name.
52
+//
53
+// ```
54
+// {{.Cookie "cookiename"}}
55
+// ```
56
+//
57
+// ##### `.Host`
58
+//
59
+// Returns the hostname portion (no port) of the Host header of the HTTP request.
60
+//
61
+// ```
62
+// {{.Host}}
63
+// ```
64
+//
65
+// ##### `httpInclude`
66
+//
67
+// Includes the contents of another file by making a virtual HTTP request (also known as a sub-request). The URI path must exist on the same virtual server because the request does not use sockets; instead, the request is crafted in memory and the handler is invoked directly for increased efficiency.
68
+//
69
+// ```
70
+// {{httpInclude "/foo/bar?q=val"}}
71
+// ```
72
+//
73
+// ##### `include`
74
+//
75
+// Includes the contents of another file. Optionally can pass key-value pairs as arguments to be accessed by the included file.
76
+//
77
+// ```
78
+// {{include "path/to/file.html"}} // no arguments
79
+// {{include "path/to/file.html" "arg1" 2 "value 3"}} // with arguments
80
+// ```
81
+//
82
+// ##### `listFiles`
83
+//
84
+// Returns a list of the files in the given directory, which is relative to the template context's file root.
85
+//
86
+// ```
87
+// {{listFiles "/mydir"}}
88
+// ```
89
+//
90
+// ##### `markdown`
91
+//
92
+// Renders the given Markdown text as HTML.
93
+//
94
+// ```
95
+// {{markdown "My _markdown_ text"}}
96
+// ```
97
+//
98
+// ##### `.RemoteIP`
99
+//
100
+// Returns the client's IP address.
101
+//
102
+// ```
103
+// {{.RemoteIP}}
104
+// ```
105
+//
106
+// ##### `.RespHeader.Add`
107
+//
108
+// Adds a header field to the HTTP response.
109
+//
110
+// ```
111
+// {{.RespHeader.Add "Field-Name" "val"}}
112
+// ```
113
+//
114
+// ##### `.RespHeader.Del`
115
+//
116
+// Deletes a header field on the HTTP response.
117
+//
118
+// ```
119
+// {{.RespHeader.Del "Field-Name"}}
120
+// ```
121
+//
122
+// ##### `.RespHeader.Set`
123
+//
124
+// Sets a header field on the HTTP response, replacing any existing value.
125
+//
126
+// ```
127
+// {{.RespHeader.Set "Field-Name" "val"}}
128
+// ```
129
+//
130
+// ##### `splitFrontMatter`
131
+//
132
+// Splits front matter out from the body. Front matter is metadata that appears at the very beginning of a file or string. Front matter can be in YAML, TOML, or JSON formats:
133
+//
134
+// **TOML** front matter starts and ends with `+++`:
135
+//
136
+// ```
137
+// +++
138
+// template = "blog"
139
+// title = "Blog Homepage"
140
+// sitename = "A Caddy site"
141
+// +++
142
+// ```
143
+//
144
+// **YAML** is surrounded by `---`:
145
+//
146
+// ```
147
+// ---
148
+// template: blog
149
+// title: Blog Homepage
150
+// sitename: A Caddy site
151
+// ---
152
+// ```
153
+//
154
+//
155
+// **JSON** is simply `{` and `}`:
156
+//
157
+// ```
158
+// {
159
+// "template": "blog",
160
+// "title": "Blog Homepage",
161
+// "sitename": "A Caddy site"
162
+// }
163
+// ```
164
+//
165
+// The resulting front matter will be made available like so:
166
+//
167
+// - `.Meta` to access the metadata fields, for example: `{{$parsed.Meta.title}}`
168
+// - `.Body` to access the body after the front matter, for example: `{{markdown $parsed.Body}}`
169
+//
170
+//
171
+// ##### `stripHTML`
172
+//
173
+// Removes HTML from a string.
174
+//
175
+// ```
176
+// {{stripHTML "Shows <b>only</b> text content"}}
177
+// ```
178
+//
179
type Templates struct {
180
// The root path from which to load files. Required if template functions
181
// accessing the file system are used (such as include). Default is