在开发Caddy插件的时候,很多现成的配置可以为我们所用,这样我们插件中的某些配置就可以遵循整个Caddyfile的全局统一配置,用户体验会更好,比如使用统一的debug来控制自己开发插件的日志输出等等。
什么是全局配置
Caddyfile的全局配置和整个Caddy有关,并不局限于某个指令、请求等。在Caddy中有一些配置使用了默认的配置,但是Caddy同时也提供了全局的配置,可以让我们修改某些配置的默认值。
比如在Caddyfile中,debug默认是关闭的,我们可以通过全局配置来启用它。
在整个Caddyfile的最顶部,使用一个单独的 {}
块,这个块就是自定义全局配置的地方,比如以上示例代码,我们开启了 debug
模式,这将会把所有的日志级别都设置为 debug
。
还有一个我们曾经用过的 order
其实也是一个全局配置,用它来自定义指令的顺序:
1
2
3
4
|
{
order hello_world last
debug
}
|
Caddyfile提供的全局配置有很多, order
、 debug
只是其中的两个,比如还有 http_port
用来设置http的端口,默认是80。
这里给出所有的配置列表:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
{
# General Options
debug
http_port <port>
https_port <port>
order <dir1> first|last|[before|after <dir2>]
storage <module_name> {
<options...>
}
storage_clean_interval <duration>
admin off|<addr> {
origins <origins...>
enforce_origin
}
log [name] {
output <writer_module> ...
format <encoder_module> ...
level <level>
include <namespaces...>
exclude <namespaces...>
}
grace_period <duration>
# TLS Options
auto_https off|disable_redirects|ignore_loaded_certs
email <yours>
default_sni <name>
local_certs
skip_install_trust
acme_ca <directory_url>
acme_ca_root <pem_file>
acme_eab <key_id> <mac_key>
acme_dns <provider> ...
on_demand_tls {
ask <endpoint>
interval <duration>
burst <n>
}
key_type ed25519|p256|p384|rsa2048|rsa4096
cert_issuer <name> ...
ocsp_stapling off
preferred_chains [smallest] {
root_common_name <common_names...>
any_common_name <common_names...>
}
# Server Options
servers [<listener_address>] {
listener_wrappers {
<listener_wrappers...>
}
timeouts {
read_body <duration>
read_header <duration>
write <duration>
idle <duration>
}
max_header_size <size>
protocol {
allow_h2c
experimental_http3
strict_sni_host
}
}
}
|
以上就是Caddyfile内置支持的全局配置,关于他们的说明可以从字面意思上推测出来,当然你也可以查看这个 https://caddyserver.com/docs/caddyfile/options 文档,了解更详细的说明 。
使用全局配置
以上这些全局配置,我们也可以在我们自己定义的插件中使用的,现在我就为你讲解如何使用他们,下面就以 debug
这个配置为例。
1
2
3
4
|
type HelloWorld struct {
Text string `json:"text,omitempty"`
Debug bool `json:"debug,omitempty"`
}
|
首先增加一个 Debug
字段用于存储是否需要Debug。
这个字段并不是我们控制,而是要用过全局配置来控制,需要我们需要读取全局配置中 debug
的值,用于控制是否需要Debug。
1
2
3
4
5
6
7
8
|
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
hw := new(HelloWorld)
if debug, ok := h.Option("debug").(bool); ok {
hw.Debug = debug
}
err := hw.UnmarshalCaddyfile(h.Dispenser)
return hw, err
}
|
在解析Caddyfile文件的时候,通过 h.Option
方法即可获取指定全局配置的值,这里我们获取的是 debug
,然后赋予 HelloWorld
的 Debug
字段。
好了,现在我们的插件也可以通过全局配置 debug
开关Debug模式了。
自定义全局配置
除了可以使用Caddy自带的全局配置外,我们还可以自定义自己的全局配置,Caddy的这种能力为我们提供了更强大的扩展性。
下面我还以这个debug模式为例,使用我们自定义的全局配置,看如何实现。需要注意的是这个纯属演示自定义全局配置的能力,实践中还是要使用内置的debug这个全局配置。
要先自定义自己的全局配置,首先我们需要注册它:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
func init() {
caddy.RegisterModule(&HelloWorld{})
httpcaddyfile.RegisterGlobalOption("hello_debug", parseOptHelloDebug)
httpcaddyfile.RegisterHandlerDirective("hello_world", parseCaddyfile)
}
func parseOptHelloDebug(d *caddyfile.Dispenser, _ interface{}) (interface{}, error) {
var debug int
for d.Next() {
var debugStr string
if !d.AllArgs(&debugStr) {
return 0, d.ArgErr()
}
var err error
debug, err = strconv.Atoi(debugStr)
if err != nil {
return 0, d.Errf("converting port '%s' to integer value: %v", debugStr, err)
}
}
return debug, nil
}
|
是的,就在我们的 init
方法中,使用函数 httpcaddyfile.RegisterGlobalOption
就可以新增一个自定义的全局配置。
parseOptHelloDebug
用来解析出Caddyfile全局配置中 hello_debug
的值,这里为了演示,我定义的hello_debug
的值是 int
类型, 1
表示开启debug模式, 0
表示不开启。
现在解析Caddyfile得到 hello_debug
的值,就可以在刚刚 parseCaddyfile
函数中使用它了,我们稍微修改下即可:
1
2
3
4
5
6
7
8
|
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
hw := new(HelloWorld)
if debug, ok := h.Option("hello_debug").(int); ok {
hw.Debug = debug == 1
}
err := hw.UnmarshalCaddyfile(h.Dispenser)
return hw, err
}
|
只需要把原来的 bool
断言换成 int
断言,并且值为 1
才被认为是开启Debug模式。
小结
现在,你已经拿到了 Debug
的值,你可以在你插件的任何地方使用它,来打印你想打印的日志,一般我们会这样:
1
2
3
|
if (h.Debug){
// 日志输出
}
|
Caddy 提供的全局配置以及可以自定义的能力,为Caddy的能力扩展以及插件开发都提供了很好的扩展,我们可以利用这个能力,大大丰富自己插件的可自定义化行为。
但是最终我想提醒的是,如果Caddy已经定义了你需要的全局配置,那么最好和他们保持一致。
本文为原创文章,转载注明出处,欢迎扫码关注公众号flysnow_org
或者网站 https://www.flysnow.org/ ,第一时间看后续精彩文章。觉得好的话,请猛击文章右下角「在看」,感谢支持。