I use Laravel as a REST API service for uploading and storing books.
The book service follows the standard REST convention:
GET: /api/books and /api/books/<book_id> for retrieving book(s)
PUT: /api/books/<book_id> for updating a book
POST: /api/books for adding a new book
DELETE: /api/books/<book_id> for deleting a book
So far so good.
Now I need another endpoint which should be used for creating a Zip file out of a book and some images. So the book is already on the server (in a database). The images need to be uploaded temporarily by the client and are NOT saved on the server. Then the images and the books are compressed and the resulting file is returned back to the client.
So I need an endpoint like /api/books/{book_id}/compress. When calling this endpoint, the client attaches the images in the request body.
How do I express that in a RESTful way?
Should that be a GET or POST request? This endpoint does not store anything on the server, so it should be a GET request from my point of view. But if it is GET, can I add images to the request body? Because that's actually supposed to be handled by POST requests.
But if it is GET, can I add images to the request body?
It's not a great idea...?
Here's what the current standard has to say about GET
Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics
A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported.
An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.
"No generally defined semantics" is kind of like "undefined behavior" - if something goes sideways, resulting in loss of property, the liability is going to be on you.
On the other hand: it is okay to use POST.
POST serves many useful purposes in HTTP, including the general purpose of "this action isn’t worth standardizing." -- Fielding, 2009
Today, we don't have a standardized HTTP method that combines safe semantics and a request payload.
But: there is a work in progress that is intended to support queries in the body of a request, and it may turn out that the same semantics can be used for transformations.
Funny you ask. I have had the same question once before and I remember someone telling me that a GET request originally does not have a request body. However I think (so I am not sure) it was still possible. Unfortunately I am unable to find that example.
According to the w3 documentation the POST request can be used for the following:
Annotation of existing resources;
Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
Providing a block of data, such as the result of submitting a
form, to a data-handling process;
Extending a database through an append operation.
I think in your case the "Providing a block of data, such as the result of submitting a form, to a data-handling process;" applies here.
Personally I am very strict in following a certain pattern in route definition and their purpose: /{resource}/{identifier?}/{relatedResource?|action?}.
In this case I would agree with /api/books/{book_id}/compress since it comlies with the listed usecases of POST.
I'm just getting into using REST and have started building my first app following this design model. From what I can gather the idea is to build your service like an api which your website itself is a consumer of.
This makes sense for me since my web app does a lot of AJAX calls, however it seems a little wasteful to authenticate each request to avoid using sessions. Is this just something I have to accept as part of the REST design process?
Also, making ajax calls works fine, but say, I need to just show a view of the users profile, does this now mean I also need to make a curl call to my api to pull this data. At this point I know I'm working internally so is authentication even required?
Some remarks:
While you could set up your whole application to have a REST interface, you should set it up to still be able to call it internally. Calling it from HTTP, and getting results back by HTTP is only input-processing, and output-rendering. So, if you seperate those concerns you get a flow: input-processing -> method call -> data return -> data rendering. Shaving of the first & last bit, what do you have left? A function call that returns data, which you can just use in your code. Seperate functionality to translate an 'outside' function call into an 'internal' one, and render 'internal' data into 'external' (xml, json, html, whatever you desire), makes your app efficient, and still fully REST capable.
Authentication is needed if you allow outside calls, even if you don't 'tell' other users data can be retrieved a certain way, it is still easily discoverable. I don't know why you wouldn't want to use sessions for this authentication (which most likely happens in forementioned translation from an 'outside' call to an internal one. I would not make 'not using sessions' a requirement, but there is no reason you couldn't allow several methods of authentication (session, re-authentication on every request, tokens, etc.).
Typically I prefer to produce an interface which can be called using standard PHP and then add an interface to this which adds authentication and RESTful access. So you can access for example:
http://example/api/fetchAllFromUsers?auth-key=XXXXX
Which translates to:
$internalInterface = new Api();
$internalInterface->fetchAllFromUsers();
Instead of authenticating each time, save a chunk of state (in, eg, a cookie) that identifies your session, and use that. It then becomes either a parameter to a GET (using the ?name-value syntax) or can be a part of the URI itself, eg
http://example.com/application/account/ACCTNO/TOKEN
where ACCTNO and TOKEN identify the account and the authentic session respectively.
This may seem a little flaky at first, but it means that your application, as it grows larger, never needs complicated load-balancing with session state and so on -- a simple proxy scheme works fine. This reduces the architeccture complexity by great staggering amounts.
Trying to figure out the best way to handle this, but since I essentially work alone, i figured that SO community could help. Not looking for code, just ideas.
I am developing a web app for my company. Total rebuild. We are moving the product search from a database table we update nightly to a SOAP service that stores info for all devices in our industry (semiconductors). Personally I wish it were in the DB still, but the decision was made before I started, but anywho...
The SOAP publisher allows us to use essentially any parameter we would like about a product in the output, but restricts the input params to two, part # and manufacturer.
Long story short is they suggest taking the result set they provide and winnowing it down via search filters on our side.
Here is my (planned) approach:
make initial request via SOAP
if request returns 0, message user else continue
Take SOAP response (WILL BE LIMITED TO 150 RESULTS MAX) and
convert to json
Send json to view and use javascript/jquery to page and filter
If user has js disabled, display all results.
Alternate options involve using / filtering php arrays
I haven't done much beyond writing the small SOAP handler script. I now have results sets but am trying to figure how best to handle.
I'm creating a webservice in which remote sites can send data to a PHP-based webservice. However, I'm struggling to come up with the best way of handling the incoming data.
The data will be in the form of shopping basket contents, so might include product name, price, ID, date, customer etc. There will be one line of data for each product in the basket, so there could be 20-30 lines for some customers.
Would sending the data to the webservice via GET be sensible? Is there a better option you can think of? Any input is greatly appreciated.
Thanks!
Probably not a great idea to send via get. I'd generate the basket as XML or JSON, then post it to the service. You can then write back a response on XML or JSON saying whether or not the call was successful.
A nice introduction to a RESTful API with PHP is here. I find it goes a bit overboard in some places, you can do the same with a little less code but it is nonetheless a good guide.
If the request is going to be making a change, I would not use GET. It would break GET's safety. Here's the HTTP spec on safe methods: RFC 2616.
I would recommend you look towards a REST architecture where it seems like a POST or possibly a PUT request should be used.
So, I was looking through some articles on creating REST API's.
And some of them suggest using all types of HTTP requests: like PUT DELETE POST GET.
We would create for example index.php and write API this way:
$method = $_SERVER['REQUEST_METHOD'];
$request = split("/", substr(#$_SERVER['PATH_INFO'], 1));
switch ($method) {
case 'PUT':
....some put action....
break;
case 'POST':
....some post action....
break;
case 'GET':
....some get action....
break;
case 'DELETE':
....some delete action....
break;
}
OK, granted - I don't know much about web services (yet).
But, wouldn't it be easier to just accept JSON object through regular POST or GET (that would contain method name and all parameters) and then respond in JSON as well. We can easily serialize/deserialize via PHP's json_encode() and json_decode() and do whatever we want with that data without having to deal with different HTTP request methods.
Am I missing something?
UPDATE 1:
Ok - after digging through various API's and learning a lot about XML-RPC, JSON-RPC, SOAP, REST I came to a conclusion that this type of API is sound. Actually stack exchange is pretty much using this approach on their sites and I do think that these people know what they are doing Stack Exchange API.
The idea of REpresentational State Transfer is not about accessing data in the simplest way possible.
You suggested using post requests to access JSON, which is a perfectly valid way to access/manipulate data.
REST is a methodology for meaningful access of data. When you see a request in REST, it should immediately be apparant what is happening with the data.
For example:
GET: /cars/make/chevrolet
is likely going to return a list of chevy cars. A good REST api might even incorporate some output options in the querystring like ?output=json or ?output=html which would allow the accessor to decide what format the information should be encoded in.
After a bit of thinking about how to reasonably incorporate data typing into a REST API, I've concluded that the best way to specify the type of data explicitly would be via the already existing file extension such as .js, .json, .html, or .xml. A missing file extension would default to whatever format is default (such as JSON); a file extension that's not supported could return a 501 Not Implemented status code.
Another example:
POST: /cars/
{ make:chevrolet, model:malibu, colors:[red, green, blue, grey] }
is likely going to create a new chevy malibu in the db with the associated colors. I say likely as the REST api does not need to be directly related to the database structure. It is just a masking interface so that the true data is protected (think of it like accessors and mutators for a database structure).
Now we need to move onto the issue of idempotence. Usually REST implements CRUD over HTTP. HTTP uses GET, PUT, POST and DELETE for the requests.
A very simplistic implementation of REST could use the following CRUD mapping:
Create -> Post
Read -> Get
Update -> Put
Delete -> Delete
There is an issue with this implementation: Post is defined as a non-idempotent method. This means that subsequent calls of the same Post method will result in different server states. Get, Put, and Delete, are idempotent; which means that calling them multiple times should result in an identical server state.
This means that a request such as:
Delete: /cars/oldest
could actually be implemented as:
Post: /cars/oldest?action=delete
Whereas
Delete: /cars/id/123456
will result in the same server state if you call it once, or if you call it 1000 times.
A better way of handling the removal of the oldest item would be to request:
Get: /cars/oldest
and use the ID from the resulting data to make a delete request:
Delete: /cars/id/[oldest id]
An issue with this method would be if another /cars item was added between when /oldest was requested and when the delete was issued.
This is a security and maintainability question.
safe methods
Whenever possible, you should use 'safe' (unidirectional) methods such as GET and HEAD in order to limit potential vulnerability.
idempotent methods
Whenever possible, you should use 'idempotent' methods such as GET, HEAD, PUT and DELETE, which can't have side effects and are therefore less error prone/easier to control.
Source
In short, REST emphasizes nouns over verbs. As your API becomes more complex, you add more things, rather than more commands.
You asked:
wouldn't it be easier to just accept JSON object through normal $_POST and then respond in JSON as well
From the Wikipedia on REST:
RESTful applications maximize the use of the pre-existing, well-defined interface and other built-in capabilities provided by the chosen network protocol, and minimize the addition of new application-specific features on top of it
From what (little) I've seen, I believe this is usually accomplished by maximizing the use of existing HTTP verbs, and designing a URL scheme for your service that is as powerful and self-evident as possible.
Custom data protocols (even if they are built on top of standard ones, such as SOAP or JSON) are discouraged, and should be minimized to best conform to the REST ideology.
SOAP RPC over HTTP, on the other hand, encourages each application designer to define a new and arbitrary vocabulary of nouns and verbs (for example getUsers(), savePurchaseOrder(...)), usually overlaid onto the HTTP 'POST' verb. This disregards many of HTTP's existing capabilities such as authentication, caching and content type negotiation, and may leave the application designer re-inventing many of these features within the new vocabulary.
The actual objects you are working with can be in any format. The idea is to reuse as much of HTTP as possible to expose your operations the user wants to perform on those resource (queries, state management/mutation, deletion).
You asked:
Am I missing something?
There is a lot more to know about REST and the URI syntax/HTTP verbs themselves. For example, some of the verbs are idempotent, others aren't. I didn't see anything about this in your question, so I didn't bother trying to dive into it. The other answers and Wikipedia both have a lot of good information.
Also, there is a lot to learn about the various network technologies built on top of HTTP that you can take advantage of if you're using a truly restful API. I'd start with authentication.
In regards to using extension to define data type.
I noticed that MailChimp API is doing it, but I don't think this is a good idea.
GET /zzz/cars.json/1
GET /zzz/cars.xml/1
My sound like a good idea, but I think "older" approach is better - using HTTP headers
GET /xxx/cars/1
Accept: application/json
Also HTTP headers are much better for cross data type communication (if ever someone would need it)
POST /zzz/cars
Content-Type: application/xml <--- indicates we sent XML to server
Accept: application/json <--- indicates we want get data back in JSON format
Am I missing something?
Yes. ;-)
This phenomenon exists because of the uniform interface constraint. REST likes using already existing standards instead of reinventing the wheel. The HTTP standard has already proven to be highly scalable (the web is working for a while). Why should we fix something which is not broken?!
note: The uniform interface constraint is important if you want to decouple the clients from the service. It is similar to defining interfaces for classes in order to decouple them from each other. Ofc. in here the uniform interface consists of standards like HTTP, MIME types, URI, RDF, linked data vocabs, hydra vocab, etc...
Good Semantics is important in programming.
Utilizing more methods besides GET/POST will be helpful because it will increase the readability of your code and make it easier to maintain.
Why?
Because you know GET will retrieve data from your api. You know POST will add new data to your system. You know PUT will make updates. DELETE will delete rows etc, etc,
I normally structure my RESTFUL Web Services so that I have a function callback named the same thing as the method.
I use PHP, so I use function_exists (I think its called). If the function doesn't exist, I throw a 405 (METHOD NOT ALLOWED).
Bill Venners: In your blog post entitled "Why REST Failed," you said that we need all four HTTP verbs—GET, POST, PUT, and DELETE— and lamented that browser vendors only GET and POST." Why do we need all four verbs? Why aren't GET and POST enough?
Elliotte Rusty Harold: There are four basic methods in HTTP: GET, POST, PUT, and DELETE. GET is used most of the time. It is used for anything that's safe, that doesn't cause any side effects. GET is able to be bookmarked, cached, linked to, passed through a proxy server. It is a very powerful operation, a very useful operation.
POST by contrast is perhaps the most powerful operation. It can do anything. There are no limits as to what can happen, and as a result, you have to be very careful with it. You don't bookmark it. You don't cache it. You don't pre-fetch it. You don't do anything with a POST without asking the user. Do you want to do this? If the user presses the button, you can POST some content. But you're not going to look at all the buttons on a page, and start randomly pressing them. By contrast browsers might look at all the links on the page and pre-fetch them, or pre-fetch the ones they think are most likely to be followed next. And in fact some browsers and Firefox extensions and various other tools have tried to do that at one point or another.
PUT and DELETE are in the middle between GET and POST. The difference between PUT or DELETE and POST is that PUT and DELETE are *idempotent, whereas POST is not. PUT and DELETE can be repeated if necessary. Let's say you're trying to upload a new page to a site. Say you want to create a new page at http://www.example.com/foo.html, so you type your content and you PUT it at that URL. The server creates that page at that URL that you supply. Now, let's suppose for some reason your network connection goes down. You aren't sure, did the request get through or not? Maybe the network is slow. Maybe there was a proxy server problem. So it's perfectly OK to try it again, or again—as many times as you like. Because PUTTING the same document to the same URL ten times won't be any different than putting it once. The same is true for DELETE. You can DELETE something ten times, and that's the same as deleting it once.
By contrast, POST, may cause something different to happen each time. Imagine you are checking out of an online store by pressing the buy button. If you send that POST request again, you could end up buying everything in your cart a second time. If you send it again, you've bought it a third time. That's why browsers have to be very careful about repeating POST operations without explicit user consent, because POST may cause two things to happen if you do it twice, three things if you do it three times. With PUT and DELETE, there's a big difference between zero requests and one, but there's no difference between one request and ten.
Please visit the url for more details. http://www.artima.com/lejava/articles/why_put_and_delete.html
Update:
Idempotent methods
An idempotent HTTP method is a HTTP method that can be called many times without different outcomes. It would not matter if the method is called only once, or ten times over. The result should be the same. Again, this only applies to the result, not the resource itself. This still can be manipulated (like an update-timestamp, provided this information is not shared in the (current) resource representation.
Consider the following examples:
a = 4;
a++;
The first example is idempotent: no matter how many times we execute this statement, a will always be 4. The second example is not idempotent. Executing this 10 times will result in a different outcome as when running 5 times. Since both examples are changing the value of a, both are non-safe methods.
Basically REST is (wiki):
Client–server architecture
Statelessness
Cacheability
Layered system
Code on demand (optional)
Uniform interface
REST is not protocol, it is principles.
Different uris and methods - somebody so called best practices.