php - 多部分请求时 Fosrestbundle 主体为空

标签 php rest symfony phpunit 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);
}

看完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 测试,这在使用 PostmanAdvanced 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/

相关文章:

php - 表单未向查询字符串发送任何数据

javascript - 如何减少从 PHP 获取信息的带宽大小?

php - 如何在包含的 SQL 查询中使用 Twig 循环值

php - 如何编写一个函数来告诉我当前正在查看主页(/index.php)?

asp.net-mvc - 走哪条路 - MVC REST 还是 WCF REST?

Java:从InvocationContext获取拦截器的注解参数

iphone - 保护 iPhone (iOS)/服务器通信

php - 如何在提交之前预先检查不同 sql 表中的表单值 - symfony

php - Symfony2 自定义学说请求

php - 当我将它们留空时,Woocommerce 自定义字段不会更新,并且仍然显示空字段