Caddyfileのサポート
Caddyモジュールは、登録されると、名前空間によってネイティブJSON設定に自動的に追加され、使用可能かつドキュメント化されます。 これにより、Caddyfileのサポートは完全にオプションとなりますが、Caddyfileを好むユーザーからよく要求されます。
Unmarshaler
モジュールにCaddyfileのサポートを追加するには、caddyfile.Unmarshaler
インターフェースを実装するだけです。 トークンの解析方法によって、モジュールのCaddyfile構文を選択できます。
アンマーシャラーの仕事は、渡されたcaddyfile.Dispenser
を使用して、モジュールの型のフィールドを設定するなど、モジュールの型を設定することです。 たとえば、Gizmo
という名前のモジュール型には、次のメソッドがあります。
// UnmarshalCaddyfile implements caddyfile.Unmarshaler. Syntax:
//
// gizmo <name> [<option>]
//
func (g *Gizmo) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
d.Next() // consume directive name
if !d.Args(&g.Name) {
// not enough args
return d.ArgErr()
}
if d.NextArg() {
// optional arg
g.Option = d.Val()
}
if d.NextArg() {
// too many args
return d.ArgErr()
}
return nil
}
godocコメントに構文を記述することをお勧めします。 Caddyfileの解析の詳細については、caddyfile
パッケージのgodocを参照してください。
ディレクティブ名トークンは、単純なd.Next()
呼び出しで消費/スキップできます。
d.NextArg()
またはd.RemainingArgs()
を使用して、欠落または過剰な引数がないか確認してください。 単純な「無効なケース」メッセージにはd.ArgErr()
を使用し、問題の説明(および理想的には、推奨される解決策)を含む有用なエラーメッセージを作成するには、d.Errf("some message")
を使用します。
また、インターフェースが正しく満たされていることを確認するために、インターフェースガードを追加する必要があります
var _ caddyfile.Unmarshaler = (*Gizmo)(nil)
ブロック
1行に収まらない設定を受け入れるには、サブディレクティブを持つブロックを許可することをお勧めします。 これは、d.NextBlock()
を使用して、元のネストレベルに戻るまで反復処理することで実行できます。
for nesting := d.Nesting(); d.NextBlock(nesting); {
switch d.Val() {
case "sub_directive_1":
// ...
case "sub_directive_2":
// ...
}
}
ループの各反復がセグメント全体(行またはブロック)を消費する限り、これはブロックを処理する洗練された方法です。
HTTPディレクティブ
HTTP Caddyfileは、CaddyのデフォルトのCaddyfileアダプター構文(または「サーバタイプ」)です。 拡張可能であるため、モジュール用に独自の「トップレベル」ディレクティブを登録できます。
func init() {
httpcaddyfile.RegisterDirective("gizmo", parseCaddyfile)
}
ディレクティブが単一のHTTPハンドラーのみを返す場合(よくあることですが)、RegisterHandlerDirective
の方が簡単です。
func init() {
httpcaddyfile.RegisterHandlerDirective("gizmo", parseCaddyfileHandler)
}
基本的な考え方は、ディレクティブに関連付ける解析関数が、1つ以上のConfigValue
値を返すということです。 (または、RegisterHandlerDirective
を使用する場合は、設定されたcaddyhttp.MiddlewareHandler
値を直接返します。) 各設定値は「クラス」に関連付けられており、HTTP Caddyfileアダプターが最終的なJSON設定のどの部分で使用できるかを知るのに役立ちます。 すべての設定値は、アダプターが最終的なJSON設定を構築するときにそこから引き出す山にダンプされます。
この設計により、ディレクティブは認識されているクラスの任意の設定値を返すことができます。つまり、HTTP Caddyfileアダプターが指定されたクラスを持つ設定の任意の部分に影響を与えることができます。
UnmarshalCaddyfile()
メソッドをすでに実装している場合、解析関数は次のように簡単です。
// parseCaddyfileHandler unmarshals tokens from h into a new middleware handler value.
func parseCaddyfileHandler(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
var g Gizmo
err := g.UnmarshalCaddyfile(h.Dispenser)
return g, err
}
httpcaddyfile.Helper
タイプの使用方法の詳細については、httpcaddyfile
パッケージのgodocを参照してください。
ハンドラーの順序
HTTPミドルウェア/ハンドラー値を返すすべてのディレクティブは、正しい順序で評価する必要があります。 たとえば、サイトのルートディレクトリを設定するハンドラーは、ルートディレクトリにアクセスするハンドラーの前に来る必要があります。そうすれば、ディレクトリパスがわかります。
HTTP Caddyfileには、標準ディレクティブのハードコードされた順序があります。 これにより、ユーザーはWebサーバーの最も一般的な機能の実装の詳細を知る必要がなくなり、正しい構成を簡単に記述できるようになります。 単一のハードコードされたリストは、Caddyfileの拡張可能な性質を考慮しても、非決定性を防ぎます。
新しいハンドラーディレクティブを登録する場合、(route
ブロックの外側で)使用するには、そのリストに追加する必要があります。 これは、次の2つの方法のいずれかを使用して設定で行われます。
order
グローバルオプションは、その設定の標準順序のみを変更します。 たとえば、order mydir before respond
は、新しいディレクティブmydir
を挿入して、respond
ハンドラーの前に評価します。 その後、ディレクティブは通常どおり使用できます。- または、
route
ブロックでディレクティブを使用します。 ルートブロック内のディレクティブは並べ替えられないため、ルートブロックで使用されるディレクティブはリストに表示される必要はありません。
ユーザーがディレクティブを正しく使用できるように、リストのどこにディレクティブを配置するのが適切かをユーザーに説明してください.
クラス
この表は、HTTP Caddyfileアダプターによって認識される、エクスポートされた型を持つ各クラスについて説明しています。
クラス名 | 予想される型 | 説明 |
---|---|---|
bind | []string |
サーバーリスナーのバインドアドレス |
route | caddyhttp.Route |
HTTPハンドラールート |
error_route | *caddyhttp.Subroute |
HTTPエラー処理ルート |
tls.connection_policy | *caddytls.ConnectionPolicy |
TLS接続ポリシー |
tls.cert_issuer | certmagic.Issuer |
TLS証明書発行者 |
tls.cert_loader | caddytls.CertificateLoader |
TLS証明書ローダー |
サーバータイプ
構造的には、Caddyfileは単純な形式であるため、ニーズに合わせてさまざまなタイプのCaddyfile形式(「サーバタイプ」と呼ばれることもあります)を使用できます。
デフォルトのCaddyfile形式はHTTP Caddyfileであり、おそらくおなじみでしょう。 この形式は、主にhttp
アプリを設定しますが、Caddy設定構造の他の部分(たとえば、証明書を読み込んで自動化するtls
アプリ)に設定を散在させる可能性があります。
HTTP以外のアプリを設定するには、独自のサーバタイプを使用する独自の設定アダプターを実装することをお勧めします。 Caddyfileアダプターは実際に入力を解析して、サーバーブロックとオプションのリストを提供します。その構造を理解してJSON設定に変換するのはアダプター次第です。