Spec-Zone.ru › Caddy

Матчинг запросов

Матчи запросов могут использоваться для фильтрации (или классификации) запросов по различным критериям.

  • Синтаксис
    • Примеры
    • Матчинг по шаблонам
    • Матчинг по пути
    • Именованные матчи
  • Стандартные матчи
    • client_ip
    • выражение
    • файл
    • заголовок
    • header_regexp
    • хост
    • метод
    • не
    • путь
    • path_regexp
    • протокол
    • запрос
    • удаленный_ip
    • переменные
    • vars_regexp

Синтаксис

В файле Caddy, непосредственно после директивы, может следовать токен матча, который ограничивает область действия директивы. Токен матча может иметь одну из этих форм:

  1. * для соответствия всем запросам (шаблон; по умолчанию).
  2. /path начинается с косой черты для соответствия пути запроса.
  3. @name для указания именованного матча.

Если директива поддерживает матчи, она будет отображаться как [<matcher>] в документации по синтаксису. Токены матча обычно необязательны, обозначаемые как [ ]. Если токен матча опущен, он эквивалентен матчу по шаблону (*).

Примеры

Эта директива применяется к всем HTTP-запросам:

reverse_proxy localhost:9000

И это то же самое (* здесь не нужно):

reverse_proxy * localhost:9000

Но эта директива применяется только к запросам, имеющим путь, начинающийся с /api/:

reverse_proxy /api/* localhost:9000

Чтобы сопоставить что-либо, кроме пути, определите именованный матчер и обратитесь к нему, используя @name:

@postfoo {
	method POST
	path /foo/*
}
reverse_proxy @postfoo localhost:9000

Матчинг по шаблонам

Матчинг по шаблону (или "захват всего") * соответствует всем запросам и необходим только в том случае, если токен матча обязателен. Например, если первый аргумент, который вы хотите передать в директиву, также является путем, он будет выглядеть точно как матчинг по пути! Таким образом, вы можете использовать матчинг по шаблону, чтобы избежать неоднозначности, например:

root * /home/www/mysite

В противном случае этот матчинг используется нечасто. Мы рекомендуем опустить его, если синтаксис этого не требует.

Матчинг по пути

Сопоставление по пути URI является наиболее распространенным способом сопоставления запросов, поэтому матчинг может быть встроенным, как в этом примере:

redir /old.html /new.html

Токены матчинга по пути должны начинаться с косой черты /.

Сопоставление по пути по умолчанию — точное совпадение, а не совпадение по префиксу. Для быстрого совпадения по префиксу необходимо добавить *. Обратите внимание, что /foo* будет соответствовать /foo и /foo/, а также /foobar; возможно, вам нужен /foo/* вместо этого.

Именованные матчи

Все матчи, которые не являются матчингом по пути или по шаблону, должны быть именованными матчами. Это матчинг, определенный вне любой конкретной директивы, и может быть повторно использован.

Определение матча с уникальным именем предоставляет большую гибкость, позволяя объединить любые доступные матчи в набор:

@name {
	...
}

или, если в наборе только один матчинг, вы можете поместить его в одну строку:

@name ...

Затем вы можете использовать матчинг таким образом, указав его в качестве первого аргумента директивы:

directive @name

Например, это проксирует HTTP/1.1 вебсокетные запросы к localhost:6001, а другие запросы — к localhost:8080. Он сопоставляет запросы, имеющие поле заголовка с именем Connection, содержащее Upgrade, и другое поле с именем Upgrade, содержащее ровно websocket:

example.com {
	@websockets {
		header Connection *Upgrade*
		header Upgrade    websocket
	}
	reverse_proxy @websockets localhost:6001
	reverse_proxy localhost:8080
}

Если набор матчей состоит только из одного матча, также работает синтаксис одной строки:

@post method POST
reverse_proxy @post localhost:6001

В качестве специального случая, expression матчинг может быть использован без указания имени, при условии, что за именем матчинга следует один цитируемый аргумент (само выражение CEL):

@not-found `{err.status_code} == 404`

Как и директивы, определения именованных матчей должны находиться внутри блоков сайта, которые их используют.

Определение именованного матча образует набор матчей. Матчи в наборе соединяются операцией И; т.е. все они должны соответствовать. Например, если в наборе есть и header, и path матчи, то оба должны соответствовать.

Несколько матчей одного типа могут быть объединены (например, несколько path матчей в одном наборе) с использованием булевой алгебры (И/ИЛИ), как описано в соответствующих разделах ниже.

Для более сложной логики булевого соответствия рекомендуется использовать expression матчинг для написания выражения CEL, которое поддерживает и &&, или ||, а также скобки ( ).

Стандартные матчи

Полная документация по матчам доступна в документации каждого модуля матча.

Запросы могут быть сопоставлены следующими способами:

client_ip

client_ip <ranges...>
expression client_ip('<ranges...>')

По адресу IP клиента. Принимает точные IP-адреса или диапазоны CIDR. Поддерживаются IPv6-зоны.

Этот матчинг лучше всего использовать при конфигурации глобального параметра trusted_proxies, в противном случае он ведет себя идентично remote_ip матчингу. Только запросы от доверенных прокси будут иметь свой IP-адрес клиента, проанализированный в начале запроса; для недоверенных запросов используется IP-адрес удаленного узла.

В качестве сокращения, private_ranges может использоваться для соответствия всем частным IPv4 и IPv6 диапазонам. Это то же самое, что и указание всех этих диапазонов: 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8 fd00::/8 ::1

Может быть несколько client_ip матчей на именованный матчинг, и их диапазоны будут объединены и соединены операцией ИЛИ.

Пример:

Сопоставление запросов с частных IPv4-адресов:

@private-ipv4 client_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8

Этот матчинг часто используется совместно с not матчингом для инвертирования соответствия. Например, чтобы отменить все подключения с публичных IPv4 и IPv6 адресов (что является обратным всем частным диапазонам):

example.com {
	@denied not client_ip private_ranges
	abort @denied
	respond "Hello, you must be from a private network!"
}

В выражении CEL это будет выглядеть так:

@my-friends `client_ip('12.23.34.45', '23.34.45.56')`

выражение

expression <cel...>

Любое выражение CEL (Common Expression Language), возвращающее true или false.

Плейсхолдеры Caddy (или сокращения Caddyfile) могут использоваться в этих выражениях CEL, так как они предварительно обрабатываются и преобразуются в обычные вызовы функций CEL перед интерпретацией средой CEL.

Большинство других матчей запросов также могут использоваться в выражениях в качестве функций, что обеспечивает большую гибкость для логики булевых операций, чем вне выражений. См. документацию по каждому матчу для поддержки синтаксиса внутри выражений CEL.

Для удобства имя матча может быть опущено при определении именованного матча, состоящего только из выражения CEL. Выражение CEL должно быть цитируемым (рекомендуется использование обратных кавычек или heredoc).

@mutable `{method}.startsWith("P")`

В этом случае подразумевается матчинг CEL.

Примеры:

Сопоставление запросов, методы которых начинаются с P, например, PUT или POST:

@methods expression {method}.startsWith("P")

Сопоставление запросов, где обработчик вернул код ошибки статуса 404, будет использоваться в сочетании с директивой handle_errors:

@404 expression {err.status_code} == 404

Сопоставление запросов, где путь соответствует одному из двух различных регулярных выражений; это возможно только с помощью выражения, потому что path_regexp матчинг обычно может существовать только один раз на именованный матчинг:

@user expression path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')

Или то же самое, опуская имя матчинга и заключая в обратные кавычки, чтобы он был проанализирован как один токен:

@user `path_regexp('^/user/(\w*)') || path_regexp('^/(\w*)')`

Вы можете использовать синтаксис heredoc для написания многострочных выражений CEL:

@api <<CEL	{method} == "GET"
	&& {path}.startsWith("/api/")
CEL
respond @api "Hello, API!"

файл

file {
	root       <path>
	try_files  <files...>
	try_policy first_exist|first_exist_fallback|smallest_size|largest_size|most_recently_modified
	split_path <delims...>
}
file <files...>
expression `file({
	'root': '<path>',
	'try_files': ['<files...>'],
	'try_policy': 'first_exist|first_exist_fallback|smallest_size|largest_size|most_recently_modified',
	'split_path': ['<delims...>']
})`
expression file('<files...>')

По файлам.

  • root определяет каталог, в котором следует искать файлы. По умолчанию используется текущий рабочий каталог или переменная root переменная ({http.vars.root}), если она задана (можно задать через директиву root директива).

  • try_files проверяет файлы в своем списке, которые соответствуют политике try_policy.

    Чтобы сопоставить каталоги, добавьте косному слэшу / к пути. Все пути к файлам относительны к корню сайта корень, и шаблоны glob будут расширены.

    Если try_policy имеет значение first_exist (по умолчанию), то последний элемент в списке может быть числом, начинающимся с = (например, =404), что в качестве запасного варианта сгенерирует ошибку с этим кодом; ошибку можно перехватить и обработать с помощью handle_errors.

  • try_policy определяет способ выбора файла. По умолчанию используется first_exist.

    • first_exist проверяет существование файла. Выбирается первый существующий файл.

    • first_exist_fallback похож на first_exist, но предполагает, что последний элемент в списке всегда существует, чтобы предотвратить доступ к диску.

    • smallest_size выбирает файл с наименьшим размером.

    • largest_size выбирает файл с наибольшим размером.

    • most_recently_modified выбирает файл, который был изменен последним.

  • split_path разделит путь по первому разделителю в списке, который встречается в каждом пути к файлу для проверки. Для каждого разделителя левая часть разделителя, включая сам разделитель, будет путём к файлу, который проверяется. Например, /remote.php/dav/ с разделителем .php попытается найти файл /remote.php. Каждый разделитель должен появляться в конце компонента пути URI, чтобы использоваться в качестве разделителя. Это узкоспециализированная настройка, и она в основном используется при обслуживании PHP-сайтов.

Так как try_files с политикой first_exist очень часто используется, для этого существует сокращённая запись:

file <files...>

Пустой file-матчер (без файлов в списке) проверит, существует ли запрашиваемый файл — дословно из URI, относительно корня сайта корень сайта. Это фактически эквивалентно file {path}.

Поскольку перенаправление на основе существования файла на диске очень распространено, существует также директива try_files директива, которая является сокращенной записью для file-матчера и обработчика rewrite обработчик.

После сопоставления будут доступны четыре новых плейсхолдера:

  • {file_match.relative} Путь к файлу, относительный к корню. Это часто полезно при перенаправлении запросов.
  • {file_match.absolute} Абсолютный путь к сопоставленному файлу, включая корень.
  • {file_match.type} Тип файла, file или directory.
  • {file_match.remainder} Часть, оставшаяся после разделения пути к файлу (если split_path настроено)

Примеры:

Сопоставление запросов, где путь — это существующий файл:

@file file

Сопоставление запросов, где путь, за которым следует .html, является существующим файлом, или, если нет, где путь — это существующий файл:

@html file {
	try_files {path}.html {path} 
}

То же самое, что и выше, но с использованием сокращённой записи и с возвращением ошибки 404, если файл не найден:

@html-or-error file {path}.html {path} =404

Ещё несколько примеров с использованием выражений CEL. Имейте в виду, что плейсхолдеры предварительно обрабатываются и преобразуются в обычные вызовы функций CEL перед интерпретацией окружением CEL, поэтому здесь используется конкатенация. Кроме того, необходимо использовать полную форму, если нужно конкатенировать с плейсхолдерами из-за текущих ограничений парсинга:

@file `file()`
@first `file({'try_files': [{path}, {path} + '/', 'index.html']})`
@smallest `file({'try_policy': 'smallest_size', 'try_files': ['a.txt', 'b.txt']})`

header

header <field> [<value> ...]
expression header({'<field>': '<value>'})

По полям заголовка запроса.

  • <field> — имя поля HTTP-заголовка для проверки.
    • Если префикс !, поле не должно существовать для сопоставления (аргумент value не требуется).
  • <value> — значение поля, которое должно совпадать для сопоставления. Можно указать одно или несколько значений.
    • Если префикс *, выполняется быстрое соответствие по суффиксу (появление в конце).
    • Если суффикс *, выполняется быстрое соответствие по префиксу (появление в начале).
    • Если заключено в *, выполняется быстрое соответствие по подстроке (появление где-либо).
    • В противном случае выполняется быстрое точное соответствие.

Разные поля заголовков в одном наборе соединены оператором И. Несколько значений одного поля соединены оператором ИЛИ.

Обратите внимание, что поля заголовков могут быть повторяющимися и иметь разные значения. Прикладные программы на стороне сервера ОБЯЗАНЫ учитывать, что значения полей заголовков — это массивы, а не отдельные значения, и Caddy не интерпретирует их смысл в подобных случаях.

Пример:

Сопоставление запросов с заголовком Connection содержащим Upgrade:

@upgrade header Connection *Upgrade*

Сопоставление запросов с заголовком Foo содержащим bar или baz:

@foo {
	header Foo bar
	header Foo baz
}

Сопоставление запросов, у которых вообще нет поля заголовка Foo:

@not_foo header !Foo

Используя выражение CEL, сопоставляем запросы WebSocket, проверяя заголовок Connection, содержащий Upgrade, и заголовок Upgrade, равный websocket (HTTP/2 имеет заголовок :protocol для этого):

@websockets `header({'Connection':'*Upgrade*','Upgrade':'websocket'}) || header({':protocol': 'websocket'})`

header_regexp

header_regexp [<name>] <field> <regexp>
expression header_regexp('<name>', '<field>', '<regexp>')
expression header_regexp('<field>', '<regexp>')

Как и header, но поддерживает регулярные выражения.

Используемый язык регулярных выражений — RE2, включенный в Go. См. справочник по синтаксису RE2 и обзор синтаксиса регулярных выражений в Go.

Начиная с версии 2.8.0, если name не указан, имя будет взято из имени именованного матчера. Например, именованный матчер @foo заставит этот матчер получить имя foo. Основное преимущество указания имени заключается в том, что если используется несколько матчеров regexp (например, header_regexp и path_regexp, или несколько различных полей заголовков) в одном именованном матчере.

К группам захвата можно получить доступ через плейсхолдеры в директивах после сопоставления:

  • {re.<name>.<capture_group>}, где:

    • <name> — имя регулярного выражения,
    • <capture_group> — имя или номер группы захвата в выражении.
  • {re.<capture_group>} без имени также заполняется для удобства. Оговорка заключается в том, что если последовательно используются несколько матчеров regexp, то значения плейсхолдеров будут перезаписаны следующей матчером.

Группа захвата 0 — это полное совпадение регулярного выражения, 1 — первая группа захвата, 2 — вторая группа захвата и т. д. Таким образом, {re.foo.1} или {re.1} оба содержат значение первой группы захвата.

Поддерживается только одно регулярное выражение на поле заголовка, поскольку шаблоны regexp не могут быть объединены; если вам нужно больше, рассмотрите использование expression матчера. Сопоставления с несколькими разными полями заголовков будут соединены оператором И.

Пример:

Сопоставление запросов, где заголовок Cookie содержит login_, за которым следует шестнадцатеричная строка, с группой захвата, к которой можно получить доступ с помощью {re.login.1} или {re.1}.

@login header_regexp login Cookie login_([a-f0-9]+)

Это можно упростить, опуская имя, которое будет выведено из именованного матчера:

@login header_regexp Cookie login_([a-f0-9]+)

Или то же самое, с использованием выражения CEL:

@login `header_regexp('login', 'Cookie', 'login_([a-f0-9]+)')`

host

host <hosts...>
expression host('<hosts...>')

Сопоставление запроса по полю заголовка Host запроса.

Поскольку большинство блоков сайта уже указывают хосты в адресе сайта, этот матчер чаще используется в блоках сайта, использующих подстановку имени хоста (см. шаблон подстановочных символов в сертификатах), но где требуется логика, специфичная для имени хоста.

Несколько host-матчеров будут соединены оператором ИЛИ.

Пример:

Сопоставление одного поддомена:

@sub host sub.example.com

Сопоставление домена верхнего уровня и поддомена:

@site host example.com www.example.com

Несколько поддоменов, использующих выражение CEL:

@app `host('app1.example.com', 'app2.example.com')`

method

method <verbs...>
expression method('<verbs...>')

По методу (глаголу) HTTP-запроса. Глаголы должны быть заглавными, например, POST. Можно сопоставить один или несколько методов.

Несколько method-матчеров будут соединены оператором ИЛИ.

Примеры:

Сопоставление запросов с методом GET:

@get method GET

Сопоставление запросов с методами PUT или DELETE:

@put-delete method PUT DELETE

Сопоставление только методов чтения с использованием выражения CEL:

@read `method('GET', 'HEAD', 'OPTIONS')`

not

not <matcher>

или, для отрицания нескольких матчеров, которые объединяются оператором И, откройте блок:

not {
	<matchers...>
}

Результаты включённых матчеров будут инвертированы.

Примеры:

Сопоставление запросов с путями, которые НЕ начинаются с /css/ или /js/.

@not-assets {
	not path /css/* /js/*
}

Сопоставление запросов, которые НЕ имеют:

  • префикса пути /api/, ИЛИ
  • метода запроса POST

т. е. должны не иметь ни одного из этих условий для соответствия:

@with-neither {
	not path /api/*
	not method POST
}

Сопоставление запросов, которые НЕ имеют ОБОИХ:

  • префикса пути /api/, И
  • метода запроса POST

т. е. должны не иметь ни того, ни другого или иметь только одно для соответствия:

@without-both {
	not {
		path /api/*
		method POST
	}
}

Для этого матчера нет выражений CEL, потому что вы можете использовать оператор ! для инвертирования вместо этого. Например:

@without-both `!path('/api*') && !method('POST')`

Что эквивалентно этому с использованием скобок:

@without-both `!(path('/api*') || method('POST'))`

path

path <paths...>
expression path('<paths...>')

По пути запроса (части компонента URI запроса). Сопоставление путей точно, но регистронезависимо. Можно использовать подстановки *:

  • В конце только, для совпадения по префиксу (/prefix/*)
  • Только в начале, для совпадения по суффиксу (*.suffix)
  • Только с обеих сторон, для совпадения по подстроке (*/contains/*)
  • Только посередине, для совпадения по шару (/accounts/*/info)

Слэши важны. Например, /foo* будет соответствовать /foo, /foobar, /foo/ и /foo/bar, но /foo/* не будет соответствовать /foo или /foobar.

Пути запросов очищаются для разрешения точек обхода каталога перед соответствием. Кроме того, несколько слэшей объединяются, если шаблон совпадения не содержит несколько слэшей. Другими словами, /foo будет соответствовать /foo и //foo, но //foo будет соответствовать только //foo.

Поскольку существует несколько закодированных форм любого данного URI, путь запроса нормализуется (декодируется по URL, неэкранируется), за исключением тех последовательностей экранирования в позициях, где последовательности экранирования также присутствуют в шаблоне совпадения. Например, /foo/bar соответствует как /foo/bar, так и /foo%2Fbar, но /foo%2Fbar будет соответствовать только /foo%2Fbar, потому что последовательность экранирования явно указана в конфигурации.

Специальный экранированный символ подстановки %* также может быть использован вместо *, чтобы оставить его сопоставляемый интервал экранированным. Например, /bands/*/* не будет соответствовать /bands/AC%2FDC/T.N.T, потому что путь будет сравниваться в нормализованном пространстве, где он выглядит как /bands/AC/DC/T.N.T, что не соответствует шаблону; однако, /bands/%*/* будет соответствовать /bands/AC%2FDC/T.N.T, потому что интервал, представленный %*, будет сравниваться без декодирования последовательностей экранирования.

Несколько путей будут объединены операцией ИЛИ.

Примеры:

Сопоставление нескольких каталогов и их содержимого:

@assets path /js/* /css/* /images/*

Сопоставление определенного файла:

@favicon path /favicon.ico

Сопоставление расширений файлов:

@extensions path *.js *.css

С выражением CEL:

@assets `path('/js/*', '/css/*', '/images/*')`

path_regexp

path_regexp [<name>] <regexp>
expression path_regexp('<name>', '<regexp>')
expression path_regexp('<regexp>')

Как path, но поддерживает регулярные выражения. Выполняется по отношению к декодированному/неэкранированному пути URI.

Используемый язык регулярных выражений — RE2, включенный в Go. См. справочник по синтаксису RE2 и обзор синтаксиса регулярных выражений Go.

Начиная с версии 2.8.0, если name не предоставлен, имя будет взято из имени именованного соответствия. Например, именованное соответствие @foo приведет к тому, что это соответствие будет именоваться foo. Основное преимущество указания имени заключается в том, что если используется более одного соответствия regexp (например, path_regexp и header_regexp) в одном именованном соответствии.

К группам захвата можно получить доступ через заполнитель в директивах после совпадения:

  • {re.<name>.<capture_group>}, где:

    • <name> — имя регулярного выражения,
    • <capture_group> — имя или номер группы захвата в выражении.
  • {re.<capture_group>} без имени также заполняется для удобства. Ограничение состоит в том, что если несколько соответствий regexp используются последовательно, то значения заполнителей будут перезаписаны следующим соответствием.

Группа захвата 0 — это полное совпадение regexp, 1 — первая группа захвата, 2 — вторая группа захвата и так далее. Таким образом, {re.foo.1} или {re.1} оба содержат значение первой группы захвата.

В именованном соответствии может быть только один шаблон path_regexp, так как это соответствие не может быть объединено с самим собой; если вам нужно больше, рассмотрите использование expression соответствия.

Пример:

Сопоставление запросов, где путь заканчивается 6-значным шестнадцатеричным числом, за которым следует .css или .js в качестве расширения файла, с группами захвата (части, заключенные в ( )), к которым можно получить доступ с помощью {re.static.1} и {re.static.2} (или {re.1} и {re.2}) соответственно:

@static path_regexp static \.([a-f0-9]{6})\.(css|js)$

Это можно упростить, опустив имя, которое будет определено по умолчанию из именованного соответствия:

@static path_regexp \.([a-f0-9]{6})\.(css|js)$

Или то же самое, используя выражение CEL, также проверяя, что file существует на диске:

@static `path_regexp('\.([a-f0-9]{6})\.(css|js)$') && file()`

protocol

protocol http|https|grpc|http/<version>[+]
expression protocol('http|https|grpc|http/<version>[+]')

По протоколу запроса. Можно использовать общее имя протокола, такое как http, https или grpc; или конкретные или минимальные версии HTTP, такие как http/1.1 или http/2+.

В именованном соответствии может быть только одно соответствие protocol.

Пример:

Сопоставление запросов, использующих HTTP/2:

@http2 protocol http/2+

С выражением CEL:

@http2 `protocol('http/2+')`

query

query <key>=<val>...
expression query({'<key>': '<val>'})
expression query({'<key>': ['<vals...>']})

По параметрам строки запроса. Должен быть последовательностью пар key=value. Ключи сопоставляются точно (регистрозависимо), но также поддерживают * для соответствия любому значению. Значения могут использовать заполнители.

Может быть несколько соответствий query в одном именованном соответствии, а пары с одинаковыми ключами будут объединены операцией ИЛИ. Разные ключи будут объединены операцией И. Таким образом, все ключи в соответствии должны иметь по крайней мере одно соответствующее значение.

Неправильные строки запроса (неправильный синтаксис, неэкранированные точки с запятой и т. д.) не будут обработаны и, следовательно, не будут соответствовать.

ПРИМЕЧАНИЕ: Параметры строки запроса представляют собой массивы, а не отдельные значения. Это связано с тем, что повторяющиеся ключи допустимы в строках запроса, и каждый из них может иметь разное значение. Это соответствие будет соответствовать ключу, если любое из его настроенных значений назначено в строке запроса. Приложения на стороне сервера, использующие строки запроса, ДОЛЖНЫ учитывать, что значения строк запроса являются массивами и могут иметь несколько значений.

Пример:

Сопоставление параметра строки запроса q с любым значением:

@search query q=*

Сопоставление параметра строки запроса sort со значением asc или desc:

@sorted query sort=asc sort=desc

Сопоставление q и sort с помощью выражения CEL:

@search-sort `query({'sort': ['asc', 'desc'], 'q': '*'})`

remote_ip

remote_ip <ranges...>
expression remote_ip('<ranges...>')

По адресу удаленного IP-адреса (т. е. IP-адресу непосредственного peer). Принимает точные IP-адреса или диапазоны CIDR. Поддерживаются зоны IPv6.

В качестве сокращения можно использовать private_ranges для соответствия всем частным диапазонам IPv4 и IPv6. Это то же самое, что указание всех этих диапазонов: 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8 fd00::/8 ::1

Если вы хотите сопоставить «реальный IP» клиента, как он получен из заголовков HTTP, используйте соответствие client_ip вместо этого.

В именованном соответствии может быть несколько соответствий remote_ip, и их диапазоны будут объединены и объединены операцией ИЛИ.

Пример:

Сопоставление запросов с частных адресов IPv4:

@private-ipv4 remote_ip 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 127.0.0.1/8

Это соответствие обычно используется совместно с соответствием not для инвертирования соответствия. Например, для прерывания всех подключений с публичных адресов IPv4 и IPv6 (что является обратным всем частным диапазонам):

example.com {
	@denied not remote_ip private_ranges
	abort @denied
	respond "Hello, you must be from a private network!"
}

В выражении CEL он будет выглядеть так:

@my-friends `remote_ip('12.23.34.45', '23.34.45.56')`

vars

vars <variable> <values...>

По значению переменной в контексте запроса или значению заполнителя. Для соответствия может быть указано несколько значений (объединение ИЛИ).

Аргумент <variable> может быть либо именем переменной, либо заполнителем в фигурных скобках { }. (Заполнители не расширяются в первом параметре.)

Это соответствие наиболее полезно при совместном использовании с map директивой, которая устанавливает выходы, или с плагинами, которые устанавливают какую-либо информацию в контексте запроса.

Пример:

Сопоставление вывода map директивы с именем magic_number для значений 3 или 5:

vars {magic_number} 3 5

Сопоставление произвольного значения заполнителя, т. е. идентификатора аутентифицированного пользователя, либо Bob, либо Alice:

vars {http.auth.user.id} Bob Alice

vars_regexp

vars_regexp [<name>] <variable> <regexp>

Как vars, но поддерживает регулярные выражения.

Используемый язык регулярных выражений — RE2, включенный в Go. См. справочник по синтаксису RE2 и обзор синтаксиса регулярных выражений Go.

Начиная с версии 2.8.0, если name не предоставлен, имя будет взято из имени именованного соответствия. Например, именованное соответствие @foo приведет к тому, что это соответствие будет именоваться foo. Основное преимущество указания имени заключается в том, что если используется более одного соответствия regexp (например, vars_regexp и header_regexp) в одном именованном соответствии.

К группам захвата можно получить доступ через заполнитель в директивах после совпадения:

  • {re.<name>.<capture_group>}, где:

    • <name> — имя регулярного выражения,
    • <capture_group> — имя или номер группы захвата в выражении.
  • {re.<capture_group>} без имени также заполняется для удобства. Ограничение состоит в том, что если несколько соответствий regexp используются последовательно, то значения заполнителей будут перезаписаны следующим соответствием.

Группа захвата 0 — это полное совпадение regexp, 1 — первая группа захвата, 2 — вторая группа захвата и так далее. Таким образом, {re.foo.1} или {re.1} оба содержат значение первой группы захвата.

В именованном соответствии поддерживается только одно регулярное выражение, так как шаблоны regexp не могут быть объединены; если вам нужно больше, рассмотрите использование expression соответствия. Соответствия с несколькими переменными будут объединены операцией И.

Пример:

Сопоставление вывода map директивы с именем magic_number для значения, начинающегося с 4, захватывая значение в группе захвата, к которой можно получить доступ с помощью {re.magic.1} или {re.1}:

@magic vars_regexp magic {magic_number} ^(4.*)

Это можно упростить, опуская имя, которое будет определено по имени сопоставителю:

@magic vars_regexp {magic_number} ^(4.*)

© 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/caddyfile/matchers

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API