PHP PHP  ·  30 вопросов  ·  ~85 мин  ·  ⏱ Таймер 25:00  ·  Сложный  · 

Middleware и конвейер запроса

Одна и та же прослойка ведёт себя по-разному в зависимости от позиции в цепочке. Тест требует проследить вход и выход через middleware, выбрать место для авторизации, журналирования и преобразования ошибок, не смешивая обязанности.

Отвечено: 0 из 30
⏱ --:--
0%
💡 Инструкция: Выберите один ответ из пяти. Нарисуйте цепочку вызовов туда и обратно и отметьте, кто может остановить обработку. На тест дано 85 минут.
Вопрос 1 из 30
Каков основной контракт PSR-15 middleware?
PHP
final class RequestIdMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        return $handler->handle($request);
    }
}
Вопрос 2 из 30
Что означает короткое замыкание?
PHP
if ($request->getHeaderLine('Authorization') === '') {
    return new JsonResponse(['error' => 'unauthorized'], 401);
}
return $handler->handle($request);
Вопрос 3 из 30
Почему next/handler нельзя вызывать дважды?
PHP
$first = $handler->handle($request);
$second = $handler->handle($request);
return $second;
Вопрос 4 из 30
Как измерить время всего внутреннего конвейера?
PHPPHP/PSR-15
$start=hrtime(true);
$response=$handler->handle($request);
$metrics->observe((hrtime(true)-$start)/1e9);
return $response;
Вопрос 5 из 30
Что лучше вынести из middleware авторизации?
Вопрос 6 из 30
Что делает withAttribute в неизменяемом request?
PHP
$requestWithUser = $request->withAttribute('user', $user);
return $handler->handle($requestWithUser);
Вопрос 7 из 30
Почему хранить currentUser в static-поле опасно для долгоживущего worker?
PHP
final class RequestContext
{
    public static ?User $currentUser = null;
}

RequestContext::$currentUser = $authenticatedUser;
Вопрос 8 из 30
Что лучше для request_id?
PHP
$requestId = $request->getHeaderLine('X-Request-Id');
if (!preg_match('/^[a-f0-9-]{16,64}$/i', $requestId)) {
    $requestId = bin2hex(random_bytes(16));
}
return $handler->handle($request->withAttribute('request_id', $requestId));
Вопрос 9 из 30
Как избежать конфликтов атрибутов?
Вопрос 10 из 30
Что произойдёт с атрибутом uid, если результат withAttribute() не передать дальше и продолжить использовать исходный request?
PHPPHP/PSR-15
$request->withAttribute('uid',42);
var_dump($request->getAttribute('uid'));
Вопрос 11 из 30
Где ставить middleware неожиданных ошибок?
PHP
try {
    return $handler->handle($request);
} catch (Throwable $error) {
    return $this->errors->toResponse($error);
}
Вопрос 12 из 30
Почему нельзя ловить Throwable и всегда возвращать 404?
PHP
try {
    return $handler->handle($request);
} catch (Throwable $error) {
    return new JsonResponse(['error' => 'not_found'], 404);
}
Вопрос 13 из 30
Что делать с деталями исключения?
PHP
try {
    return $handler->handle($request);
} catch (Throwable $error) {
    $eventId = bin2hex(random_bytes(8));
    $logger->error('Unhandled request error', ['event_id' => $eventId, 'exception' => $error]);
    return new JsonResponse(['error' => 'internal_error', 'event_id' => $eventId], 500);
}
Вопрос 14 из 30
Как обеспечить security headers на 500?
Вопрос 15 из 30
Что опасно в catch, который делает $handler->handle($request) повторно?
Вопрос 16 из 30
Каков вывод двух оборачивающих middleware?
PHPPHP/PSR-15
// A: before; handle(next); after
// B: before; handle(next); after
Вопрос 17 из 30
Где должен стоять routing относительно middleware, которому нужны route attributes?
PHP
$routed = $router->match($request);
$request = $request
    ->withAttribute('route', $routed->name)
    ->withAttribute('order_id', $routed->params['id'] ?? null);
return $authorization->process($request, $handler);
Вопрос 18 из 30
Кэш middleware стоит до auth и кэширует персональный ответ только по URL. Риск?
PHP
final class ResponseCacheMiddleware
{
    public function process(Request $request, Handler $handler): Response
    {
        $key = $request->path;
        return $this->cache->remember($key, fn () => $handler->handle($request));
    }
}
Вопрос 19 из 30
Почему CORS middleware часто должно охватывать error response?
Вопрос 20 из 30
Как проверить порядок без догадок?
Вопрос 21 из 30
Как изолированно тестировать middleware?
PHP
$next = new class implements RequestHandlerInterface {
    public int $calls = 0;
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $this->calls++;
        return new Response(204);
    }
};
$response = $middleware->process($request, $next);
Вопрос 22 из 30
Что проверять у auth middleware при отсутствии token?
PHP
$next = new CountingHandler();
$response = $auth->process($requestWithoutToken, $next);
assert($response->getStatusCode() === 401);
assert($next->calls === 0);
Вопрос 23 из 30
Как проверить добавленный user?
Вопрос 24 из 30
Зачем проверять исключение из следующего handler?
Вопрос 25 из 30
Как найти слой, добавляющий задержку?
Вопрос 26 из 30
Как обрабатывать X-Forwarded-For?
PHP
$remote = $request->getServerParams()['REMOTE_ADDR'] ?? '';
if (in_array($remote, $trustedProxies, true)) {
    $clientIp = parseForwardedFor($request->getHeaderLine('X-Forwarded-For'));
} else {
    $clientIp = $remote;
}
Вопрос 27 из 30
Где ставить лимит размера тела?
PHP
$length = (int) $request->getHeaderLine('Content-Length');
if ($length > 1_000_000) {
    return new JsonResponse(['error' => 'payload_too_large'], 413);
}
return $handler->handle($request);
Вопрос 28 из 30
Что должно происходить с метриками при коротком замыкании?
Вопрос 29 из 30
Почему security middleware нельзя исключать для 404?
Вопрос 30 из 30
Как безопасно обновлять pipeline?

Ответьте на все 30 вопросов, чтобы получить результат

🔗 Встроить тест на свой сайт (iframe) ▼

Скопируйте код и вставьте в любое место на вашем сайте:

Также доступна прямая ссылка на embed-страницу