Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get HTTP Request body content in Laravel?

I am making an API with Laravel 5 and I'm testing it with PHPUnit. I need to test legacy functionality for compatibility, which is an XML POST. As of right now, my first test looks like:

public function testPostMessages()
{
    $response = $this->call('POST', 'xml');

    $this->assertEquals(200, $response->getStatusCode());
}

This is passing just fine. Next on my list is actually sending the XML data with the POST. So for my second test, I have:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'xml');

    $this->assertTrue(is_valid_xml($response->getContent()));
}

This test fails. However, I am not sending my XML data. How do I send my XML?
Now, after that I need to add in the functionality to get the content from the request. I know there is a Request object that I can interact with but I don't exactly know which method to call on it. How do I get my XML from inside my controller?


Update #1

I was able to get some results in the meantime. My current test looks like this:

public function testPostMessagesContent()
{
    $response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));
    $this->assertContains('~', $response->getContent());
}

I only have the tilde there because I know it won't match so that I can see the whole response. In XmlController.php I have:

class XmlController extends Controller {
public function index(Request $request)
{
    return $request;
    }
}

My output from PHPUnit is as follows:

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 "~".

Where are my parameters and my content? I feel like I am simply just using call() incorrectly.


Update #2

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. If I use Request::getContent() I get back a blank string. Here's my call in the test:

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

Here's my test results:

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

Update #3

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.


Answer Criteria

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?
like image 637
beznez Avatar asked Feb 11 '15 16:02

beznez


People also ask

How do I get request body from post request?

To retrieve the body of the POST request sent to the handler, we'll use the @RequestBody annotation, and assign its value to a String. This takes the body of the request and neatly packs it into our fullName String. We've then returned this name back, with a greeting message.

How do you get parameters in laravel?

Laravel routes are located in the app/Http/routes. For instance, to pass in a name parameter to a route, it would look like this. Route::get('/params/{name}', function ($name) { return $name }); By convention, the Controller function accepts parameters based on the parameters provided.

How can you retrieve the full URL for the incoming request laravel?

The “path” method is used to retrieve the requested URI. The is method is used to retrieve the requested URI which matches the particular pattern specified in the argument of the method. To get the full URL, we can use the url method.


4 Answers

Inside controller inject Request object. So if you want to access request body inside controller method 'foo' do the following:

use Illuminate\Http\Request;

    public function foo(Request $request){
        $bodyContent = $request->getContent();
    }
like image 95
gandra404 Avatar answered Oct 19 '22 22:10

gandra404


You can pass data as the third argument to call(). Or, depending on your API, it's possible you may want to use the sixth parameter.

From the docs:

$this->call($method, $uri, $parameters, $files, $server, $content); 
like image 22
Jason McCreary Avatar answered Sep 21 '22 23:09

Jason McCreary


For those who are still getting blank response with $request->getContent(), you can use:

$request->all()

e.g:

public function foo(Request $request){
   $bodyContent = $request->all();
}
like image 5
user3785966 Avatar answered Oct 19 '22 23:10

user3785966


I don't think you want the data from your Request, I think you want the data from your Response. The two are different. Also you should build your response correctly in your controller.

Looking at the class in edit #2, I would make it look like this:

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

Once you've gotten that far you should check the content of your response in your test case (use print_r if necessary), you should see the data inside.

More information on Laravel responses here:

http://laravel.com/docs/5.0/responses

like image 5
delatbabel Avatar answered Oct 19 '22 22:10

delatbabel