-
-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
develop: Implementing placeholders (#409)
* noot * noot * formatting * links * links * better explained * grammar * grammar * fix ref * more explained * noot * noot * Update src/docs/markdown/extending-caddy/placeholders.md Co-authored-by: Matt Holt <[email protected]> * Update src/docs/markdown/extending-caddy/placeholders.md Co-authored-by: Matt Holt <[email protected]> * Update src/docs/markdown/extending-caddy/placeholders.md Co-authored-by: Matt Holt <[email protected]> * Update src/docs/markdown/extending-caddy/placeholders.md Co-authored-by: Matt Holt <[email protected]> * noot * noot * noot * noot * noot * noot * Update src/docs/markdown/extending-caddy/placeholders.md Co-authored-by: Francis Lavoie <[email protected]> --------- Co-authored-by: Matt Holt <[email protected]> Co-authored-by: Francis Lavoie <[email protected]>
- Loading branch information
1 parent
5ab8f02
commit 335e086
Showing
3 changed files
with
124 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
--- | ||
title: "Placeholder Support" | ||
--- | ||
|
||
# Placeholders | ||
|
||
In Caddy, placeholders are processed by each individual plugin as needed; they do not automatically work everywhere. | ||
|
||
This means that if you wish for your plugin to support placeholders, you must explicitly add support for them. | ||
|
||
If you are not yet familiar with placeholders, start by reading [here](/docs/conventions#placeholders)! | ||
|
||
## Placeholders Overview | ||
|
||
Placeholders are a string in the format `{foo.bar}` used as dynamic configuration values, which is later evaluated at runtime. | ||
|
||
Placeholders-like strings which start with a dollar sign (`{$FOO}`), are evaulated at Caddyfile parse time, and do not need to be dealt with by your plugin. This is because these are not placeholders, but Caddyfile-specific [environmental variable substitution](/docs/caddyfile/concepts#environment-variables), they just happen to share the `{}` syntax. | ||
|
||
It is therefore important to understand that `{env.HOST}` is inherently different from something like `{$HOST}`. | ||
|
||
As an example, see the following Caddyfile: | ||
```caddyfile | ||
:8080 { | ||
respond {$HOST} 200 | ||
} | ||
:8081 { | ||
respond {env.HOST} 200 | ||
} | ||
``` | ||
|
||
When you adapt this Caddyfile with `HOST=example caddy adapt` you will get | ||
```json | ||
{ | ||
"apps": { | ||
"http": { | ||
"servers": { | ||
"srv0": { | ||
"listen": [ | ||
":8080" | ||
], | ||
"routes": [ | ||
{ | ||
"handle": [ | ||
{ | ||
"body": "example", | ||
"handler": "static_response", | ||
"status_code": 200 | ||
} | ||
] | ||
} | ||
] | ||
}, | ||
"srv1": { | ||
"listen": [ | ||
":8081" | ||
], | ||
"routes": [ | ||
{ | ||
"handle": [ | ||
{ | ||
"body": "{env.HOST}", | ||
"handler": "static_response", | ||
"status_code": 200 | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Importantly, look at the `"body"` field in both `srv0` and `srv1`. | ||
|
||
Since `srv0` used `{$HOST}`, the special environmental variable replacement with `$`, the value became `example`, as it was processed during Caddyfile parse time. | ||
|
||
Since `srv1` used `{env.HOST}`, a normal placeholder, it was parsed as its own raw string value, `{env.HOST}` | ||
|
||
Some users may immediately notice that this means it is impossible to use the `{$ENV}` syntax in a JSON config. The solution to this is to process such placeholders at Provision time, which is covered below. | ||
|
||
|
||
## Implementing placeholder support | ||
|
||
You should not process placeholders when ummarshaling your Caddyfile. Instead, unmarshal the placeholders as strings in your configuration and evaluate them during either your module's execution (e.g. `ServeHTTP()` for HTTP handlers, `Match()` for matchers, etc.) or in the `Provision()` step, using a `caddy.Replacer`. | ||
|
||
|
||
### Examples | ||
|
||
In this example, we are using a newly constructed replacer to process placeholders. It has access to [global placeholders](/docs/conventions#placeholders) such as `{env.HOST}`, but NOT request placeholder such as `{http.request.uri}` | ||
|
||
```go | ||
func (g *Gizmo) Provision(ctx caddy.Context) error { | ||
repl := caddy.NewReplacer() | ||
g.Name = repl.ReplaceAll(g.Name,"") | ||
return nil | ||
} | ||
``` | ||
|
||
Here, we extract a replacer out of the `context.Context` inside the `*http.Request`. This replacer not only has access to global placeholders, but also request placeholders such as `{http.request.uri}`. | ||
|
||
```go | ||
func (g *Gizmo) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { | ||
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) | ||
_, err := w.Write([]byte(repl.ReplaceAll(g.Name,""))) | ||
if err != nil { | ||
return err | ||
} | ||
return next.ServeHTTP(w, r) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters