Spec-Zone.ru › Varnish

VMOD std — Стандартный модуль Varnish

СИНОПСИС

import std [as name] [from "path"]

REAL random(REAL lo, REAL hi)

REAL round(REAL r)

VOID collect(HEADER hdr, STRING sep=”, “)

STRING querysort(STRING)

STRING toupper(STRING s)

STRING tolower(STRING s)

STRING strstr(STRING s1, STRING s2)

BOOL fnmatch(STRING pattern, STRING subject, BOOL pathname, BOOL noescape, BOOL period)

STRING fileread(STRING)

BLOB blobread(STRING)

BOOL file_exists(STRING path)

BOOL healthy(BACKEND be)

INT port(IP ip)

DURATION duration([STRING s], [DURATION fallback], [REAL real], [INT integer])

BYTES bytes([STRING s], [BYTES fallback], [REAL real], [INT integer])

INT integer([STRING s], [INT fallback], [BOOL bool], [BYTES bytes], [DURATION duration], [REAL real], [TIME time])

IP ip(STRING s, [IP fallback], BOOL resolve=1, [STRING p])

REAL real([STRING s], [REAL fallback], [INT integer], [BOOL bool], [BYTES bytes], [DURATION duration], [TIME time])

TIME time([STRING s], [TIME fallback], [REAL real], [INT integer])

STRING strftime(TIME time, STRING format)

VOID log(STRING s)

VOID syslog(INT priority, STRING s)

VOID timestamp(STRING s)

BOOL syntax(REAL)

STRING getenv(STRING name)

BOOL cache_req_body(BYTES size)

VOID late_100_continue(BOOL late)

VOID set_ip_tos(INT tos)

VOID rollback(HTTP h)

BOOL ban(STRING)

STRING ban_error()

TIME now()

DURATION timed_call(SUB)

INT real2integer(REAL r, INT fallback)

TIME real2time(REAL r, TIME fallback)

INT time2integer(TIME t, INT fallback)

REAL time2real(TIME t, REAL fallback)

ОПИСАНИЕ

vmod_std содержит базовые функции, являющиеся неотъемлемой частью Varnish, но по архитектурным соображениям лучше расположенные в VMOD.

Числовые функции

REAL random(REAL lo, REAL hi)

Возвращает случайное вещественное число между lo и hi.

Эта функция использует «тестируемый» генератор случайных чисел в varnishd, что позволяет выполнять детерминированные тесты (см. команду debug.srandom CLI). Эта функция не должна использоваться для криптографических приложений.

Пример:

set beresp.http.random-number = std.random(1, 100);

REAL round(REAL r)

Округляет вещественное число r до ближайшего целого, но в случае середины округляет в сторону от нуля (см. round(3)).

Строковые функции

VOID collect(HEADER hdr, STRING sep=”, “)

Объединяет несколько заголовков hdr в один длинный заголовок. По умолчанию разделитель sep — стандартная запятая с дополнительным пробелом для красивого вывода.

Следует быть осторожным при объединении заголовков. В частности, объединение Set-Cookie приведёт к неожиданным результатам на стороне браузера.

Использование hdr из obj.http приводит к сбою VCL.

Примеры:

std.collect(req.http.accept);
std.collect(req.http.cookie, "; ");

STRING querysort(STRING)

Сортирует строку запроса для целей нормализации кэша.

Пример:

set req.url = std.querysort(req.url);

STRING toupper(STRING s)

Преобразует строку s в верхний регистр.

Пример:

set beresp.http.scream = std.toupper("yes!");

STRING tolower(STRING s)

Преобразует строку s в нижний регистр.

Пример:

set beresp.http.nice = std.tolower("VerY");

STRING strstr(STRING s1, STRING s2)

Возвращает строку, начинающуюся с первого вхождения строки s2 в строке s1, или пустую строку, если s2 не найдена.

Обратите внимание, что сравнение регистрозависимое.

Пример:

if (std.strstr(req.url, req.http.restrict)) {
        ...
}

Это проверит, встречается ли содержимое req.http.restrict где-либо в req.url.

BOOL fnmatch(STRING pattern, STRING subject, BOOL pathname, BOOL noescape, BOOL period)

BOOL fnmatch(
   STRING pattern,
   STRING subject,
   BOOL pathname=1,
   BOOL noescape=0,
   BOOL period=0
)

Сопоставление с образцом в стиле оболочки; возвращает true если subject соответствует pattern, где pattern может содержать символы подстановочных знаков, такие как * или ?.

Сопоставление выполняется реализацией fnmatch(3) на вашей системе. Правила сопоставления с образцом на большинстве систем включают следующие:

  • * соответствует любой последовательности символов
  • ? соответствует одному символу
  • выражение в квадратных скобках, такое как [abc] или [!0-9] интерпретируется как класс символов в соответствии с правилами основных регулярных выражений (не pcre2(3) регулярных выражений), за исключением того, что ! используется для отрицания класса символов вместо ^.

Если pathname равно true, то символ обратного слэша / соответствует только буквально и никогда не соответствует *, ? или выражению в квадратных скобках. В противном случае / может соответствовать одному из этих шаблонов. По умолчанию pathname равно true.

Если noescape равно true, то символ обратного слэша \ соответствует как обычный символ. В противном случае \ является символом экранирования и соответствует символу, следующему за ним в pattern. Например, \\ соответствует \ когда noescape равно true, и \\ когда false. По умолчанию noescape равно false.

Если period равно true, то ведущий символ точки . соответствует только буквально и никогда не соответствует *, ? или выражению в квадратных скобках. Точка считается ведущей, если она является первым символом в subject; если pathname также равно true, то точка, которая сразу следует за / тоже является ведущей (как в /.). По умолчанию period равно false.

std.fnmatch() вызывает сбой VCL и возвращает false если pattern или subject равны NULL — например, если указан не заданный заголовок.

Примеры:

# Matches URLs such as /foo/bar and /foo/baz
if (std.fnmatch("/foo/\*", req.url)) { ... }

# Matches URLs such as /foo/bar/baz and /foo/baz/quux
if (std.fnmatch("/foo/\*/\*", bereq.url)) { ... }

# Matches /foo/bar/quux, but not /foo/bar/baz/quux
if (std.fnmatch("/foo/\*/quux", req.url)) { ... }

# Matches /foo/bar/quux and /foo/bar/baz/quux
if (std.fnmatch("/foo/\*/quux", req.url, pathname=false)) { ... }

# Matches /foo/bar, /foo/car and /foo/far
if (std.fnmatch("/foo/?ar", req.url)) { ... }

# Matches /foo/ followed by a non-digit
if (std.fnmatch("/foo/[!0-9]", req.url)) { ... }

Файловые (системные) функции

STRING fileread(STRING)

Читает текстовый файл и возвращает строку с содержимым.

Весь файл кэшируется при первом вызове, и последующие вызовы вернут это кэшированное содержимое, даже если файл изменился тем временем.

Для двоичных файлов используйте std.blobread() вместо этого.

Пример:

synthetic("Response was served by " + std.fileread("/etc/hostname"));

Учитывайте, что все содержимое файла появляется в возвращаемой строке, включая символы новой строки, которые могут привести к неверным заголовкам, если std.fileread() используется для формирования заголовка. В этом случае вам может потребоваться изменить строку, например, с помощью regsub() (см. VCL):

set beresp.http.served-by = regsub(std.fileread("/etc/hostname"), "\R$", "");

BLOB blobread(STRING)

Читает любой файл и возвращает blob с содержимым.

Весь файл кэшируется при первом вызове, и последующие вызовы вернут это кэшированное содержимое, даже если файл изменился тем временем.

BOOL file_exists(STRING path)

Возвращает true если путь или файл, на который указывает путь, существует, false в противном случае.

Пример:

if (std.file_exists("/etc/return_503")) {
        return (synth(503, "Varnish is in maintenance"));
}

Функции проверки типов

BOOL healthy(BACKEND be)

Возвращает true если бэкенд be работает нормально.

INT port(IP ip)

Возвращает номер порта IP-адреса ip. Всегда возвращает 0 для *.ip переменной, когда адрес является сокетом Unix-домена.

Функции преобразования типов

Все эти функции имеют одинаковую форму:

TYPE type([arguments], [fallback TYPE])

Должен быть предоставлен ровно один из аргументов (кроме необязательного fallback), и он будет преобразован в TYPE.

Если преобразование завершится неудачно, будет возвращено значение fallback, а если fallback не указан, произойдёт сбой VCL.

DURATION duration([STRING s], [DURATION fallback], [REAL real], [INT integer])

DURATION duration(
   [STRING s],
   [DURATION fallback],
   [REAL real],
   [INT integer]
)

Возвращает DURATION из STRING, REAL или INT аргумента.

Для строкового аргумента s, s должен быть квантифицирован с помощью единиц ms (миллисекунды), s (секунды), m (минуты), h (часы), ``d`` (дни), w (недели) или y (годы).

Аргументы real и integer принимаются как секунды.

Если преобразование аргумента s завершится неудачно, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Преобразования из аргументов real и integer никогда не завершаются неудачей.

Должен быть указан только один из аргументов s, real или integer, иначе произойдёт сбой VCL.

Примеры:

set beresp.ttl = std.duration("1w", 3600s);
set beresp.ttl = std.duration(real=1.5);
set beresp.ttl = std.duration(integer=10);

BYTES bytes([STRING s], [BYTES fallback], [REAL real], [INT integer])

BYTES bytes(
   [STRING s],
   [BYTES fallback],
   [REAL real],
   [INT integer]
)

Возвращает BYTES из STRING, REAL или INT аргумента.

Строковый аргумент s может быть квантифицирован с помощью множителей (k (кило), m (мега), g (гига), t (тера) или p (пета)).

Аргументы real и integer принимаются как байты.

Если преобразование аргумента s завершится неудачно, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Другие преобразования могут завершиться неудачей, если аргумент не может быть представлен, потому что он отрицательный, слишком малый или слишком большой. Опять же, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Аргументы real будут округляться вниз.

Должен быть указан только один из аргументов s, real или integer, иначе произойдёт сбой VCL.

Пример:

std.cache_req_body(std.bytes(something.somewhere, 10K));
std.cache_req_body(std.bytes(integer=10*1024));
std.cache_req_body(std.bytes(real=10.0*1024));

INT integer([STRING s], [INT fallback], [BOOL bool], [BYTES bytes], [DURATION duration], [REAL real], [TIME time])

INT integer(
   [STRING s],
   [INT fallback],
   [BOOL bool],
   [BYTES bytes],
   [DURATION duration],
   [REAL real],
   [TIME time]
)

Возвращает INT из STRING, BOOL или других величин.

Если преобразование аргумента s завершится неудачно, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Аргумент bool будет возвращён как 0 для false и 1 для true. Это преобразование никогда не завершится неудачей.

Для аргумента bytes будет возвращено количество байтов. Это преобразование никогда не завершится неудачей.

Аргумент duration будет округлен вниз до количества секунд и возвращён.

Аргумент real будет округлен вниз и возвращён.

Для аргумента time будет возвращено количество секунд с начала эпохи Unix (1970-01-01 00:00:00 UTC).

Преобразования из duration, real и time могут завершиться неудачей, если аргумент не может быть представлен, потому что он слишком мал или слишком велик. В этом случае будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Должен быть указан только один из аргументов s, bool, bytes, duration, real или time, иначе произойдёт сбой VCL.

Примеры:

if (std.integer(req.http.foo, 0) > 5) {
        ...
}

set resp.http.answer = std.integer(real=126.42/3);

IP ip(STRING s, [IP fallback], BOOL resolve=1, [STRING p])

Преобразует строку s в первый IP-адрес, возвращённый системной библиотечной функцией getaddrinfo(3). Если преобразование завершится неудачно, будет возвращено значение fallback или произойдёт сбой VCL.

IP-адрес включает номер порта, который можно найти с помощью std.port(), по умолчанию равного 80. Значение порта по умолчанию можно изменить с помощью аргумента p. Оно будет перезаписано, если s содержит как IP-адрес, так и номер порта или имя сервиса.

Если s содержит оба, синтаксис может быть либо address:port либо address port. Если адрес является числовым IPv6-адресом, он должен быть заключён в квадратные скобки, например [::1] 80 или [::1]:http. Значение fallback также может содержать и адрес, и порт, но его порт по умолчанию всегда 80.

Если resolve ложно, вызывается getaddrinfo(3) с использованием AI_NUMERICHOST и AI_NUMERICSERV, чтобы избежать сетевых запросов в зависимости от системной конфигурации getaddrinfo(3) или nsswitch. Это делает преобразование "числовых" IP-строк и сервисов более эффективным.

Пример:

if (std.ip(req.http.X-forwarded-for, "0.0.0.0") ~ my_acl) {
        ...
}

REAL real([STRING s], [REAL fallback], [INT integer], [BOOL bool], [BYTES bytes], [DURATION duration], [TIME time])

REAL real(
   [STRING s],
   [REAL fallback],
   [INT integer],
   [BOOL bool],
   [BYTES bytes],
   [DURATION duration],
   [TIME time]
)

Возвращает REAL из STRING, BOOL или других величин.

Если преобразование аргумента s завершится неудачно, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Аргумент bool будет возвращён как 0.0 для false и 1.0 для true.

Для аргумента bytes будет возвращено количество байтов.

Для аргумента duration будет возвращено количество секунд.

Аргумент integer будет возвращён как REAL.

Для аргумента time будет возвращено количество секунд с начала эпохи Unix (1970-01-01 00:00:00 UTC).

Ни одно из этих преобразований, кроме s, не завершится неудачей.

Должен быть указан только один из аргументов s, integer, bool, bytes, duration или time, иначе произойдёт сбой VCL.

Пример:

if (std.real(req.http.foo, 0.0) > 5.5) {
        ...
}

TIME time([STRING s], [TIME fallback], [REAL real], [INT integer])

TIME time([STRING s], [TIME fallback], [REAL real], [INT integer])

Возвращает TIME из STRING, REAL или INT аргумента.

Для строкового аргумента s поддерживаются следующие форматы:

"Sun, 06 Nov 1994 08:49:37 GMT"
"Sunday, 06-Nov-94 08:49:37 GMT"
"Sun Nov  6 08:49:37 1994"
"1994-11-06T08:49:37"
"784111777.00"
"784111777"

Аргументы real и integer принимаются как секунды с начала эпохи.

Если преобразование аргумента s завершится неудачно или аргументы real или integer отрицательны, будет возвращено значение fallback, если оно указано, иначе произойдёт сбой VCL.

Примеры:

if (std.time(resp.http.last-modified, now) < now - 1w) {
        ...
}

if (std.time(int=2147483647) < now - 1w) {
        ...
}

STRING strftime(TIME time, STRING format)

Форматирует аргумент time с помощью аргумента format, используя strftime(3) и возвращает результат для часового пояса UTC (исторически GMT).

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

Пример:

set req.http.iso = std.strftime(now, "%Y%m%dT%H%M%SZ");
# e.g. 20210521T175241Z

Функции LOGGING

VOID log(STRING s)

Записывает строку s в общий журнал памяти, используя тег VSL SLT_VCL_Log.

Пример:

std.log("Something fishy is going on with the vhost " + req.http.host);

VOID syslog(INT priority, STRING s)

Записывает строку s в syslog с тегом priority. priority формируется путём объединения значений facility и level. Смотрите файл syslog.h вашей системы для возможных значений.

Примечание: В отличие от VCL и других функций в модуле std vmod, эта функция не вызовет сбой VCL при переполнении рабочей области: При условии переполнения рабочей области функция std.syslog() не оказывает никакого влияния.

Пример:

std.syslog(9, "Something is wrong");

Это отправит сообщение в syslog, используя LOG_USER | LOG_ALERT.

VOID timestamp(STRING s)

Вставляет метку времени в журнал с текущим временем, используя строку s в качестве метки. Это полезно для определения времени выполнения длинных подпрограмм VCL и делает метки времени, автоматически вставляемые Varnish, более точными.

Пример:

std.timestamp("curl-request");

Функции УПРАВЛЕНИЯ и ИНФОРМАЦИИ

BOOL syntax(REAL)

Возвращает true если версия VCL не ниже REAL.

STRING getenv(STRING name)

Возвращает переменную окружения name или пустую строку. См. getenv(3).

Пример:

set req.http.My-Env = std.getenv("MY_ENV");

BOOL cache_req_body(BYTES size)

Кэширует тело запроса, если оно меньше size. Возвращает true если тело было кэшировано, false в противном случае.

Обычно тело запроса можно отправить только один раз. Кэширование позволяет повторно отправлять запросы к бэкенду с телом запроса, как обычно это происходит с POST и PUT.

Пример:

if (std.cache_req_body(1KB)) {
        ...
}

Ограничение: vcl_recv.

VOID late_100_continue(BOOL late)

Управляет тем, когда varnish реагирует на заголовок запроса клиента Expect: 100-continue.

Varnish всегда генерирует ответ 100 Continue по запросу клиента через заголовок Expect: 100-continue при ожидании данных тела запроса.

Но по умолчанию ответ 100 Continue генерируется сразу после того, как vcl_recv возвращается, для уменьшения задержек, предполагая, что тело запроса будет прочитано в конечном итоге.

Вызов std.late_100_continue(true) в vcl_recv заставит ответ 100 Continue быть отправлен только по необходимости. Это может привести к дополнительным задержкам при обработке тел запросов, но является правильным поведением при строгом толковании RFC7231.

Эта функция не действует вне vcl_recv и после вызова std.cache_req_body() или любой другой функции, использующей тело запроса.

Пример:

vcl_recv {
        std.late_100_continue(true);

        if (req.method == "POST") {
                std.late_100_continue(false);
                return (pass);
        }
        ...
 }

Ограничение: vcl_recv.

VOID set_ip_tos(INT tos)

Устанавливает байт Differentiated Services Codepoint (DSCP) / IPv4 Type of Service (TOS) / IPv6 Traffic Class (TCLASS) для текущего сеанса на tos. Бездействует, если адрес прослушивания — сокет доменной Unix.

Обратите внимание, что установка класса трафика влияет на все запросы по одному TCP-соединению http1.1 / http2 и, в частности, не удаляется в конце запроса.

Пример:

if (req.url ~ "^/slow/") {
        std.set_ip_tos(0);
}

Ограничение: client.

VOID rollback(HTTP h)

Восстанавливает HTTP-заголовки h до их исходного состояния.

Пример:

std.rollback(bereq);

Ограничение: backend, vcl_recv, vcl_pass, vcl_hash, vcl_purge, vcl_miss, vcl_hit, vcl_deliver, vcl_synth.

BOOL ban(STRING)

Деактивирует все объекты кэша, соответствующие заданному выражению с помощью механизма запрета. Возвращает true если запрет выполнен успешно, и false в противном случае. Подробности об ошибке доступны через std.ban_error().

Формат STRING:

<field> <operator> <arg> [&& <field> <oper> <arg> ...]
  • <поле>:

    • строковые поля:

      • req.url: URL запроса
      • req.http.*: Любой заголовок запроса
      • obj.status: Статус объекта кэша
      • obj.http.*: Любой заголовок объекта кэша

      obj.status обрабатывается как строка, несмотря на то, что фактически является целым числом.

    • поля длительности:

      • obj.ttl: Остающееся значение ttl в момент выдачи запрета
      • obj.age: Возраст объекта в момент выдачи запрета
      • obj.grace: Время ожидания объекта
      • obj.keep: Время хранения объекта
  • <оператор>:

    • для всех полей:

      • ==: <поле> и <аргумент> равны
      • !=: <поле> и <аргумент> не равны

      строки сравниваются регистрозависимо

    • для строковых полей:

      • ~: <поле> соответствует регулярному выражению <аргумент>
      • !~: <поле> не соответствует регулярному выражению <аргумент>
    • для полей длительности:

      • >: <поле> больше, чем <аргумент>
      • >=: <поле> больше или равно <аргумент>
      • <: <поле> меньше, чем <аргумент>
      • <=: <поле> меньше или равно <аргумент>
  • <аргумент>:

    • для строковых полей:

      Либо строковая константа, либо регулярное выражение. Обратите внимание, что <аргумент> не использует какие-либо разделители строк, такие как " или {"…"} или """…""" используемые в другом месте в varnish. Для сопоставления со строками, содержащими пробелы, можно использовать регулярные выражения, содержащие \s.

    • для полей длительности:

      Длительность VCL, например 10s, 5m или 1h, см. Длительности

Выражения могут быть объединены с помощью оператора и &&. Для использования логики или используйте несколько запретов.

Неопределённое <поле> не равно ни одной строке, таким образом для несуществующего заголовка операторы == и ~ всегда возвращают false, а операторы != и !~ всегда возвращают true, соответственно, для любого значения <аргумента>.

STRING ban_error()

Возвращает текстовое описание ошибки последнего вызова std.ban() из той же задачи или пустую строку, если ошибка отсутствовала или вызов std.ban() не был.

TIME now()

Возвращает текущее время. В отличие от встроенной переменной now каждый вызов возвращает новое значение.

DURATION timed_call(SUB)

Вызывает заданный SUB и возвращает высокоточное измерение времени выполнения.

УСТАРЕВШИЕ функции

INT real2integer(REAL r, INT fallback)

УСТАРЕВШАЯ: Эта функция будет удалена в будущей версии varnish, используйте std.integer() с аргументом real и функцию std.round() вместо этого, например:

std.integer(real=std.round(...), fallback=...)

Округляет вещественное число r до ближайшего целого, но при округлении половинных значений уходит от нуля (см. round(3)). Если преобразование завершается с ошибкой, возвращается fallback.

Примеры:

set req.http.integer = std.real2integer(1140618699.00, 0);
set req.http.posone = real2integer( 0.5, 0);    # =  1.0
set req.http.negone = real2integer(-0.5, 0);    # = -1.0

TIME real2time(REAL r, TIME fallback)

УСТАРЕВШАЯ: Эта функция будет удалена в будущей версии varnish, используйте std.time() с аргументом real и функцию std.round() вместо этого, например:

std.time(real=std.round(...), fallback=...)

Округляет вещественное число r до ближайшего целого (см. std.real2integer()) и возвращает соответствующее время, когда интерпретируется как unix-эпоха. Если преобразование завершается с ошибкой, возвращается fallback.

Пример:

set req.http.time = std.real2time(1140618699.00, now);

INT time2integer(TIME t, INT fallback)

УСТАРЕВШАЯ: Эта функция будет удалена в будущей версии varnish, используйте std.integer() с аргументом time вместо этого, например:

std.integer(time=..., fallback=...)

Преобразует время t в целое число. Если преобразование завершается с ошибкой, возвращается fallback.

Пример:

set req.http.int = std.time2integer(now, 0);

REAL time2real(TIME t, REAL fallback)

УСТАРЕВШАЯ: Эта функция будет удалена в будущей версии varnish, используйте std.real() с аргументом time вместо этого, например:

std.real(time=..., fallback=...)

Преобразует время t в вещественное число. Если преобразование завершается с ошибкой, возвращается fallback.

Пример:

set req.http.real = std.time2real(now, 1.0);

СМОТРИТЕ ТАКЖЕ

  • varnishd
  • VSL
  • fnmatch(3)
  • strftime(3)

АВТОРСКИЕ ПРАВА

Copyright (c) 2010-2017 Varnish Software AS
All rights reserved.

Author: Poul-Henning Kamp <phk@FreeBSD.org>

SPDX-License-Identifier: BSD-2-Clause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

Copyright © 2006 Verdens Gang AS
Copyright © 2006–2020 Varnish Software AS
Licensed under the BSD-2-Clause License.
https://varnish-cache.org/docs/7.4/reference/vmod_std.html

Spec-Zone.ru

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