在下面的代码中,我希望 $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);
}
看完this问答 我还添加了一个 body 监听器。
<?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 运行时,正文不是空的。
我使用的测试用例:
发布网址:
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 案例会获取主体,尽管模拟请求仍然是空的。
最佳答案
请参阅 php.net 上的 php://
包装器:
Note: Prior to PHP 5.6, a stream opened with php://input could only be read once; the stream did not support seek operations. However, depending on the SAPI implementation, it may be possible to open another php://input stream and restart reading. This is only possible if the request body data has been saved. Typically, this is the case for POST requests, but not other request methods, such as PUT or PROPFIND.
因此请更新您的 PHP 版本或确保您只读取一次输入。
关于php - 多部分请求时 Fosrestbundle 主体为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28781823/