Determine REST POST/PUT request format - php

I'm developing a REST CodeIgniter Controller and need to POST and PUT to a URL in multiple formats.
The main formats I can think of would be:
XML
JSON
HTML Form data
There will be a response format defined in the URI e.g. /format/xml or /format/csv.
I don't want to have to define the request format in the URI as well.
I was wondering if anyone has any suggestions on finding out the request format so my script can complete the request.
I'm thinking it may be possible to get this data from the request headers "content-type"?
"content-type: text/xml" = XML
"content-type: application/json" = JSON
"content-type: text/plain" = HTLM Form data **i think!*
Would this method be robust or are there better approaches out there?
Thanks.

The content-type is the correct way to get the information you want.
Just make sure to throw an exception with some feedback and the correct http error code if the client calls it on the wrong format or do not pass the content-type header (you could also assume one content-type as default)
Also, you don't really have to use format/format_of_the_response . A better way would be to use the header Accept on the same way you use the header content-type

That method is robust as long as you know the your REST client will follow your content-type rule. If you control the client then this is fine. If you don't control the client then how acceptable is failure of the call when an unusual (or no) content-type is passed in?
Oh and for reference HTML form data has a content type of 'application/x-www-form-urlencoded'

I know this has been answered, but Phil Sturgeon wrote a REST Client and REST Server Library for codeigniter, might help you out a little bit.
http://github.com/philsturgeon/codeigniter-restclient

Related

amzon SP-API ,The request signature we calculated does not match the signature you provided

Errors appear when I encrypt and upload the feed data
the document link :https://github.com/amzn/selling-partner-api-docs/blob/main/guides/use-case-guides/feeds-api-use-case-guide-2020-09-04.md#step-2-encrypt-and-upload-the-feed-data
I develop in php,and the composer is composer require double-break/spapi-php
$feeder = new Feeder();
$feeder->uploadFeedDocument($docPayload, 'text/plain; charset=utf-8',
//ROOT_PATH.'uploads/amz/'.$feedFileName
'https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_4_1/OrderAcknowledgement.xsd'
);
Errors appear when I encrypt and upload the feed data:
Make sure content type you pass to createFeedDocument matches exactly the content type you pass to Feeder::uploadFeedDocument. In my case I was passing text/tab-separated-values to the former but text/tab-separated-values; charset=UTF-8 to the latter (with charset appended) and was getting the error you're describing. I fixed it by passing text/tab-separated-values; charset=UTF-8 in both instances.
I agree with this comment https://stackoverflow.com/a/67474344/12360781
But a more elaborative answer would be that we should pass these headers to the PUT request and of course the content-type should be the same as we passed to CreateFeedDocument operation.
{"Content-Type": "text/tab-separated-values; charset=UTF-8"}
This piece of code worked for me in Ruby:
faraday_connection = Faraday::Connection.new(#url)
#response = faraday_connection.send(:put, nil, #data.to_json, { "Content-Type": "text/tab-separated-values; charset=UTF-8" })
I had the same issue and after spending three days searching for the solution at last I come up with the following solution although I was using the Github C# sdk but the error was the same.
I was missing two important header required and after providing them fixed the issue for me.
Following is the code (C#)
restRequest.AddOrUpdateHeader("Content-Type", "application/json");
restRequest.AddOrUpdateHeader("User-Agent", "XXXX 2022");
Best of Luck!!!

Handle utf-8 format posted data

My c++ desktop application is posting data to my server with the charset=UTF-8 format (specified in my HTTP request headers). My php script analysing the posted data is not reading _POST correctly.
Does my script need to manually decode the posted data? I thought if the HTTP post request specified the charset that the script/php will automatically figure it out?
foreach($_POST as $key => $value)
{
$contents .= $key . ", " . $value . "\r\n";
}
// contents = n, J o h n D o e
// when it should = name, John Doe\r\nuserid, hithere\r\n
I thought if the HTTP post request specified the charset that the script/php will automatically figure it out?
No, character encoding is a lower layer. First of all, you need to let PHP know about the Content-Type of the data that you are sending it.
Check the manual on $_POST, it says:
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
For HTTP file upload you would use the latter, for other "normal" form data (text fields, anything basically that sends string data) the first one.
And of course your script will have to send the data encoded according to the chosen Content-Type. Whatever HTTP library you are using should provide methods to handle that; I'd recommend a look in the docuentation if you're not sure.
That would be the way to do it, as far as emulating HTML forms goes. If that is not your goal, your other option would be to send the data encoded in any format you chose, like f.e. JSON (or maybe even not treated any special way at all), and then read the raw input using file_get_contents and the php://input stream wrapper.

laravel 4 why send content-type when sending json?

In the book of laravel I read, and also my co-worker who has experience with laravel said that generating JSON I should in laravel way.
Why do I need to do this:
Route::get('markdown/response', function()
{
$data = array('iron', 'man', 'rocks');
return Response::json($data);
});
As I read it sends also content-type header when using this.
When I was using codeigniter I used to do simply this:
echo json_endode($data);
and never ever ever had any problems. Even if it is not set content type. Actually I dont know maybe php sets it automatically, but since I did not have problems, I did not care.
And when using 'new' technology I really want to know why it is better than good old one.
With respect, by not providing a content-type header, you were doing it "wrong" when coding in CodeIgniter.
Most clients (browsers, ajax requests, especially jQuery) can still can guess how to handle the response correctly and so probably "just worked" for you. You were likely always implicitly returning a Content-Type: text/html with your response, which is a default header in CodeIgniter.
You should always return a proper content type with your HTTP responses so the consuming client knows how to treat this content. Note that this is a mechanism of HTTP as defined in specification, not specific to any framework or even a language.
Response::json()
The above code is just a convenience function, where Laravel will automatically set the application/json header for you, as well as convert an array of data into JSON format. The only effective difference from your CodeIgniter code is the setting of the header, as you've pointed out.
It's worth noting that the Response object extends Symfony's response object, which is very "powerful" - in other words, it's a very good implementation of the HTTP protocol.
The response object returned from Response::json (and other Response static methods) are highly modifiable.
$response = Response::json($data);
$response->header('Content-Type', 'application/json');
return $response;
You can check for more available methods in the Laravel and Symfony code API.
http://laravel.com/api/class-Illuminate.Http.Response.html
http://api.symfony.com/2.1/Symfony/Component/HttpFoundation/Response.html
Just because it worked doesn't mean it wasn't wrong. JSON isn't HTML, so text/html is an inaccurate Content-Type for it.
Sending the correct header means libraries like jQuery understand what sort of data they're getting back, and thus are able to handle it on their own without guidance. Browsers may also do things like pretty-printing the JSON data or making it otherwise easier to read.
Depends what you are trying to do with the route. if you only want to return json data you can just return json_encode($data) and that will work, To actually return a json response for use with something like an ajax request you need the headers set properly or the accepting route just thinks its getting a string. Response::json is for setting the response which sets the headers appropriately.

slim php (explanation of "request body" documentation)

I am working with Slim PHP for the first time and I am trying to understand one of the concepts. In the slim PHP documentation, it states:
Request Body
Use the request object’s getBody() method to fetch the raw HTTP request body sent by the HTTP client. This is particularly useful for Slim application’s that consume JSON or XML requests.
<?php
$request = $app->request();
$body = $request->getBody();
My question is, what is "the raw HTTP request body"? Is it just a string of all the HTML in the body of the page? What format is it stored as? What would echo $body look like? If I do var_dump($body) I get string(0)"". How do I use it?
I'll just make it an answer rather than comment...
Raw request data is what's submitted from the browser as a body of the POST request.
http://en.wikipedia.org/wiki/POST_%28HTTP%29#Use_for_submitting_web_forms
Technically it can be used to read the data from usual html forms, but this doesn't make much sense as PHP does this good enough and places everything into $_POST.
You may need to read raw data if you have some javascript that sends XML or JSON data, which is not natively accepted by PHP.
The terms you ask for are defined in the RFC2616: Hypertext Transfer Protocol -- HTTP/1.1.
For example, in particular what a Message (Request/Response) Body is: 4.3 Message Body.
If those RFCs are new to you, grab that one an read it from top to bottom and try to understand as much as possible. You'll start to see how those things in the internet work.
Also there is version 2.0 is in the pipe with some changes:
Hypertext Transfer Protocol version 2.0 (Draft 04)
Just in case you're interested.

URL encoding seems to get in the way of properly json encoding/decoding in my PHP program

I'm implementing a PHP script which receives an HTTP POST message with in the body a json string, tied to a 'report' parameter. So HTTP POST report=.
I'm testing this out with SimpleTest (PHP Unit Testing).
I build the json:
$array = array("type" => "start"); // DEBUG
$report = json_encode($array);
I send the POST:
$this->post(LOCAL_URL, array("report"=>$json));
(calls a method in the WebTestCase class from SimpleTest).
SimpleTest says it sends this:
POST /Receiver/web/report.php HTTP/1.0
Host: localhost:8888
Connection: close
Content-Length: 37
Content-Type: application/x-www-form-urlencoded
report=%7B%22type%22%3A%22start%22%7D
I receive as such:
$report = $_POST['report'];
$logger->debug("Content of the report parameter: $report");
$json = json_decode($report);
The debug statement above gives me:
Content of the report parameter: {\"type\":\"start\"}
And when I decode, it gives the error
Syntax error, malformed JSON
The 'application/x-www-form-urlencoded' content-type is automatically selected by SimpleTest. When I set it to 'application/json', my PHP script doesn't see any parameters and as such, can't find the 'report' variable.
I suppose something is going wrong with the url encoding, but I'm lost here as to how I should get the json accross.
Also, what is the usual practice here? Does one use the key/value approach even if you just send an entire json body? Or can I just dump the json string in the body of the HTTP POST and read it out somehow? (I had no success in actually reading it out without a variable to point to).
Anyway, I hope the problem is somewhat clearly stated.
Thanks a bunch in advance.
Dieter
It sounds like you have magic quotes enabled (which is a big no-no). I would suggest you disable this, otherwise, run all your input through stripslashes().
However, it is better practice to reference the POST data as a key/value pair, otherwise you will have to read the php://input stream.
For the quick fix, try:
$report = stripslashes($_POST['report']);
Better, disable magic quotes GPC. G=Get, P=Post, C=Cookie.
In your case Post. Post values get automatically ("magic") quoted with a single slash.
Read here how to disable magic quotes.

Categories