Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel doesn't read HTTP request payload for PUT request

So I am stumbling a bit here, as I have figured out that PHP will not read the HTTP request body from a PUT request. And when the Content-Type header in the request is set to application/json, there doesn't seem to be any way to get the body.

I am using Laravel, which builds their request layer on top of Symfony2's HttpFoundation lib.

I have debugged this a bit with jQuery, and these are some example requests:

Doing a request like this, I can find the content through Input::getContent()

$.ajax({ 
    url: 'http://api.host/profiles/12?access_token=abcdef', 
    type: 'PUT', 
    data: {"profiles":[{"name":"yolanda ellis","email":"[email protected]"}]} 
});

I cannot get the content with file_get_contents('php://input') though. jQuery per default sends the data as application/x-www-form-urlencoded.

It becomes even more mindboggeling when I pass another Content-Type in the request. Just like Ember-Data does:

$.ajax({ 
    url: 'http://api.host/profiles/12?access_token=abcdef', 
    type: 'PUT', 
    data: {"profiles":[{"name":"yolanda ellis","email":"[email protected]"}]},
    contentType: 'application/json' 
});

The data seems nowhere to be found, when doing it like this. This means that my Ember.js app does not properly work with my API.

What on earth is going on here?

Edit

Here's a full request example as seen in Chrome DevTools: http://pastebin.com/ZEjDAsmJ

I have found that this is a Laravel specific issue.

Edit 2: Answer found

It appears that there's a dependency in my project, which reads from php://input when the Content-Type: application/json header is sent with the request. This clears the stream—as pointed out in the link provided by @Mark_1—causing it to be empty when it reaches Laravel.

The dependency is bshaffer/oauth2-server-php

like image 958
Ronni Egeriis Persson Avatar asked Aug 19 '14 15:08

Ronni Egeriis Persson


People also ask

What is request -> input () in laravel?

input() is a method of the Laravel Request class that is extending Symfony Request class, and it supports dot notation to access nested data (like $name = $request->input('products.0.name') ).

Is request payload same as request body?

What I wanted to know is whether a request payload and request body mean the same thing? No, they have different meanings. A payload (a.k.a. content) is a part of representation data while a body is a part of a message, which are two different HTTP concepts.

How do you find the payload of a request?

The simplest way to analyze the payload is to enable the network-monitoring tool of the browser, and capture the network traffic of HTTP requests. With this tool you can see: how many HTTP requests the browser is sending to the server.

What is HTTP request payload?

The payload of an HTTP request or response consists of HTTP protocol information such as headers, a URL, body content, and version and status information.


2 Answers

You should be able to use Input::json() in your code to get the json decoded content.

I think you can only read the input stream once, so if a different package read the input stream before you, you can't access it.

Are you using OAuth2\Request::createFromGlobals() to create the request to handle your token? You should pass in the existing request object from Laravel, so both have access to the content. Did you read this? http://bshaffer.github.io/oauth2-server-php-docs/cookbook/laravel/ That links to https://github.com/bshaffer/oauth2-server-httpfoundation-bridge which explains how to create a request object from an httpfoundation request object (which Laravel uses).

Something like this:

$bridgeRequest = \OAuth2\HttpFoundationBridge\Request::createFromRequest($request);
$server->grantAccessToken($bridgeRequest, $response);

So they both share the same content etc.

like image 102
Barryvdh Avatar answered Oct 19 '22 15:10

Barryvdh


I found the following comment at http://php.net/manual/en/features.file-upload.put-method.php

PUT raw data comes in php://input, and you have to use fopen() and fread() to get the content. file_get_contents() is useless.

Does this help?

like image 3
Mark_1 Avatar answered Oct 19 '22 13:10

Mark_1