Symfony — Предоставление всех ответов API в соответствии с типом контента

маршруты.yaml

Каким бы ни был тип контента, я хочу, чтобы ответ был именно такого типа. Как мне это сделать?

Я хочу, чтобы это был ответ по типу контента. Я хочу сделать это глобально. Например; Если тип содержимого — json, ответ должен быть json. Если тип содержимого — XML, ответ должен возвращать XML. или если тип содержимого xxx, ответ должен возвращать xxx

Сама система должна автоматически определять тип возвращаемого значения в соответствии с типом содержимого. Возможно ли это в symfony? Потому что Symfony по умолчанию возвращает исключения в формате xml. Если пользователь API отправляет тип контента как json и получает исключение, он получает его как xml. Я не хочу этого.

Я могу написать _format json или xml. Но я хочу, чтобы это было динамично.

Должен ли тип ответа соответствовать типу из запроса? Или из конфигурации? В обоих случаях: почему бы не прочитать эти данные и не действовать соответствующим образом в своем коде?

Nico Haase 23.01.2023 14:49

Чтобы было ясно, вы не хотите поддерживать все возможные заголовки типов контента, верно? Вы, вероятно, хотите поддерживать только XML и JSON, я предполагаю?

Chris Haas 23.01.2023 15:05

Я хочу получить ответ точно в соответствии с типом контента. @КрисХаас

Akif Tezcan 23.01.2023 15:08

Пожалуйста, добавьте все пояснения к вашему вопросу, отредактировав его. Также поделитесь своими попытками решить проблему

Nico Haase 23.01.2023 15:17

Что не совсем понятно в моем вопросе. @NicoHaase Я хочу, чтобы это был ответ по типу контента. Я хочу сделать это глобально. Например; Если тип содержимого — json, ответ должен быть json. Если тип содержимого — XML, ответ должен возвращать XML. или если тип содержимого xxx, ответ должен возвращать xxx

Akif Tezcan 23.01.2023 15:25

Это четкое требование. Но что вы пытались выполнить его? Как выглядит ваш контроллер? Для этого вам нужно либо написать какой-то код, либо использовать любую внешнюю библиотеку, например ApiPlatform.

Nico Haase 23.01.2023 15:51

Вау, каждый возможный тип контента сам по себе является большой проблемой. CSV, EBCDIC, RTF и т. д., я не знаю, как вообще такое построить. Я говорю это иронично, потому что вы, вероятно, хотите ограничить свои результаты известным списком, а не «всем, что предоставляет клиент». Кроме того, возможно, стоит соблюдать заголовок Accept, если он есть.

Chris Haas 23.01.2023 16:10

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

Community 24.01.2023 08:00

@Community -Chris Hass -Nico Haase Система сама должна автоматически определять тип возвращаемого значения в соответствии с типом содержимого. Возможно ли это в symfony? Потому что Symfony по умолчанию возвращает исключения в формате xml. Если пользователь API отправляет тип контента как json и получает исключение, он получает его как xml. Я не хочу этого .. Это должно работать глобально. Я не хочу специально проверять блок кода

Akif Tezcan 24.01.2023 09:30

Думаю, никто не знает, как это исправить. Я осуждаю Симфони. Потому что Laravel предоставляет это автоматически. Он автоматически устанавливает тип возвращаемого значения в соответствии с типом содержимого.

Akif Tezcan 24.01.2023 09:33

Почему бы не проверить, как Laravel это делает? Их код открыт для чтения для всех

Nico Haase 24.01.2023 09:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
11
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проверьте, как HttpKernel обрабатывает ответ.


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

Вы должны написать подписчика/слушателя, чтобы преобразовать ваш ответ в нужный формат:


use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final class ResponseSubscriber implements EventSubscriberInterface
{
    public function __contstruct(private Request $request) {}

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::RESPONSE => 'onResponse',
        ];
    }

    public function onResponse(ResponseEvent $event): void
    {
        // Skip on internal requests. E.g. redirect
        if (!$event->isMainRequest()) {
            return;
        }

        $data = $event->getResponse();

        $requestedType = $this->request->headers->has('Accept')
            ? $this->request->headers->get('Accept')
            : 'application/json';

        $response = match ($requestedType) {
             'application/json' => $this->getJsonResponse($data),
             'application/xml' => $this->getXmlResponse($data),
             'text/html' => $this->getHtmlResponse($data),
             ...
             default => throw new \InternalException('Request type ' . $requestedType . ' is not supported'), // This better be checked on KernelEvents::REQUEST
        }

        $event->stopPropagation();
        $response->setResponse($response);
    }
}

Вы можете использовать XDebug для пошаговой отладки и посмотреть, куда перемещаются ваши данные ответа, чтобы лучше понять внутреннее устройство Symfony.

это глобальное решение? Я не думаю, что есть глобальное решение. Я не думаю, что это будет работать в системных исключениях Symfony.

Akif Tezcan 24.01.2023 11:39

Исключения, создаваемые системой, будут по-прежнему поступать в формате XML. Даже если глобального решения нет, этот код может работать в ответах, находящихся под нашим контролем. но в собственных ошибках системы content-type не будет возвращать входящий тип.

Akif Tezcan 24.01.2023 11:43

@AkifTezcan Хорошо, я понял ваши требования. Проверьте обновленный ответ с обработкой событий ответа

Justinas 24.01.2023 12:00

Нужно ли нам где-то определять класс Response Subscriber? Я должен куда-то указывать?

Akif Tezcan 24.01.2023 12:50

@AkifTezcan Это простой подписчик с обычным процессом. Вы можете изменить $this->request на $event->getRequest()

Justinas 24.01.2023 13:01

Другие вопросы по теме