Тело Fosrestbundle пусто при многочастном запросе
В коде ниже я ожидаю $request->getContents()
чтобы получить содержание тела HTTP
запрос. При отправке не составного запроса это работает, как и ожидалось, хотя при использовании составных запросов $body
переменная остается пустой.
public function postDebugAction(Request $request) {
$body = $request->getContent();
if (empty($body)) {
throw new \Exception('Body empty.');
}
return $this->view(array(), 201);
}
Прочитав этот вопрос и ответ, я также добавил слушателя тела.
<?php
namespace VSmart\ApiBundle\Listener;
use FOS\RestBundle\EventListener\BodyListener as BaseBodyListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use FOS\RestBundle\Decoder\DecoderProviderInterface;
class BodyListener extends BaseBodyListener {
/**
* @var DecoderProviderInterface
*/
private $decoderProvider;
/**
* @param DecoderProviderInterface $decoderProvider Provider for fetching decoders
*/
public function __construct(DecoderProviderInterface $decoderProvider) {
$this->decoderProvider = $decoderProvider;
}
/**
* {@inheritdoc}
*/
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
if (strpos($request->headers->get('Content-Type'), 'multipart/form-data') !== 0) {
return;
}
$format = 'json';
if (!$this->decoderProvider->supports($format)) {
return;
}
$decoder = $this->decoderProvider->getDecoder($format);
$iterator = $request->request->getIterator();
$request->request->set($iterator->key(), $decoder->decode($iterator->current(), $format));
}
}
Согласно моему тесту PHPUnit это работало, хотя при использовании Postman
а также Advanced Rest Client
для имитации запроса тело снова кажется пустым. Я дважды проверил это, чтобы запустить оба запроса на симуляцию как PHPUnit с отладчиком. Результатом является то, что, действительно, тело пусто при моделировании через клиент Rest и не пусто при запуске через PHPUnit.
Тестовый пример, который я использовал:
POST URL:
http://localhost/EntisServer/web/app_dev.php/api2/debug
Заголовки:
Authorization: Bearer ZGYzYjY1YzY4MGY3YWM3OTFhYTI4Njk3ZmI0NmNmOWZmMjg5MDFkYzJmOWZkOWE4ZTkyYTRmMGM4NTE1MWM0Nw
Content-Type: multipart/form-data; boundary=-----XXXXX
Содержание:
-----XXXXX
Content-Disposition: form-data; name="json"
Content-Type: application/json; charset=utf-8
{
"blabla": 11
}
-----XXXXX
Content-Disposition: form-data; name="q_3101"; filename="image.jpg"
Content-Type: image/jpeg
contents of a file...
-----XXXXX--
ОБНОВЛЕНИЕ Я был не уверен, прошел ли я отладчик без использования BodyListener
, Когда я сделал, результат точно такой же. Итак, без BodyListener
случай PHPUnit получает тело, хотя моделируемый запрос все еще пуст.
2 ответа
Вы можете найти ваши загруженные файлы в $request->files->all()
после fos_rest.decoder_provider
декодирования.
Увидеть php://
фантики на php.net:
Примечание: до PHP 5.6 поток, открытый с помощью php://input, мог быть прочитан только один раз; поток не поддерживает операции поиска. Однако, в зависимости от реализации SAPI, может быть возможно открыть другой поток ввода php: // и возобновить чтение. Это возможно только в том случае, если данные тела запроса были сохранены. Как правило, это касается запросов POST, но не других методов запроса, таких как PUT или PROPFIND.
Поэтому обновите свою версию PHP или убедитесь, что вы читаете ввод только один раз.