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

Потоки запросов и границы системы

Эта страница объясняет, как запрос проходит через проект и где находятся границы ответственности.

Общий HTTP-поток

Упрощённый путь любого HTTP-запроса:

  1. Запрос входит в Laravel через public/index.php.
  2. Laravel application строится через bootstrap/app.php.
  3. До route/controller срабатывают глобальные middleware.
  4. Laravel ищет route: обычный route, route из frontend provider, Filament route или route из БД.
  5. Controller/closure/Livewire/Filament выполняет доменную логику.
  6. Ответ возвращается как redirect, JSON, JS, Blade view или Livewire response.

Глобальные middleware

В bootstrap/app.php глобально добавлены:

  • App\Http\Middleware\LoginByGkUHash;
  • App\Http\Middleware\Redirect.

Они подключены через prepend, поэтому их поведение нужно учитывать первым.

Redirect

Redirect читает активные записи LandingRedirect, строит кэшируемую карту landing_redirect_map и может сделать redirect до обработки route.

Особенности:

  • source URL нормализуется;
  • query string сохраняется;
  • добавляется защита от повторного redirect через header X-Redirect-Hop;
  • данные redirect-ов управляются из БД, не из кода.

Практический вывод: если URL ведёт себя странно, проверяйте не только routes, но и таблицу landing_redirects плюс cache key landing_redirect_map.

LoginByGkUHash

LoginByGkUHash смотрит query-параметр gk_uhash. Если параметр есть, middleware ищет пользователя GK, создаёт локального User при необходимости и логинит его в web guard.

Практический вывод: ?gk_uhash= — глобальная auth-граница. Она влияет не только на одну страницу, а на весь HTTP-контур.

Публичный каталог

Поток /catalog/...:

  1. ModernCatalogServiceProvider регистрирует catch-all route с prefix из config('systematika.modern_catalog_url').
  2. Route вызывает ModernCatalogController::view($segments).
  3. Controller передаёт URL-сегменты в InitialStateBuilder.
  4. InitialStateBuilder ищет сущности по slug и строит state.
  5. SEO builder подбирает page_title.
  6. Controller выставляет $GLOBALS['page_custom_head'] и $GLOBALS['page_custom_title'] при наличии title.
  7. Blade view pages.modern-catalog рендерит Livewire SPA.
  8. Livewire-компоненты фильтров отправляют событие setCatalogState.
  9. Spa пересобирает state и route.
  10. JS runtime меняет browser URL через history API.

Граница ответственности:

  • URL и slug parsing: RouteBuilder, InitialStateBuilder, AfterFilterStateBuilder.
  • Доступные фильтры: CatalogFilter.
  • Список продуктов: QueryBuilder.
  • SEO: CatalogSeoPhrase и builders в SeoPhrases.
  • UI: app/Livewire/ModernCatalog/*, resources/views/livewire/modern-catalog/*.

Roadmap

Поток /program/...:

  1. ModernRoadmapProvider регистрирует routes для /program, /program/{subject}, /program/{subject}/{level}, /program/{subject}/{level}/{mode}, /program/{subject}/{level}/{mode}/{variant}.
  2. ModernRoadmapController принимает текущий шаг.
  3. Controller создаёт State и Storage.
  4. State выбирает subject, difficulty level, mode и mode variant.
  5. PageAvailableHelper решает, можно ли показывать промежуточную страницу.
  6. Если страницу показывать нельзя, DefaultSlugHelper подбирает дефолтный slug и controller делает redirect.
  7. На финальном шаге Blade view рендерит Livewire roadmap SPA.
  8. ModulesResolver выбирает стратегию построения модулей.

Граница ответственности:

  • Выбор шагов: ModernRoadmapController, State, Storage.
  • Дефолты: DefaultSlugHelper.
  • Доступность промежуточных страниц: PageAvailableHelper.
  • Варианты selector-ов: SelectorBuilders/*.
  • Модули программы: Builders/*, ModulesResolver.

Важная деталь: в PageAvailableHelper флаги $enabled сейчас фактически выключены. Это значит, что многие промежуточные страницы не показываются как самостоятельные страницы, а схлопываются в redirect на default values.

Proxy pages

Поток proxy-страницы:

  1. При старте приложения ProxyPageServiceProvider проверяет, доступны ли таблицы landing_layouts и landing_proxy_pages.
  2. Провайдер читает активные LandingProxyPage.
  3. Для каждой записи регистрирует route.
  4. Route берёт to_path, при необходимости подставляет {path?}.
  5. View рендерится через proxy-pages.page или proxy-pages.tailwind-page.
  6. Layout/component получает HTML старого сайта, кэширует и вставляет локальный контент.

Граница ответственности:

  • Динамический список routes: таблица landing_proxy_pages.
  • Тип layout: таблица landing_layouts.
  • Кэш HTML: landing_page_cache_entries и view cache.
  • Принудительный refresh: header X-FORCE-UPDATE.
  • Прогрев после WP hook: jobs TriggerWpPageCache и TriggerLaravelPageCache.

API

routes/api.php содержит closure endpoints.

WP hook group

  • Middleware: CheckWpHookKey.
  • Header: X-WP-HOOK-KEY.
  • Endpoint POST /api/page-cache/wp-hook диспатчит TriggerWpPageCache.
  • Endpoint /api/debug-dump пишет диагностический dump в storage/logs.

Internal API group

  • Middleware: CheckApiKey.
  • Header: X-API-KEY.
  • Endpoint GET /api/export-group-discipline-gk-dtos отдаёт JS с window.COURSES_CATALOG.

Особенность: export-group-discipline-gk-dtos использует GroupDisciplineGkDtoResource::$allowedTypes из Filament namespace. Это смешивает API слой и admin слой.

Админка

Filament-поток:

  1. Route ведёт на path из ADMIN_PANEL.
  2. Filament применяет session/cookies/csrf/auth middleware.
  3. User::canAccessPanel() проверяет право входа.
  4. Resource/Page управляет конкретной моделью.
  5. Model events могут менять связанные записи.

Граница ответственности:

  • Panel config: AppPanelProvider.
  • CRUD screens: app/Filament/Panel/Resources/*.
  • Custom pages: app/Filament/Panel/Pages/*.
  • Permissions: Spatie Permission + project traits/policies.
  • Фактическая бизнес-валидация часто находится в моделях и формах Filament одновременно.

Cron и queue

Scheduler объявлен в routes/console.php.

Каждый день по timezone Europe/Moscow запускаются:

КомандаВремяЧто делает
cron:status-movement01:05, 13:05Меняет статусы product offerings по правилам переходов
cron:check-and-rebuild-status01:10, 13:10Синхронизирует формат и page status из текущего статуса
cron:tariff-movement01:15, 13:15Меняет тарифы product offerings по правилам переходов

Очередь по умолчанию — database. Для нормальной работы нужен queue worker. В dev-режиме composer dev запускает php artisan queue:listen --tries=1.

Границы безопасности

ГраницаМеханизм
АдминкаUser::canAccessPanel()
API keyCheckApiKey, header X-API-KEY
WP hookCheckWpHookKey, header X-WP-HOOK-KEY
Auto-loginLoginByGkUHash, query gk_uhash
Redirect controlLandingRedirect, cache landing_redirect_map
CSRF/session adminMiddleware Filament/Laravel

Документируйте любые изменения этих границ отдельно. Ошибка здесь меняет поведение всего сайта, а не одной страницы.