Поддержка Caddyfile
Модули Caddy автоматически добавляются в нативный конфиг JSON благодаря своему пространству имен при их регистрации, что делает их как пригодными для использования, так и документированными. Это делает поддержку Caddyfile полностью необязательной, но она часто запрашивается пользователями, предпочитающими Caddyfile.
Unmarshaler
Чтобы добавить поддержку Caddyfile для вашего модуля, просто реализуйте интерфейс caddyfile.Unmarshaler. Вы можете выбрать синтаксис Caddyfile для вашего модуля, определив способ разбора токенов.
Задача unmarshaler — просто настроить тип вашего модуля, например, заполнив его поля, используя 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 для метода. См. godoc для пакета caddyfile для получения дополнительной информации о разборе Caddyfile.
Имя директивы можно потреблять/пропускать с помощью простого вызова d.Next().
Убедитесь, что вы проверяете отсутствие и/или избыток аргументов с помощью d.NextArg() или d.RemainingArgs(). Используйте d.ArgErr() для простого сообщения об "ошибке", или используйте d.Errf("some message") для создания полезного сообщения об ошибке с объяснением проблемы (и, по возможности, с предложенным решением).
Вы также должны добавить интерфейсный контроль, чтобы убедиться в надлежащем удовлетворении интерфейса:
var _ caddyfile.Unmarshaler = (*Gizmo)(nil)
Блоки
Чтобы принять больше конфигурации, чем помещается в одну строку, вы можете разрешить блок с поддирективами. Это можно сделать с помощью d.NextBlock() и итерирования, пока вы не вернётесь к исходному уровню вложенности:
for nesting := d.Nesting(); d.NextBlock(nesting); {
switch d.Val() {
case "sub_directive_1":
// ...
case "sub_directive_2":
// ...
}
}
Пока каждая итерация цикла потребляет весь сегмент (строку или блок), это элегантный способ обработки блоков.
Директивы HTTP
HTTP Caddyfile — это стандартный синтаксис адаптера Caddyfile (или тип "сервера"). Он расширяемый, что означает, что вы можете зарегистрировать собственные "глобальные" директивы для своего модуля:
func init() {
httpcaddyfile.RegisterDirective("gizmo", parseCaddyfile)
}
Если ваша директива возвращает только один HTTP-обработчик (как это часто бывает), вы можете найти RegisterHandlerDirective более удобным:
func init() {
httpcaddyfile.RegisterHandlerDirective("gizmo", parseCaddyfileHandler)
}
Основная идея заключается в том, что функция разбора, которую вы связываете со своей директивой, возвращает одно или несколько 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 godoc пакета для получения дополнительной информации о том, как использовать тип httpcaddyfile.Helper.
Порядок обработчиков
Все директивы, которые возвращают значения HTTP-средств/обработчиков, должны оцениваться в правильном порядке. Например, обработчик, устанавливающий корневой каталог сайта, должен идти перед обработчиком, который обращается к корневому каталогу, чтобы он знал, какой путь к каталогу.
HTTP Caddyfile имеет жёстко заданный порядок для стандартных директив. Это гарантирует, что пользователям не нужно знать детали реализации наиболее распространенных функций своего веб-сервера и упрощает написание правильных конфигураций. Единственный жёстко заданный список также предотвращает недетерминированность, учитывая расширяемый характер Caddyfile.
При регистрации новой директивы обработчика она должна быть добавлена в этот список, прежде чем её можно будет использовать (вне блока route). Это делается одним из трёх способов:
-
(Рекомендуемый) Автор плагина может вызвать
httpcaddyfile.RegisterDirectiveOrderвinit()после регистрации директивы, чтобы вставить директиву в порядок относительно другой стандартной директивы. Таким образом, пользователи могут использовать директиву напрямую в своих сайтах без дополнительной настройки. Например, чтобы вставить вашу директивуgizmoдля оценки после обработчикаheader:httpcaddyfile.RegisterDirectiveOrder("gizmo", httpcaddyfile.After, "header") -
Пользователи могут добавить
orderглобальный параметр для изменения стандартного порядка в своём Caddyfile. Например:order gizmo before respondвставит новую директивуgizmoдля оценки перед обработчиком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.
© 2015-2025 Matthew Holt and The Caddy Authors
Licensed under the Apache License 2.0.
Caddy is a registered trademark of Stack Holdings GmbH.
https://caddyserver.com/docs/extending-caddy/caddyfile