@marcel91200 / caddy Mirror · read-only / commits / fdabac51
Fork 0

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