Как решить проблему дублирования Yii HTTP Client’ом тела ответа?

Проблема дублирования тела ответа при использовании Yii HTTP Client обычно возникает, когда при запросе веб-сервер возвращает ответ с несколькими заголовками Content-Type.

По умолчанию, Yii HTTP Client не поддерживает работу с несколькими заголовками Content-Type и парсит только первый заголовок. В результате, при наличии дублирующихся заголовков, тело ответа также дублируется.

Однако, существует несколько способов решить эту проблему:

1. Использование расширенного класса HttpClient: Можно создать собственный класс HttpClient, наследующий базовый класс Yii HTTP Client, и переопределить метод parseResponse. В переопределенном методе, можно проверять наличие нескольких заголовков Content-Type и выбрать первый уникальный. Пример:

use yiihttpclientClient;

class CustomHttpClient extends Client
{
    /**
     * @inheritdoc
     */
    protected function parseResponse($response)
    {
        $contentTypeHeader = $response->getHeaders()->get('Content-Type');
        if (count($contentTypeHeader) > 1) {
            // Выбираем первый уникальный заголовок
            $contentType = array_unique($contentTypeHeader);
        } else {
            $contentType = $contentTypeHeader;
        }

        // Заменяем оригинальный заголовок
        $response->getHeaders()->set('Content-Type', $contentType);

        return parent::parseResponse($response);
    }
}

После создания класса CustomHttpClient, можно использовать его для отправки запросов вместо стандартного HttpClient. Пример:

$client = new CustomHttpClient();
$response = $client->createRequest()
    ->setMethod('GET')
    ->setUrl('https://example.com')
    ->send();

2. Использование расширенного класса ResponseFormatter: Можно создать собственный класс ResponseFormatter, наследующий базовый класс Yii ResponseFormatter, и переопределить метод format. В переопределенном методе, можно проверять наличие нескольких заголовков Content-Type и выбрать первый уникальный. Пример:

use yiiwebResponseFormatterInterface;

class CustomResponseFormatter implements ResponseFormatterInterface
{
    /**
     * @inheritdoc
     */
    public function format($response)
    {
        $contentTypeHeader = $response->getHeaders()->get('Content-Type');
        if (count($contentTypeHeader) > 1) {
            // Выбираем первый уникальный заголовок
            $contentType = array_unique($contentTypeHeader);
        } else {
            $contentType = $contentTypeHeader;
        }

        // Заменяем оригинальный заголовок
        $response->getHeaders()->set('Content-Type', $contentType);
    }
}

После создания класса CustomResponseFormatter, можно зарегистрировать его в конфигурации приложения, чтобы Yii использовала его при форматировании ответов. Пример:

'response' => [
    'formatters' => [
        'custom' => [
            'class' => 'pathtoCustomResponseFormatter',
            'contentType' => 'application/json', // Задаем Content-Type, который нужен
        ],
    ],
    'acceptParams' => ['custom' => 'application/json'], // Задаем значение accept-param для использования созданного ResponseFormatter
    'class' => 'yiiwebResponse',
],

3. Использование стандартной функциональности Yii: Если дублирование тела ответа связано с конкретным веб-сервером или API, то можно обратиться к документации этого сервиса и узнать, какие заголовки Content-Type поддерживает сервер. Затем, в запросе к серверу можно указать конкретный Content-Type заголовок для получения только желаемого формата ответа.

Например, если веб-сервер поддерживает только JSON и XML, и вы хотите получить только JSON, то можно указать соответствующий заголовок в запросе:

$response = Yii::$app->httpclient->createRequest()
    ->setMethod('GET')
    ->setUrl('https://example.com/api')
    ->setHeaders([
        'Accept' => 'application/json',
    ])
    ->send();

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