4.0 KiB
4.0 KiB
Архитектура и жизненный цикл запроса
Общая схема
HTTP → Caddy (:80) → /worker.php → FrankenPHP worker loop
Kernel::boot($basePath) [один раз при старте]
→ Environment::detect() // читает APP_ENV, дефолт 'dev'
→ Config::load($configDir) // config/*.php + config/env/{env}.php + config/env/local.php
→ ContainerFactory::build() // PHP-DI, в prod компилируется в var/cache/prod/
loop (WorkerRunner::run()):
frankenphp_handle_request(fn() =>
HttpApplication::handleRequest($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER)
→ Request::fromGlobals() // парсит метод, путь, заголовки, JSON body
→ OPTIONS? → CORS headers + 204 // preflight, без роутинга
→ Router::match(method, path) // regex-компиляция {param} → именованные группы
→ 404 / 405+Allow / RouteMatch
→ MiddlewarePipeline::run() // каждый middleware меняет Request через withContext()
→ $controller($request): Response // DI-resolved invokable
→ $response->withHeaders(corsHeaders())->emit()
)
→ HttpApplication::terminate() // хук для закрытия ресурсов (сейчас пустой)
→ gc_collect_cycles()
→ если !$keepRunning или достигнут MAX_REQUESTS — выход из цикла
Карта компонентов
| Файл | Класс | Роль |
|---|---|---|
src/Kernel.php |
Kernel |
Статический bootstrap, хранит контейнер |
src/Environment.php |
Environment |
Читает APP_ENV, метод isProd() |
src/Config.php |
Config |
Загружает config/*.php, deep-merge с env-оверрайдами; get('a.b.c') |
src/ContainerFactory.php |
ContainerFactory |
Строит PHP-DI контейнер; в prod включает compilation |
src/Http/WorkerRunner.php |
WorkerRunner |
Цикл FrankenPHP, MAX_REQUESTS, gc |
src/Http/HttpApplication.php |
HttpApplication |
CORS, роутинг, dispatch, обработка исключений |
src/Http/Request.php |
Request |
Иммутабельный; body(), get(key), withContext() |
src/Http/Response.php |
Response |
json(), error(), withHeader(), emit() |
src/Http/Router.php |
Router |
Regex-компиляция маршрутов, возвращает RouteMatch |
src/Http/MiddlewarePipeline.php |
MiddlewarePipeline |
Последовательно прогоняет middleware через DI |
src/Http/RouteDefinition.php |
RouteDefinition |
method, path, controller, middleware[] |
src/Http/HttpException.php |
HttpException |
Выбрасывается из любого места → Response::error |
src/Auth/AuthMiddleware.php |
AuthMiddleware |
Bearer JWT → AuthContext в request |
src/Auth/JwtService.php |
JwtService |
HS256, issue/verify, lcobucci/jwt |
src/Log/StdoutLogger.php |
StdoutLogger |
JSON → stdout, PSR-3 |
src/Log/FileLogger.php |
FileLogger |
JSON → файл (если LOG_FILE задан) |
src/Orm/AbstractMongoRepository.php |
AbstractMongoRepository |
persist/findById/delete/findOneWhere |
src/Orm/MongoHydrator.php |
MongoHydrator |
hydrate/dehydrate, поддержка Embedded/EmbeddedList |
src/ExceptionHandler.php |
ExceptionHandler |
Ловит Throwable вне dispatch (critical лог) |
Обработка исключений в dispatch
В HttpApplication::dispatch() ловятся:
AuthException→ 401HttpException→ код из исключения\JsonException→ 400 (невалидный JSON body)\Throwable→ логируется, 500
Исключения, вылетающие за пределы handleRequest() (т.е. до/после dispatch), ловит ExceptionHandler в WorkerRunner.