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
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') ).
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.
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.
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.
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With