Placeholder 佔位符
在 Caddy 中,Placeholder 佔位符會根據個別外掛程式的需求進行處理;它們不會自動在所有地方都運作。
這表示如果您希望您的外掛程式支援 Placeholder 佔位符,您必須明確地新增對它們的支援。
如果您還不熟悉 Placeholder 佔位符,請從這裡開始閱讀!
Placeholder 佔位符概觀
Placeholder 佔位符是以 {foo.bar}
格式呈現的字串,用作動態配置值,並在執行時進行評估。
Caddyfile 環境變數替換(以美元符號開頭,例如 {$FOO}
)在 Caddyfile 解析時進行評估,並且不需要由您的外掛程式處理。 這些並非 Placeholder 佔位符,儘管它們共用相同的 { }
語法。
因此,務必理解 {env.HOST}
(全域 Placeholder 佔位符)與 {$HOST}
(Caddyfile 環境變數替換)在本質上是不同的。
例如,請參閱以下 Caddyfile:
:8080 {
respond {$HOST} 200
}
:8081 {
respond {env.HOST} 200
}
當您使用 HOST=example caddy adapt
將此 Caddyfile 轉換為 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
}
]
}
]
}
}
}
}
}
特別注意 srv0
和 srv1
中的 "body"
欄位。
由於 srv0
使用了 {$HOST}
(Caddyfile 環境變數替換),因此該值變成了 example
,因為它在產生 JSON 配置時已在 Caddyfile 解析期間被處理。
由於 srv1
使用了 {env.HOST}
(全域 Placeholder 佔位符),因此在轉換為 JSON 時它保持不變。
這確實意味著撰寫 JSON 配置(不使用 Caddyfile)的使用者無法使用 {$ENV}
語法。 因此,對於外掛程式作者來說,實作 Placeholder 佔位符替換支援非常重要,尤其是在配置被佈建時。 這將在下面解釋。
實作 Placeholder 佔位符支援
您不應在 UnmarshalCaddyfile()
中處理 Placeholder 佔位符。 相反地,Placeholder 佔位符應稍後替換,無論是在 Provision()
步驟中,還是在模組執行期間(例如,HTTP 處理器的 ServeHTTP()
,匹配器的 Match()
等),使用 caddy.Replacer
。
範例
在這裡,我們使用新建立的替換器來處理 Placeholder 佔位符。 它有權存取全域 Placeholder 佔位符,例如 {env.HOST}
,但沒有 HTTP Placeholder 佔位符,例如 {http.request.uri}
,因為佈建發生在配置載入時,而不是在請求期間。
func (g *Gizmo) Provision(ctx caddy.Context) error {
repl := caddy.NewReplacer()
g.Name = repl.ReplaceAll(g.Name,"")
return nil
}
在這裡,我們在 ServeHTTP
期間從請求內容 r.Context()
中獲取替換器。 此替換器有權存取全域 Placeholder 佔位符和每個請求的 HTTP Placeholder 佔位符,例如 {http.request.uri}
。
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)
}