Введение
Справочному центру нужны быстрые публичные страницы, конечная точка проверки состояния в формате JSON и документ только для сотрудников. Статический файл может случайно получить приоритет перед кодом, который должен обработать запрос. Вы изучите это поведение локально, настроите маршрутизацию с приоритетом Worker и развернёте явную политику, которая сохранит доступность публичного сайта и защитит синтетический ресурс для сотрудников.
Эта самостоятельная лабораторная работа начинается в каталоге /home/labex/project/help-center. В окружении установлены Node.js 22.22.0, локальный Wrangler 4.131.1 и предоставленные файлы HTML, CSS и JavaScript. Используйте собственную учебную учётную запись Cloudflare, а также навыки авторизации, развёртывания и работы с файлами секретов, изученные ранее. Предыдущая виртуальная машина, облачный ресурс, купленный домен, база данных или платное обновление не требуются. Запросы учитываются в рамках обычного использования учётной записи.
Все содержимое и учётные данные синтетические. Оставьте один терминал открытым. Небезопасная исходная конфигурация используется только локально; развёртывается только исправленный Worker. Перед завершением работы виртуальной машины удалите развёртывание, удалите локальные тестовые учётные данные и выйдите из системы.
Наблюдение за маршрутизацией с приоритетом ресурсов локально
На этом шаге вы изучите предоставленную оболочку справочного центра и увидите, как по умолчанию совпадающие файлы получают приоритет перед Worker. В ресурсах специально присутствуют конфликтующий файл /api/health и фиктивный справочник для сотрудников. Всё содержимое синтетическое, а эта первая конфигурация остаётся локальной.
cd /home/labex/project/help-center
node --version
npx wrangler --version
ls -R public
Ожидайте Node v22.22.0 и Wrangler 4.131.1. Инструменты установлены локально для проекта; при воспроизведении окружения в другом месте используйте npm ci вместе с lock-файлом проекта. В каталоге public находятся HTML, CSS, JavaScript для браузера и два ресурса для проверки маршрутизации. Не помещайте туда учётные данные или настоящие внутренние документы.
WORKER_NAME="labex-help-$(openssl rand -hex 6)"
cat > wrangler.jsonc <<CONFIG
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-09-14",
"workers_dev": true,
"preview_urls": false,
"assets": {
"directory": "./public",
"binding": "ASSETS",
"html_handling": "none",
"not_found_handling": "none",
"run_worker_first": false
}
}
CONFIG
Параметр directory задаёт файлы для загрузки, а binding предоставляет их обработчику через env.ASSETS. Значение html_handling: none сохраняет явные пути к файлам, а not_found_handling: none отключает автоматический fallback для SPA. Поскольку автоматическая обработка HTML отключена, обработчик явно сопоставляет путь / с /index.html. Для проверки состояния он должен вернуть JSON, а остальные пути передать хранилищу ресурсов.
cat > src/index.js <<'JS'
export default {
async fetch(request, env) {
if (new URL(request.url).pathname === '/api/health') {
return Response.json({status: 'ok', service: 'help-center'});
}
const assetUrl = new URL(request.url);
if (assetUrl.pathname === '/') assetUrl.pathname = '/index.html';
return env.ASSETS.fetch(new Request(assetUrl, request));
}
};
JS
npx wrangler dev --ip 0.0.0.0 --port 8080 > dev.log 2>&1 &
cat dev.log
Прежде чем продолжить, дождитесь сообщения о готовности в журнале. При необходимости повторите cat.
curl -i http://127.0.0.1:8080/
curl -i http://127.0.0.1:8080/styles.css
curl -i http://127.0.0.1:8080/api/health
curl -i http://127.0.0.1:8080/staff/handbook.html
Главная страница и CSS должны вернуть код 200. Проверка состояния возвращает статический текст STATIC_HEALTH_PLACEHOLDER, а не JSON обработчика, потому что совпадающий ресурс получает приоритет. Фиктивный справочник также доступен напрямую. Это демонстрирует приоритет маршрутизации, но не является безопасным развёртыванием. Не разворачивайте эту исходную конфигурацию. Перед её изменением выполните проверку.
Если в вашей лабораторной среде доступен предварительный просмотр Web 8080, откройте его сейчас. Оболочка справочного центра загрузится, но её строка состояния сообщит, что состояние API недоступно, поскольку браузер ожидал JSON. Для проверки маршрутизации считайте ответы командной строки основным источником данных; предварительный просмотр служит визуальной контрольной точкой.
На примере ниже показана исходная проблема: страница и таблица стилей загружаются, но API status unavailable означает, что браузер не получил ожидаемый JSON проверки состояния. Одна только работающая оболочка страницы не подтверждает корректность маршрутизации API.

Запуск Worker перед ресурсами и защита содержимого для сотрудников
На этом шаге вы настроите запуск обработчика до проверки любого совпадения со статическим ресурсом. Остановите фактический процесс разработки, номер которого показан командой jobs; в примере предполагается, что это задание 1.
jobs
kill %1
cat > wrangler.jsonc <<CONFIG
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-09-14",
"workers_dev": true,
"preview_urls": false,
"assets": {
"directory": "./public",
"binding": "ASSETS",
"html_handling": "none",
"not_found_handling": "none",
"run_worker_first": true
}
}
CONFIG
При значении run_worker_first: true каждый запрос сначала попадает в обработчик, включая запросы к файлам, которые иначе совпали бы напрямую. Также существуют выборочные шаблоны маршрутов, но это небольшое приложение использует одну явную политику маршрутизации. См. раздел Static Assets configuration.
Создайте одноразовые учётные данные сотрудника с помощью описанного ранее процесса работы с файлом секретов. umask ограничивает права доступа к новым файлам. Это токен-носитель только для лабораторной работы, а не токен API учётной записи. Не размещайте его в публичных файлах, JavaScript-коде браузера, URL или журналах.
umask 077
STAFF_TOKEN=$(openssl rand -hex 24)
printf 'STAFF_TOKEN=%s\n' "$STAFF_TOKEN" > .dev.vars
cat .gitignore
Убедитесь, что шаблоны .dev.vars* и .env* исключены из системы контроля версий. Замените обработчик полной политикой ниже. Она один раз декодирует путь, возвращает состояние в формате JSON, разрешает только перечисленные публичные файлы, проверяет учётные данные сотрудника перед получением этого ресурса и отклоняет неизвестные пути. Запрос к ASSETS не содержит клиентский заголовок Authorization. Защищённые ответы используют private, no-store.
cat > src/index.js <<'JS'
export default {
async fetch(request, env) {
const url = new URL(request.url);
let path;
try { path = decodeURIComponent(url.pathname); }
catch { return Response.json({error: 'not_found'}, {status: 404}); }
if (path === '/api/health') {
if (request.method !== 'GET') {
return Response.json({error: 'method_not_allowed'}, {status: 405, headers: {Allow: 'GET'}});
}
return Response.json({status: 'ok', service: 'help-center'});
}
const publicPaths = ['/', '/index.html', '/styles.css', '/app.js'];
if (path === '/staff/handbook.html') {
if (!env.STAFF_TOKEN) return Response.json({error: 'staff_unconfigured'}, {status: 503});
if (request.headers.get('Authorization') !== `Bearer ${env.STAFF_TOKEN}`) {
return Response.json({error: 'unauthorized'}, {status: 401});
}
} else if (!publicPaths.includes(path)) {
return Response.json({error: 'not_found'}, {status: 404});
}
if (!['GET', 'HEAD'].includes(request.method)) {
return Response.json({error: 'method_not_allowed'}, {status: 405, headers: {Allow: 'GET, HEAD'}});
}
url.pathname = path === '/' ? '/index.html' : path;
// Only known paths reach the asset store, after any required authorization.
const response = await env.ASSETS.fetch(new Request(url, {method: request.method}));
if (path === '/staff/handbook.html') {
const headers = new Headers(response.headers);
headers.set('Cache-Control', 'private, no-store');
return new Response(response.body, {status: response.status, headers});
}
return response;
}
};
JS
npx wrangler dev --ip 0.0.0.0 --port 8080 > dev.log 2>&1 &
cat dev.log
После сообщения о готовности сравните ответы для публичного, защищённого и неизвестного маршрутов:
curl -i http://127.0.0.1:8080/api/health
curl -i http://127.0.0.1:8080/staff/handbook.html
curl -i http://127.0.0.1:8080/staff/handbook.html -H "Authorization: Bearer wrong-token"
curl -i http://127.0.0.1:8080/staff/handbook.html -H "Authorization: Bearer $STAFF_TOKEN"
curl -i --path-as-is http://127.0.0.1:8080/%73taff/handbook.html
curl -i http://127.0.0.1:8080/missing-page -H "Sec-Fetch-Mode: navigate"
Теперь проверка состояния возвращает 200 и {"status":"ok","service":"help-center"}, хотя конфликтующий файл по-прежнему существует. Запросы без учётных данных и с неверными учётными данными возвращают JSON с кодом 401, а с подходящим токеном возвращается HTML синтетического справочника. Закодированный путь к странице сотрудников также возвращает 401, а неизвестный навигационный запрос — JSON с кодом 404. Удаление ресурса скрыло бы проблему маршрутизации, поэтому оставьте его.
Обновите необязательный предварительный просмотр Web 8080: теперь строка состояния должна сообщать API status: ok. Конечная точка справочника без учётных данных возвращает JSON с кодом 401. Некоторые встроенные браузеры блокируют переход к такому ответу и оставляют на экране предыдущую страницу; для проверки используйте результат curl. Такое поведение браузера не подтверждает успешный доступ. Для авторизованного доступа используйте curl с синтетическим заголовком; не вставляйте секрет в адресную строку. Выполняйте проверку при работающем сервере. Она также проверяет HEAD, закодированные пути, альтернативные варианты написания и публичные типы ресурсов.
Сравните строку состояния с предыдущим предварительным просмотром. API status: ok показывает, что страница может прочитать ответ проверки состояния. Эта визуальная проверка охватывает публичный маршрут состояния; для оценки защищённого справочника используйте приведённые выше ответы curl.

Развёртывание ресурсов и защищённого обработчика
На этом шаге вы развернёте только исправленную конфигурацию в своей учебной учётной записи. Остановите текущий локальный процесс, используя его фактический номер из команды jobs.
jobs
kill %1
npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_tail:read
Откройте показанную ссылку и введите код устройства в браузере, где выполнен вход, проверьте существующие разрешения Wrangler и Background Access, затем выберите свою учебную учётную запись. Дождитесь завершения команды в терминале.
npx wrangler whoami --json
Подтвердите фактическое имя и ID учётной записи, затем замените YOUR_ACCOUNT_ID ниже на этот ID. Сохраните исходное имя ресурса и исправленные настройки ресурсов.
cat > wrangler.jsonc <<CONFIG
{
"name": "$WORKER_NAME",
"main": "src/index.js",
"compatibility_date": "2026-09-14",
"account_id": "YOUR_ACCOUNT_ID",
"workers_dev": true,
"preview_urls": false,
"assets": {
"directory": "./public",
"binding": "ASSETS",
"html_handling": "none",
"not_found_handling": "none",
"run_worker_first": true
}
}
CONFIG
npx wrangler deploy
Wrangler загружает каталог public и разворачивает его обработчик. Скопируйте точный напечатанный URL workers.dev ниже. Используйте существующий поддомен учебной учётной записи; пользователи, которые делают это впервые, могут воспользоваться подсказкой Wrangler о доступном поддомене.
APP_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$APP_URL/staff/handbook.html"
До загрузки секрета этот маршрут возвращает 503 staff_unconfigured: обработчик запускается первым и по умолчанию отклоняет запрос. .dev.vars — локальная конфигурация, она не была загружена во время развёртывания. Если первоначальное распространение имени хоста задерживает ответ, кратко повторите запрос перед расследованием постоянной ошибки.
npx wrangler secret bulk .dev.vars
npx wrangler secret list
Убедитесь, что STAFF_TOKEN отображается как secret_text, но его значение не выводится. Доставка секрета во все точки обслуживания может занять некоторое время. Если следующие запросы по-прежнему возвращают staff_unconfigured, подождите 10 секунд и повторяйте их в течение максимум двух минут. Перед проверкой требуется стабильный ответ 401 без учётных данных и 200 с ними. Постоянное несоответствие нужно расследовать; не принимайте 503 как окончательный результат и не меняйте политику авторизации только для успешного прохождения проверки.
curl -i "$APP_URL/"
curl -i "$APP_URL/api/health"
curl -i "$APP_URL/staff/handbook.html"
curl -i "$APP_URL/staff/handbook.html" -H "Authorization: Bearer $STAFF_TOKEN"
curl -i "$APP_URL/missing-page" -H "Sec-Fetch-Mode: navigate"
Ожидайте публичный HTML, JSON проверки состояния, код 401 без учётных данных, HTML справочника с учётными данными и код 404 для неизвестной страницы. В той же учётной записи Dashboard откройте Compute → Workers & Pages, найдите нужный Worker и подтвердите его публичный URL. Используйте проверку, чтобы удостовериться в принадлежности ресурса, развёрнутых привязках, содержимом ресурсов и поведении авторизации. Также можно открыть публичную главную страницу в собственном браузере; не передавайте токен сотрудника через URL. Синтетическая проверка токена — это урок по маршрутизации, а не полноценная система идентификации сотрудников.
На вкладке Overview Worker сравните имя в цепочке навигации и связанный адрес workers.dev с результатом развёртывания. Имя и поддомен на снимке экрана являются примерами; сгенерированные имя и поддомен учётной записи у вас будут другими. Это публичный адрес развёрнутого приложения, тогда как Web 8080 показывает локальный сервер разработки. Открытие этого существующего Worker не требует создания другого приложения.

Удаление развёртывания справочного центра
На этом шаге вы удалите Worker лабораторной работы, связанные с ним ресурсы и привязку секрета, пока авторизация ещё действует. Подтвердите уникальное имя и учётную запись:
cat wrangler.jsonc
npx wrangler delete
Проверьте точное имя лабораторного ресурса в приглашении, затем нажмите единственную клавишу y. Wrangler 4.131.1 может сообщить задокументированную устаревшую ошибку аутентификации Workers Sites KV после удаления. Не расширяйте разрешения и не используйте это сообщение как доказательство удаления. Обновите раздел Workers & Pages и выполните проверку: успешный авторизованный список ресурсов должен показывать, что это имя отсутствует. Сохраните все несвязанные ресурсы, учётную запись и её поддомен workers.dev.
Удаление локальных учётных данных и отключение
На этом шаге вы удалите локальные синтетические учётные данные после проверки очистки в облаке, а затем отключите эту виртуальную машину.
rm .dev.vars
unset STAFF_TOKEN
npx wrangler logout
npx wrangler whoami --json
Ожидайте явное значение "loggedIn": false; ненулевой код выхода для неаутентифицированного состояния ожидаем, если этот структурированный результат присутствует. Выполните проверку и завершите работу виртуальной машины. Вход через браузер может остаться доступным; ни завершение работы виртуальной машины, ни выход из системы не удаляют облачные ресурсы автоматически.
Итоги
Вы наблюдали маршрутизацию с приоритетом ресурсов, а затем использовали обработку с приоритетом Worker, чтобы ответы API и авторизация имели приоритет перед совпадающими файлами. Предоставленная оболочка справочного центра сохранила публичные HTML, CSS и JavaScript для браузера, а явная обработка путей заблокировала запросы сотрудников без авторизации и неизвестные маршруты. Вы проверили закодированные пути и навигацию в стиле браузера, развернули исправленный сайт с отдельной загрузкой секрета, а затем подтвердили удаление и выход из системы.
Всегда осознанно выбирайте порядок маршрутизации, когда статические файлы и политика приложения используют одно имя хоста. Один локальный ответ не подтверждает корректность развёрнутой конфигурации или принадлежность учётной записи.

