beznez's avatar

Get raw POST data

I have been looking all over the internet for the last few days to try to resolve this issue. I have just started building an API in Laravel 5. This API needs to be able to accept an XML POST. I started testing it with PHPUnit. Here is my original post. I did find a hopeful solution, which stated that deep down in the Symfony framework the Request object uses file_get_contents("php://input");. So, I cannot call this a second time in my project. I also resolved my namespace issue and so my controller looks like this:

class XmlController extends Controller
{
    public function index()
    {
        $content = Request::getContent();
        return $content;
    }
}

I implemented the suggested solution:

$request = Request::instance();
$content = $request->getContent();

My test was giving me just the headers:

1) XmlTest::testPostMessagesContent
Failed asserting that 'POST xml HTTP/1.1
Accept:          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
Content-Type:    application/x-www-form-urlencoded
Host:            localhost
User-Agent:      Symfony/2.X
' contains "~".

And after I implemented the solution, I get a blank string:

1) XmlTest::testPostMessagesContent
Failed asserting that '' contains "~".

How can I get the content of the Request?

0 likes
8 replies
beznez's avatar

Update: I updated my controller to use Request:all() like so:

class XmlController extends Controller
{
    public function index()
   {
        $content = Request::all();
        return $content;
    }
}

This returned my key-value pair, but not the content.

1) XmlTest::testPostMessagesContent
Failed asserting that '{"key":"value"}' contains "~".

Key-value pairs are good; it's progress. However, what I really need is the content since I'll be receiving that data in the content portion of the request.

beznez's avatar

@bestmomo If I use Request::getContent() I get back a blank string. Here's the call in my test:

$response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));

Here's my results:

1) XmlTest::testPostMessagesContent
Failed asserting that '' contains "~".
bestmomo's avatar

What do you get with :

Request::__toString()
beznez's avatar

The same header that I was receiving earlier:

1) XmlTest::testPostMessagesContent
Failed asserting that 'POST xml HTTP/1.1
Accept:          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
Content-Type:    application/x-www-form-urlencoded
Host:            localhost
User-Agent:      Symfony/2.X
' contains "~".
beznez's avatar

Update: I am not able to get the content body of an HTTP Request at all. Since XML wasn't working, I moved forward with the REST part of my API, which uses JSON. Here's one of my tests:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'messages', ['content' => 'content']);

    $this->assertEquals('saved!', $response->getContent());
}

This test passes. If I use curl, I get a successful call as well:

curl -X POST -d "content=my_new_content" "http://localhost:8000/messages"

This returns 'saved!' That's awesome, but if I try to use curl in a standalone PHP script (to simulate a client), this is what is returned:

Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 302 [header_size] => 603 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.063977 [namelookup_time] => 0.000738 [connect_time] => 0.000866 [pretransfer_time] => 0.000943 [size_upload] => 12 [size_download] => 328 [speed_download] => 5126 [speed_upload] => 187 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.057606 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63248 [redirect_url] => http://localhost:8000 [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) Redirecting to http://localhost:8000. 

This is my curl command adding the POST fields:

curl_setopt($ch, CURLOPT_POSTFIELDS, 'content=test');

It seems to me that POSTFIELDS is getting added to the body of the request. In this case, I still have the same problem. I am not able to get body content of my HTTP headers. After commenting out my validation, I get:

Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 200 [header_size] => 565 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.070225 [namelookup_time] => 0.000867 [connect_time] => 0.00099 [pretransfer_time] => 0.001141 [size_upload] => 12 [size_download] => 6 [speed_download] => 85 [speed_upload] => 170 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.065204 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63257 [redirect_url] => [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) saved!

So I have my 'saved!' message. Great! But, in my database now I have a blank row. Not great. It is still not seeing the body content, just the headers.

I'm looking for the answers to these questions:

  1. Why can't I get the body content of my request?
  2. How do I get the body content of my request?
akinyeleolubodun's avatar

I know this is a bit old but I would like to profer a solution that works

    public function index(Request $request)
    {
        $request_content = $request->getContent();
    }
1 like
chuck_wood's avatar

Using Laravel 5.5 here and $request->getContent() also only returns the empty string. Looking at the source, it seems that it's because it's trying to re-read php://input, which can only be read once. So, if anyone has any ideas, let me know!

Please or to participate in this conversation.