Разделить маршруты GET и HEAD в symfony

185
11 декабря 2019, 06:40

В моем приложении необходимо реализовать различную логику для GET и HEAD запросов. По HEAD внешняя система должна получить 200 или 404 в зависимости от существования документа. Если документ существует, то внешняя система перенаправляет пользователя по тому же адресу, где уже открывается полноценная страница с авторизацией и т.д.

Но, как оказалось, в symfony запросы HEAD заменяются на GET Unacessible routes in prod because HEAD request becomes GET #21074

Т.е. при запросе HEAD в контроллере:

class MyController extends AbstractController
{
    /**
     * @Route("/document/{id}", methods={"GET"}, requirements={"id"="\d+"})
     * @return Response
     */
    public function getAction(string $id): Response
    {
        return $this->render('default/index.html.twig');
    }
    /**
     * @Route("/document/{id}", methods={"HEAD"}, requirements={"id"="\d+"})
     * @return Response
     */
    public function headAction(string $id): Response
    {
        return new Response('', Response::HTTP_NOT_FOUND);
    }
}

выполнится getAction. Можно ли изменить такое поведение в конфигурации? Иначе в голову ничего не приходит кроме проверки REQUEST_METHOD:

/**
 * @Route("/cabinet/{id}", methods={"GET"}, requirements={"id"="\d+"})
 * @param string $id
 * @param Request $request
 * @return Response
 */
public function getAction(string $id, Request $request): Response
{
    if($request->server->getAlpha('REQUEST_METHOD') === 'HEAD') {
        return new Response('', Response::HTTP_NOT_FOUND);
    }
    return $this->render('default/index.html.twig');
}
Answer 1

Если коротко, то нельзя разделить.

Symfony исходят из RFC7231

Метод HEAD идентичен GET за исключением того, что сервер НЕ ОТПРАВЛЯЕТ тело сообщения в ответе.

HEAD может повлиять на ранее кэшированные GET-ответы RFC7234 (тут описан механизм Freshening Responses для HEAD).

Этот вопрос поднимался несколько раз (раз, два, три, четыре) и так и заглох как я понял.

Думаю, можно попробовать вытащить метод из $this->context->getMethod()

Ну и соответсвенно изменить контроллер

 /**
 * @Route("/cabinet/{id}", methods={"GET", "HEAD"}, requirements={"id"="\d+"})
 * @param string $id
 * @param Request $request
 * @return Response
 */
public function getAction(string $id, Request $request): Response
{
    if($this->context->getMethod() === 'HEAD') {
        return new Response('', Response::HTTP_NOT_FOUND);
    }
    return $this->render('default/index.html.twig');
}
READ ALSO
PHP: Поиск части слова в строке

PHP: Поиск части слова в строке

Есть строка со списком словЕсть определенное слово, которое нужно найти в этой строке

188
Ошибка при обновлении ядра Drupal

Ошибка при обновлении ядра Drupal

Обновил ядро друпал с версии 764, на версию 8

205
SQL limit несколько условий [дубликат]

SQL limit несколько условий [дубликат]

коллеги помоги правильно написать запрос столкнулся с проблемой что нужно вывести определенно количество записей с определенным параметром...

209
Как перенаправлять запросы с сервера?

Как перенаправлять запросы с сервера?

Как перенаправлять запросы с помощьюhtaccess и сделать исключение

201