Caddy 實戰(十一)- Caddyfile 設計之美
Caddyfile 是 Caddy 的核心配置文件,它的設計,關乎着我們使用,開發者的解析以及擴展,所以本篇着重的介紹 Caddy 是如何設計一個 Caddyfile 的,我們也可以從中學到如何設計一個配置文件,並且讓它更好的通用,更好的解析。
其實設計如此複雜的一個配置文件,已經和設計一門編程語言,很接近了。
結構
我前面的系統文章中,你也看到了如何使用 Caddyfile 的指令等功能,來滿足我們的需求的。在我們寫 Caddyfile 的時候,是遵循一定的規範的,哪些地方要怎麼寫,誰可以包含誰,這些規範就構成了 Caddyfile 的結構。
這張圖是瞭解 Caddyfile 的神器,它定了 Caddy 的規範以及結構,讓我們可以很方面的使用 Caddyfile。現在,我來介紹下里面的一些關鍵點:
看到最頂部的紅色框圈出來的這部分了嗎?這是一個全局配置,它在 Caddyfile 的最頂部,用於配置一些通用的全局信息。當然它並不是必須的,你也可以不用配置它。
第二部分的 snippet
是一個可以複用的片段,你可以在其他地方通過 import
來引入它,這非常適用於你的 Caddyfile 中有很多重複配置的情況。它和全局配置的差別在於 {
前面有一對小括號,用於定義可複用片段的名字,這樣你纔可以在其他地方通過這個名字引用。下面我通過一個例子來說明它的使用,如下所示:
(static_file){
root * /var/www/mysite
file_server
}
www.example.com{
import static_file
}
www.example.com{
import static_file
}
接下來就是 Site Block
了,也就是定義你的站點的塊,在 Apache 中叫虛擬主機。寫到這裏你可以看到,Caddyfile 只有這三個頂級的定義塊,一個全局配置、一個可複用的片段、一個就是站點配置,其他所有的配置,都要放在這三個頂級的配置中。
你可以通過站點塊定義多個站點,但是他們之間沒什麼關係。如果你只有一個站點,你可以省略站點後面的大括號, 比如下面兩種定義是等價的:
localhost
reverse_proxy /api/* localhost:9001
file_server
等價於:
localhost {
reverse_proxy /api/* localhost:9001
file_server
}
因爲整個 Caddyfile 中只有這麼一個站點,所以大括號是可選的。
塊
... {
...
}
example1.com {
root * /www/example.com
file_server
}
example2.com {
reverse_proxy localhost:9000
}
指令
localhost
reverse_proxy localhost:9000 localhost:9001 {
lb_policy first
}
Caddyfile 解析
directive abc def
以上可能會返回異常,或者其他不可預知的行爲。如果 abc def
是一個單獨參數的話,最安全的做法就是使用引號,這樣 Caddy 的詞法分析器,就不會把他們當成兩個標記 (Token)。
directive "abc def"
directive "\"abc def\""
這裏還有一個辦法,就是使用反引號:
directive `"foo bar"`
效果是等價的,反引號尤其是包含引號的文本中使用非常方便,比如 JSON 字符串等。
地址
地址就是站點塊的頂部那部分,通常也是 Caddyfile 的第一個內容。Caddy 基本上支持所有的地址樣式,如下常用示例:
-
localhost
-
example.com
-
:443
-
http://example.com
-
localhost:8080
-
127.0.0.1
-
example.com/foo/*
-
*.example.com
-
http://
根據地址,Caddy 可以推斷出站點的 Scheme、Host、Port 和 Path。
如果指定主機名,則只接受具有匹配主機頭的請求。換句話說,如果站點地址是 localhost
,那麼 Caddy 將不會將請求與 127.0.0.1
匹配,因爲 127.0.0.1
的請求主機頭不是localhost
, 沒法匹配。
Caddy 允許在地址中使用通配符 (*), 但是它也有嚴格的限制:它只用來匹配主機名。比如 *.example.com
可以匹配 foo.example.com
,但不匹配 foo.bar.example.com
。
你也可以讓多個站點地址共享同一個定義,只需要使用逗號分隔這些地址即可。
localhost:8080, example.com, www.example.com
最後,地址必須唯一,不能多次指定同一個地址。
請求匹配
一個客戶端請求過來,Caddy 是怎麼處理的呢?比如用哪個指令來處理,這就需要設置匹配器了,通過匹配器,你可以精確的設置某個指令用於哪些請求。
如果不設置,默認情況下,該指令適用於所有請求。
指令後的第一個參數是匹配器,比如:
root * /var/www # matcher token: *
root /index.html /var/www # matcher token: /index.html
root @post /var/www # matcher token: @post
*
表示匹配所有,這裏的 @post
是一個定義的匹配器,可以被引用、複用。匹配器的定義,詳見我們結構那部分的截圖。
以上示例其實代表了三種匹配器:通配符匹配器、路徑匹配器和命名匹配器,更多的關於請求匹配器的說明可以詳見 https://caddyserver.com/docs/caddyfile/matchers ,這裏不再贅述。
佔位符
使用 Nginx 的時候,我們會看到有 $
開頭的變量,它就是佔位符,是一種將動態值注入靜態配置的方法,通過它可以讓我們更靈活的配置 Nginx。同樣的,Caddy 也有佔位符的功能,便於我們配置 Caddyfile。
在 Caddyfile 中,佔位符的兩邊用大括號 {} 限定,並在其中包含變量名,例如: {foo.bar}
。佔位符大括號可以轉義, \{like so\}
。變量名通常用點命名,以避免模塊之間的衝突。
你可以在 Caddyfile 中使用任何 Caddy 佔位符,但爲了方便起見,您也可以使用一些等效的速記佔位符:
並非所有佔位符在配置的所有部分都可用,哪些佔位符可用取決於上下文。例如,HTTP 應用程序設置的佔位符僅在與處理 HTTP 請求相關的配置區域中可用。
片段
在結構部分我簡單的介紹過片段,它是一個可以複用的配置,使用 import
導入實現複用。
(redirect) {
@http {
protocol http
}
redir @http https://{host}{uri}
}
片段是頂級配置,片段定義的開頭是片段的名稱,使用小括號 ()
括起來。定義好一個片段後,就可以通過 import
使用給它了。
import redirect
除了複用之外,片段的另一個強大之處在於可以傳參給片段,實現動態化配置。
(snippet) {
respond "Yahaha! You found {args.0}!"
}
a.example.com {
import snippet "Example A"
}
b.example.com {
import snippet "Example B"
}
使用非常簡單,通過 {args.0}
可以獲得傳遞過來的第一個參數。
環境變量
在 Caddyfile,你也可以使用環境變量,這樣可以讓你的配置更靈活。
使用環境變量也非常簡單,和佔位符差不多,也是一個大括號包裹,但是多一個 $
符號。
{$SITE_ADDRESS}
這種形式的環境變量在解析開始之前被替換,因此它們可以擴展爲空值、部分標記、完整標記,甚至多個標記和行。和 C 語言的 define
一樣,是不是很強大。
在具體的代碼實現上,Caddy 是使用 Go 語言的 os.LookupEnv
方法獲取環境變量的。
那麼,如果忘記配置環境變量怎麼辦呢?別急,這點 Caddy 肯定考慮到了,我們在使用環境變量的時候,可以設置一個默認值,如果找不到環境變量的時候,會使用這個默認值。
{$DOMAIN:localhost}
Caddyfile 是使用 :
來分隔環境變量名稱和默認值的,以上示例中,默認值是 localhost
。
註釋
Caddyfile 是支持註釋的,這樣我們就可以增加點註釋,便於多人協作和理解。在 Caddyfile 中,註釋以 #
開頭,直到行的末尾。
# Comments can start a line
directive # or go at the end
小結
這篇主要介紹了 Caddyfile 的規範以及設計,這也是一個比較完整的配置文件的設計,看了這篇相信你不光可以很好的理解 Caddyfile 並使用它,也可以很好的理解 Nginx 的 conf 配置,因爲都差不多。
一個配置文件的設計,牽涉到規範、可以擴展性、模塊化、可複用、變量,還得需要加載、替換、詞法分析等,這儼然已經是在定義一門腳本言語了,所以如果你有編譯器的功底,也能更好的理解 Caddyfile 的設計和解析。
本文爲原創文章,轉載註明出處, 歡迎掃碼關注公衆號
flysnow_org
或者網站 https://www.flysnow.org/ ,第一時間看後續精彩文章。覺得好的話,請猛擊文章右下角「在看」,感謝支持。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/3pNMzRdxIcURZ7jBg8EwYQ