Перейти к основному содержимому

Кастомные HTTP-заголовки

К любому статическому сайту можно добавить собственные HTTP response headers — например Strict-Transport-Security, X-Frame-Options, Content-Security-Policy или Referrer-Policy. Задаются они файлом _headers в корне собранного сайта (синтаксис как у Netlify).

Отдельной панели «Custom Headers» в дашборде нет — управление заголовками живёт в этом файле, чтобы конфиг версионировался в git рядом с кодом.

Почему через файл, а не в коде сайта

У статического сайта нет вашего серверного процесса: это набор файлов, которые отдаёт CDN и edge-nginx Layero. HTTP response headers — часть ответа сервера, поэтому их проставляет тот, кто отдаёт байты, а не сам HTML-файл. Тег <meta http-equiv> здесь не помогает: браузеры игнорируют его для Strict-Transport-Security, X-Frame-Options, Content-Security-Policy — эти политики действуют только как настоящие HTTP-заголовки.

Файл _headers — это и есть способ передать ваше намерение на уровень отдачи: сборщик читает его и прикрепляет указанные заголовки к ответам edge.

:::note SSR и runtime-приложения Всё описанное — про статические сайты. Если у вас SSR или runtime-приложение (Next.js в режиме сервера, Streamlit, Flask), процесс работает на сервере и может ставить заголовки сам — в коде (res.setHeader(...), next.config.js → headers() и т.п.). Для таких проектов _headers не нужен. :::

Быстрый старт

Положите файл с именем _headers (без расширения) в корень выходной папки сборки — рядом с index.html:

_headers
/*
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin

Задеплойте — и заголовки начнут отдаваться на всех страницах сайта. Проверить можно любым запросом с -I:

curl -sI https://<org>-<project>.layero.ru/ | grep -i -E 'strict-transport|x-frame|referrer'

Синтаксис

Файл — это блоки. Блок начинается со строки-пути на левом краю (без отступа, должна начинаться с /). Следом идут строки с отступом вида Header-Name: значение, которые относятся к этому пути. Пустые строки и строки, начинающиеся с #, игнорируются.

_headers
# Комментарий — игнорируется

/*
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000

/about/
X-Robots-Tag: noindex

/assets/*
Cache-Control: public, max-age=31536000, immutable

Поддерживаемые пути

ШаблонЧто матчитПример
/*Все страницы (catch-all)весь сайт
Точный путьРовно этот URL/about/, /index.html
/prefix/*Все пути внутри префикса/assets/*, /docs/*

Wildcard в середине пути (/foo/*/bar) пока не поддерживается — такая строка молча пропускается, а в лог сборки пишется предупреждение.

Как разрешаются пересечения

Порядок в файле сохраняется, и при совпадении нескольких блоков для одного заголовка побеждает последний. Поэтому общий блок /* обычно ставят первым, а точечные переопределения — ниже:

_headers
/*
Cache-Control: public, max-age=0, must-revalidate

/assets/*
Cache-Control: public, max-age=31536000, immutable

Здесь /assets/style.css получит «долгий» кэш, а всё остальное — must-revalidate.

Что можно и нельзя задавать

Разрешены любые заголовки, включая Content-Security-Policy, Permissions-Policy, X-Content-Type-Options, Cross-Origin-* и т.д.

Несколько заголовков зарезервированы платформой и переопределить их нельзя — они пропускаются с предупреждением в логе сборки:

  • Set-Cookie
  • X-Layero-Cache, X-Layero-Deploy-Id, X-Layero-Project-Id, X-Layero-S3-Path, X-Layero-Redirects, X-Layero-Headers (служебные заголовки Layero).

Layero не добавляет security-заголовки автоматически. HSTS, X-Frame-Options и подобное появятся только после того, как вы объявите их в _headers.

Куда положить файл

_headers должен попасть в корень артефакта — ту папку, содержимое которой публикуется (output в настройках проекта или в layero.json).

  • Многие генераторы копируют «как есть» файлы из папки статики (public/, static/, assets/). Кладите _headers туда — на выходе он окажется в корне сборки.
  • Обычный проект: файл виден в собранной папке рядом с index.html.
  • Monorepo: в пределах root_directory проекта, чтобы после сборки оказаться в корне output.

После деплоя убедитесь, что заголовки применились, запросом curl -sI (см. Быстрый старт). Если их нет — почти всегда файл не попал в корень output.

Ошибки в файле не роняют деплой

Парсер устойчив к ошибкам: некорректные строки (путь без /, заголовок без :, неподдерживаемый wildcard, зарезервированное имя) пропускаются, корректные — применяются. Все замечания попадают в лог сборки, деплой не падает. Пустой или отсутствующий _headers очищает ранее заданные правила — так что состояние заголовков всегда отражает последнюю сборку.

Работает и на кастомных доменах

Заголовки применяются одинаково и на адресе <org>-<project>.layero.ru, и на подключённом кастомном домене — правила привязаны к деплою, а не к конкретному хосту.

Редиректы

Постраничные редиректы задаются соседним файлом _redirects (тоже Netlify-совместимый формат, матчит по пути). Обратите внимание: _redirects работает по пути, а не по хосту, поэтому host-based редирект www.site.ru → site.ru им не сделать — это настраивается на стороне DNS/регистратора (см. Кастомные домены).