简体   繁体   中英

Fosrestbundle body empty when multipart request

In the code bellow I expect the $request->getContents() to get the body content of the HTTP request. When sending non multipart request this works as expected though when using multipart requests the $body variable remains empty.

public function postDebugAction(Request $request) {
    $body = $request->getContent();

    if (empty($body)) {
        throw new \Exception('Body empty.');
    }


    return $this->view(array(), 201);
}

After reading this question and answer I added a body listener aswell.

<?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));
    }

}

According to my PHPUnit test this was working though when using Postman and Advanced Rest Client to simulate the request the body seems to be empty again. I double checked this to run both the simulate requests as PHPUnit with the debugger. Result is that, indeed, the body is empty when simulated via a Rest client and not empty when ran through PHPUnit.

The test case I used:

POST url:

http://localhost/EntisServer/web/app_dev.php/api2/debug

Headers:

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--

UPDATE I was uncertain whether I stepped through the debugger without using the BodyListener . When I did the result is exactly the same. So, without the BodyListener the PHPUnit case gets the body though the simulated request is still empty.

See php:// wrappers on php.net:

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.

So update your PHP version or make sure you only read the input once.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM