RESTful API help, confused with HTTP and XML responses - php

I am writing an API and have been reading tutorials etc from various sources. I am a little confused regarding responses. I have written a class that will send back a HTTP header response as well as an XML response. Is this correct or should I be using one or the other and not both? Also how to do I check the HTTP header response I send is correct? Im using PHP.
I have used the following tool to check the HTTP response:
http://www.seoconsultants.com/tools/check-server-headers-tool/
which says the response is HTTP/1.1 200 OK. However in my script I have set it as:
header(HTTP/1.1 401 Unauthorized);
Therefore which is correct? How can I check properly? Any ideas what is going wrong?
Many thanks in advance for your help.

Redbot http://redbot.org/ will give a very thorough analysis of your HTTP response to ensure you are compliant with the HTTP spec.
You would be well advised to read some introductory material on the HTTP protocol. It will make your life much easier.

In a restful service, you use the http methods get, put, post and delete, so the http header is there "included". The payload of such a method call can be formatted the way you like (it must be an existing mimetype!), so xml is possible, too! You have to divide between the response "metadata" and the response payload: the "metadata" is a http header, the payload is your xml string, so you have to send both! Otherwise, you would send an empty response :-)
In your request you have to define which data representation (in your case xml) should be used for the response. Have a look at this image (the left one ist restful).
But nevertheless it is a good idea to use a framework for this, like other answers say.

Are you writing this from scratch? if you are then use a common or popular framework as basis and concentrate to building your API methods and let the framework handle the delivery mechanism
http://inchoo.net/tools-frameworks/symfony2-rest/ and you can google for more samples

HTTP Headers could be any you like - let the client handle them. Client can use them to find out if the operation (request) finished successfully or not, if the service is available and other common useful stuff. Headers are correct if they are either pre-defined by protocol and contain valid data or they are defined by you (no validations needed).
XML, JSON or any other response is the data you want to tell the client. It may contain details on errors, the results of performed actions and so on.

I don't suggest you mess with the HTTP header response. Keep it always set to 200 OK, and send back the needed information in the XML response.
That way, the client has to worry only about the XML response. In case there was an HTTP error, such as 403 Forbidden, it would mean this is on the system level (sever configuration) rather than on the application layer itself.

Related

Get XML Response using CURL, FOPEN or FILE_GET_CONTENTS in PHP

I would like to create a PHP script that would perform a request to an https site using the GET method. In return, I get a response in xml format. I need to be able to get the contents/save this xml.
I've tried using curl, file_get_contents, fopen but I'm getting a Bad Request (400) response. But when I try to go directly to the url, I receive the xml response. Here's the url that I'm trying to get response with:
https://tst.webservices.outsurance.co.za/SecureHost/Lead/LeadPostService.svc/SubmitAffiliateLead?xml=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22+%3F%3E%0D%0A%0D%0A%3Clead%3E%0D%0A+++%3Cmode%3ELIVE%3C%2Fmode%3E%0D%0A%09%3Ctitle%3EMrs%3C%2Ftitle%3E%0D%0A%09%3Cfirstname%3EHannah%3C%2Ffirstname%3E%0D%0A%09%3Clastname%3EDwindle%3C%2Flastname%3E%0D%0A%09%3Cid%3E1723658492165%3C%2Fid%3E%0D%0A%09%3Chomecode%3E%3C%2Fhomecode%3E%0D%0A%09%3Chometel%3E%3C%2Fhometel%3E%0D%0A%09%3Cworkcode%3E011%3C%2Fworkcode%3E%0D%0A%09%3Cworktel%3E132189%3C%2Fworktel%3E%0D%0A%09%3Cmobile%3E0824176239%3C%2Fmobile%3E%0D%0A%09%3Cemail%3Ehannahdwindle#gmail.com%3C%2Femail%3E%0D%0A%09%3Ccomment%3ETHIS+IS+A+COMMENT%3C%2Fcomment%3E%0D%0A%09%3Csource%3EUPSTART%3C%2Fsource%3E%0D%0A%09%3Cnotes%3ETHIS+I+A+NOTE%3C%2Fnotes%3E%0D%0A%09%3Clanguage%3EE%3C%2Flanguage%3E%0D%0A%09%3Cproduct%3EP%3C%2Fproduct%3E%0D%0A%3C%2Flead%3E%0D%0A+++++++++
I really don't kknow what to do now. I have tried every solution that I've seen on the internet but to no avail.
I wrote this response a while back. It can give you way to debug your outgoing requests.
It looks like your http client is composing a request that the receiving application doesn't like. This can be on the application level too (maybe they just don't like your variables and are returning a 400 level response). I've seen API implementers do that. There's nothing to stop the implementers from doing that.
I'd find out what the exact request is that you're sending (by that link I provided) and contact the API implementers to ensure that they're expecting that type of request.
Also, with fiddler, you can craft http requests. However, the best way to craft requests to test remote APIs is to manage every byte. You can do that by using this method (supports both HTTP and HTTPS).
Lastly, I wrote an XML wrapper to make xml modification/querying easier, if it helps you at all.

Best Practice for Errors in RESTful API

What are the best practices for returning HTTP status codes in RESTful API? I am using Laravel 4 for my PHP framework.
In the case of an error, should I use
return Response::json('User Exists', 401);
or
include flag for success
return Response::json([
'success' => false,
'data' => 'User Exists'],
401
);
or
use 200 instead of 4xx, relying on success to determine if there is an error
return Response::json([
'success' => false,
'data' => 'User Exists'],
200
);
And in the case of success and there is no need to return any data, do you still return anything?
PHP API Code
public function getCheckUniqueEmail() {
// Check if Email already exist in table 'users'
$uniqueEmail = checkIfEmailExists();
// Return JSON Response
if($uniqueEmail) {
// Validation fail (user exists)
return Response::json('User Exists', 401);
} else {
// Validation success
// - Return anything?
}
}
When you look at the list of available HTTP status codes, you will at some point realize that there are plenty of them, but used alone they cannot really explain an error by itself.
So to answer your question, there are two parts. One is: How can your API communicate the reasons for an error and add useful information that the user of the API (which in most cases is another developer) can read and act upon. You should add as much information as possible, both machine readable and human readable.
The other part: How can HTTP status codes help in distinguish certain error (and success) states?
This latter part is actually harder than one might thing. There are the obvious cases where 404 is used to tell "not found". And 500 for any errors that are server-side.
I wouldn't use status 401, unless I really want to allow the operation to succeed if there are HTTP authentication credentials present. 401 usually triggers a dialog box in the browser, which is bad.
In case of a ressource being unique and already existing, status "409 Conflict" seems appropriate. And if creating a user succeeds, status "201 Created" sounds like a good idea, too.
Note that there are a lot more status codes, some of them related to extensions of the HTTP protocol (like DAV), some completely unstandardized (like status "420 Enhance your calm" from the Twitter API). Have a look at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes to see what has been used so far, and decide whether you want to use something appropriate for your error cases.
From my experience, it is easy to simply pick a status code and use it, but it is hard to do so consistently and in accordance with existing standards.
I wouldn't however stop here just because others might complain. :) Doing RESTful interfaces right is a hard task in itself, but the more interfaces exists, the more experience has been gathered.
Edit:
Regarding versioning: It is considered bad practice to put a version tag into the URL, like so: example.com/api/v1/stuff It will work, but it isn't nice.
But the first thing is: How does your client specify which kind of representation he wants to get, i.e. how can he decide to either get JSON or XML? Answer: With the Accept header. He could send Accept: application/json for JSON and Accept: application/xml for XML. He might even accept multiple types, and it is for the server to decide then what to return.
Unless the server is designed to answer with more than one representation of the resource (JSON or XML, client-selected), there really isn't much choice for the client. But it still is a good thing to have the client send at least "application/json" as his only choice and then return a header Content-type: application/json in response. This way, both sides make themselves clear about what they do expect the other side to see the content like.
Now for the versions. If you put the version into the URL, you effectively create different resources (v1 and v2), but in reality you have only one resource (= URL) with different methods to access it. Creating a new version of an API must take place when there is a breaking change in the parameters of a request and/or the representation in the response which is incompatible with the current version.
So when you create an API that uses JSON, you do not deal with generic JSON. You deal with a concrete JSON structure that is somehow unique to your API. You can and probably should indicate this in the Content-type sent by the server. The "vendor" extension is there for this: Content-type: application/vnd.IAMVENDOR.MYAPI+json will tell the world that the basic data structure is application/json, but it is your company and your API that really tells which structure to expect. And that's exactly where the version for the API request fits in: application/vnd.IAMVENDOR.MYAPI-v1+json.
So instead of putting the version in the URL, you expect the client to send an Accept: application/vnd.IAMVENDOR.MYAPI-v1+json header, and you respond with Content-type: application/vnd.IAMVENDOR.MYAPI-v1+json as well. This really changes nothing for the first version, but let's see how things develop when version 2 comes into play.
The URL approach will create a completely unrelated set of new resources. The client will wonder if example.com/api/v2/stuff is the same resource as example.com/api/v1/stuff. The client might have created some resources with the v1 API and he stored the URLs for this stuff. How is he supposed to upgrade all these resources to v2? The resources really have not changed, they are the same, the only thing that changed is that they look different in v2.
Yes, the server might notify the client by sending a redirect to the v2 URL. But a redirect does not signal that the client also has to upgrade the client part of the API.
When using an accept header with the version, the URL of the resource is the same for all versions. The client decides to request the resource with either version 1 or 2, and the server might be so kind and still answers version 1 requests with version 1 responses, but all version 2 requests with the new and shiny version 2 responses.
If the server is unable to answer to a version 1 request, he can tell the client by sending HTTP status "406 Not Acceptable" (The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.)
The client can send the accept header with both versions included, which enabled the server to respond with the one he likes most, i.e. a smart client might implement versions 1 and 2 and now sends both as accept header, and waits for the server to upgrade from version 1 to 2. The server will tell in every response whether it is version 1 or 2, and the client can act accordingly - he does not need to know the exact date of the server version upgrade.
To sum it up: For a very basic API with limited, maybe internal, usage even having a version might be overkill. But you never know if this will be true a year from now. It is always a very good idea to include a version number into an API. And the best spot for this is inside the mime type that your API is about to use. Checking for the single existing version should be trivial, but you have the option of transparently upgrading later, without confusing existing clients.
I wouldn't use 200 status for everything. That just would be confusing.
Jquery allows you to process different response codes differently, there are built in methods for that already so take advantage of using them in your apps and when your app grows you can provide that API for others to use too.
Edit:
Also I highly recommend watching this talk about Laravel and API development:
http://kuzemchak.net/blog/entry/laracon-slides-and-video
There are some list of HTTP Status Code at Illuminate\Http\Response that extend to Symfony\Component\HttpFoundation\Response. You can use that in your class.
For example:
use Illuminate\Http\Response as LaravelResponse;
...
return Response::json('User Exists', LaravelResponse::HTTP_CONFLICT);
It much more readable.

Should Rest API accept POST array or JSON string?

I've been reading a few REST tutorials and some of them says that in order to send data to a rest API you should send post data as an array, which is something like this:
$data = array('foo' => 'bar');
$rest->post($data);
Then there are others that say you should send JSON data like this:
$data = array('foo' => 'bar');
$data = json_encode($data);
$rest->post($data);
Not sure if there's a standard way of doing this or either if is fine but what is generally recommended when designing API's?
EDIT: There seems to be confusion. To clarify I agree JSON should be used for client consumption but this question is about SERVER consumption. Meaning should the SERVER accept JSON or POST data from its clients?
If you're the one creating the RESTful API, meaning your application is the server and is accepting requests, then your question seems confusing. Your application will not be sending any POST data; clients will be sending POST data to you.
With that being said, having an API which will accept JSON-encoded requests is possible, though would really only be useful for very niche scenarios. The vast majority of clients will be POSTing data to your API in the application/x-www-form-urlencoded format. PHP handles this behind the scenes for you, and exposes the data as the $_POST superglobal.
If you're talking about responding to POST requests, and what format you should use, then that will depend on what format the client wants you to send it in. The client will either specify this in the Accept header, or some APIs allow it to be specified in the URL (e.g. foo.com/some/thing/123.json or foo.com/some/thing/123/json). The client isn't required to tell your application what format it wants, so it's up to you to pick a sensible default. Most APIs will use JSON these days.
I've never heard of an API that understood serialized PHP array format, though, so I don't know what resources you've been reading, but I'm pretty sure you misunderstood what they were suggesting.
Actually, I think this is a pretty good question. don't know why it got downvoted.
Also, contrary to what I saw written in some comments, the client can use any language he wants, not only javascript. And it's not the server job to know which language was used to "build" the request, just that the request is valid. This makes more sense if you think that the entity making the request can actually be another server (think about a proxy server used to send post requests across domains).
That being said, personally, I think it's better for the server side to consume a XML or JSON. The main reason is validation.
It's easier to validate a XML or JSON against a schema.
Also the schema can be made public, and a well designed schema can describe webservice by itself. The client can even use the same schema to validate the request prior to sending it to the server.
Passing an url encoded form is also valid, of course. And can be validated server side as well. SO i think, down the road, it's just a matter of preference.
Also, check this discussion in SO, it regards the same topic:
JSON vs Form POST
You should think about the clients that will consume the API. A HTML5\AJAX client will probably want JSON data, while other clients (Silverlight or native mobile apps) might be better at consuming XML.
One great framework\platform for writing REST API's is looking to be Microsoft's Web API (based on ASP.NET MVC). The product succeeds the WCF framework and allows users to write REST API's in a MVC environment. One feature is that it chooses a serialization provider based on the HTTP Accept header.
So if a client Accepts application/json they work with the service in JSON and if the accept XML they work with the service in XML. You can also write your own object serializer and plug it into the framework.
More information: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/video-your-first-web-api
Most of the time you would want to stick to receiving POST data but I think receiving json data does have its uses for example when it comes to batch requests.
The Facebook API uses it.
You don't need to do file_get_contents('php//input'). From the facebook documentation you could just do something like this:
curl -X POST "http://example.com/batch" -d 'batch={ "param" : 1, "param2" : "2"}'
Then in the PHP code, if you're using PHP, you can get it through the $_POST parameter and do a json_decode.
var_dump($_POST);
array(1) {
["batch"]=>
string(30) "{ "param" : 1, "param2" : "2"}"
}
var_dump(json_decode($_POST['batch'], true));
array(2) {
["param"]=>
int(1)
["param2"]=>
string(1) "2"
}
JSON makes more sense, since it is language-independent and can be useful when API scales.
I am currently developing a REST API and I was asking myself the same question. After some research I found out that is no standard and is totally up to you.
You are developing the server side so you can decide how data should be sent to you. The client need to adapt to your design.
Personally I choose to receive all POST and PUT data as JSON directly in body.
The point is to reuse the HTTP implementation that already exists.
HTTP is built to accept many different content-types and you only need to specify which you are using in the headers.
A REST API that accepts the various formats and works off the content-type header is refreshing. You can submit x-www-form-urlencoded values from an HTML webpage or make an AJAX request with raw JSON and there is no confusion as long as everyone is following protocol.
As a developer you must choose the support your app will provide because you can't support everything. Typically it boils down to the support or convenience of your own environment -- nobody wants to reinvent the wheel.
Many frameworks that are designed with building APIs in mind, handle the most popular content types at a lower level. They may also encode the response data according to the "Accept" header.
Implement whatever you think will be used most first or find a framework that already speaks HTTP and takes care of all of that for you.

Difference between an Output of a normal API and a REST API

What is the difference between a REST API and a normal API (which prints a JSON response)?
There is no difference at all. REST describes a way of interacting with a HTTP server, not what the server should return in response. Most web apps interact with the server side by POST or GET requests with any additional information needed to fulfil the request in a form submission for POST or the query string for GET. So if you want to delete something from the server they typically do POST with a form that contains data that specifies a resource along with an instruction to delete it.
However, HTTP implements methods (also known as verbs) other than GET or POST. It also implements, amongst others, HEAD (return the same headers you would have done for a GET, but with no response body), PUT (Take the request body and store its content at whatever URL the PUT request was made to), and DELETE (Delete whatever resource exists at the specified URL). A REST interface simply makes use of these additional verbs to convay the meaning of the request to the server.
Browsers typically only support GET and POST for "normal" (non-XHR) requests, but tools like Curl can issue the full set of HTTP verbs. You can also use additional verbs with XHR-based techniques such as AJAX.
You will still have to provide a traditional non-REST API for browsers to use, unless you're making javascript and XHR support a requirement for using your app.
REST mostly just refers to using the HTTP protocol the way it was intended. Use the GET HTTP method on a URL to retrieve information, possibly in different formats based on HTTP Accept headers. Use the POST HTTP method to create new items on the server, PUT to edit existing items, DELETE to delete them. Make the API idempotent, i.e. repeating the same query with the same information should yield the same result. Structure your URLs in a hierarchical manner etc.
REST just is a guiding principle how to use URLs and the HTTP protocol to structure an API. It says nothing about return formats, which may just as well be JSON.
That is opposed to, for example, APIs that send binary or XML messages to a designated port, not using differences in HTTP methods or URLs at all.

Open Id XRDS Discovery

I am working with Open Id, just playing around making a class to interact / auth Open Id's on my site (in PHP). I know there are a few other Libraries (like RPX), but I want to use my own (its good to keep help better understand the protocol and whether its right for me).
The question I have relates to the Open Id discovery sequence. Basically I have reached the point where I am looking at using the XRDS doc to get the local identity (openid.identity) from the claimed identity (openid.claimed_id).
My question is, do I have to make a cURL request to get the XRDS Location (X-XRDS-location) and then make another cURL request to get the actual XRDS doc??
It seems like with a DUMB request I only make one cURL request and get the Open Id Server, but have to make two to use the XRDS Smart method. Just doesn't seem right, can anyone else give me some info.
To be complete, yes, your RP must HTTP GET on the URL the user gives you, and then search for an XRDS document reference and if found do another HTTP GET from there. Keep in mind that the XRDS may be hosted on a different server, so don't code up anything that would require the connection to be the same between the two requests since it might not be the same connection.
If in your initial HTTP GET request you include the HTTP header:
Accept: application/xrds+xml
Then the page MAY respond immediately with the XRDS document rather than an HTML document that you have to parse for an XRDS link. You'll be able to detect that this has occurred by checking the HTTP response header for application/xrds+xml in its Content-Type header. This is an optimization so that RPs don't typically have to make that second HTTP GET call -- but you can't rely on it happening.
The best advice I can give you, is to try to abstract your HTTP requesting a little bit, and then just go through the entire process of doing an HTTP request twice.
You can keep your curl instances around if you want to speed things up using persistent connections, but that may or may not be want you want.
I hope this helps, and good luck.. OpenID is one of the most bulky and convoluted web standards I've come across since WebDAV =)
Evert
I know I'm late to the game here, but I think you should also check out the webfinger protocol. It takes the standard "email as userid" pattern and lets you do a lookup from there to discover openid etc.

Categories