Fosrestbundle在多部分请求时无法获取请求体。

3
在下面的代码中,我期望$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);
}

在阅读这个问题和答案后,我也添加了一个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模拟请求时,请求体似乎又变成了空的。我使用调试器验证了两种情况,结果是,通过Rest客户端模拟时,请求体确实为空,而通过PHPUnit运行时不为空。
我使用的测试用例如下:
POST url:
http://localhost/EntisServer/web/app_dev.php/api2/debug

标题:

Authorization: Bearer ZGYzYjY1YzY4MGY3YWM3OTFhYTI4Njk3ZmI0NmNmOWZmMjg5MDFkYzJmOWZkOWE4ZTkyYTRmMGM4NTE1MWM0Nw
Content-Type: multipart/form-data; boundary=-----XXXXX

Content:

-----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个回答

0

请参考php.net上的php://包装器:

注意:在PHP 5.6之前,使用php://input打开的流只能读取一次;该流不支持寻址操作。但是,根据SAPI实现的不同,可能可以打开另一个php://input流并重新开始读取。这仅在请求体数据已保存的情况下才可能发生。通常,这适用于POST请求,但不适用于其他请求方法,例如PUT或PROPFIND。

因此,请更新您的PHP版本或确保只读取输入一次。


0

fos_rest.decoder_provider 解码之后,您可以在 $request->files->all() 中找到您上传的文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接