tags:

views:

390

answers:

8

So...

I've been reading about REST a little bit, and the idea behind it sounds nice, but the question is, can it be easily integrated into the standard flow of a webpage?

For example, a user creates some sort of item, a blog post or what have you, and now he wants to delete it, so he clicks a 'delete' link on the page. Now what? How do we issue a DELETE request to, say, http://mysite.com/posts/5? And how do we handle that request? I have no experience with cURL or anything, but from the looks of it, I would have to curl_init('http://mysite.com/posts/5') and then work some magic. But where would I even put that script? That would have to be on another page, which would break the whole idea of REST. Then I would just be GETing another page, which would in turn DELETE the page I originally intended?

Is this why people rarely use REST or is there actually a nice way to do this?


Looks like I need to clarify. People are suggesting I include words like "DELETE" and "POST" in the URL. I believe REST dictates that we have a unique URL for each resource but not for each action on that resource. I assume this also means that we only have one and only one URL for each resource. i.e. I want to be able to DELETE or VIEW the contents of a particular post from one URL (by sending either DELETE, PUT, POST, or GET), not different URLs with additional params

+1  A: 

Depending on what framework you use, there are models that determine how actions are handled for each resource.

Basically using another parameter, you want to send the resource what action to perform. That parameter may be sent through AJAX/JS for example.

If you want to do it without javascript/ajax (in case it's disabled), then a form POST method would work as well, sending the resource the extra ACTION parameter.

Of course, in both cases, you have to consider security, and make sure that they're not sending the resource an action they shouldn't be. Make sure to do your checking on the backend, and send an appropriate response or error message.

Client side scripting, whether through JS/Ajax or form POST or other methods require the extra security precaution.

Edited after clarification from poster.

Sev
Sure, but that's no longer REST at all. What you're describing is easy to do, but that wasn't the point of this question :) The idea is that /posts/5 could be used to either view the contents of post 5, or delete post 5 depending on the HTTP request.
Mark
Ah okay, I had misunderstood your question. Thanks for clarifying.
Sev
Forms only allow GET or POST though... I don't see how this helps me do DELETEs?
Mark
You're talking about the action of the form. I'm talking about sending the resource the action to perform, as in, delete in this case. So it could be a hidden form element for example.
Sev
+1  A: 

Well one way is to make an AJAX call using the DELETE method.

Jonathan Maddison
Well, AJAX is great and all but I'd like to use a server-side technology so as not to depend on what the client has enabled.
Mark
Web browsers are limited to GET and POST, so if you don't want to use AJAX then you have accept that your "uniform interface" is going to be limited to GET and POST. You can use POST to delete things. You could do a POST to http://example.org/TrashCan?url=/MyResource/75
Darrel Miller
Web browsers aren't limited to GET and POST - HTML4 forms are. HTML5 adds PUT and DELETE, and JavaScript can do them to depending on the implementation.
Wahnfrieden
+1  A: 

I don't think REST is rarely used. You're using it right now, on StackOverflow. As far as your specific example goes, you can send DELETE requests though XMLHttpRequest in browsers that support it. When JS is off, or for non-compliant browsers, you can do something like:

POST http://foo.com/delete?post=5

Not ideal, but still more restful than many sites.

EDIT: Changed to POST

Matthew Flaschen
Probably better to overload POST because GET shouldn't have side-effects: POST http://foo.com/delete?post=5
rojoca
Probably would want to use POST over GET, for XSRF reasons.
Simon Buchan
Some server-side libraries let you overload POST by appending something like ?method=DELETE to your URIs. On the server side this is mapped into a proper DELETE request. Hopefully we'll get RESTful submits in HTML soon ...
Jim Ferrans
... Should refresh pages before commenting :/
Simon Buchan
completely agree with Ferrans's comment, you should try to keep the message as "restful" as possible, something like http://foo.com/posts/5?_method=deletethen you would use the "_method" variable to override the used method, so if your client only supports gets and posts, it may issue a post and tell your service to behave as it would have been called with a delete method...
opensas
There's nothing RESTful about using fancy URIs or using HTTP correctly.
Wahnfrieden
+1  A: 

Facebook's REST server is a pseudo one, you can do it like them, asking for the post method: POST, GET, etc. the action and the other values you need for that request.

Why I say facebook is a pseudo REST server? : well, one of the Principles of REST says

  • Every resource is uniquely addressable using a universal syntax for use in hypermedia links

in facebook you only have /server.php and there is where you make the request, even for (POST, GET, PUT, DELETE...)

the other way is using mod_rewrite and parse the url the client is requesting

EDIT: just found this, looks interesting. Have fun!

Gabriel Sosa
+1  A: 

Don't overthink it. You're not going to be able to do this with straight HTML forms and a browser. They do not support DELETE method. Ajax can do it.

I want to be able to DELETE to VIEW the contents of a particular post from one URL (by sending either DELETE, PUT, POST, or GET), not different URLs with additional params

Delete to view? I'm not sure I understand it, but your delete should be done through the headers, not through the URL. The delete method should not return a view. REST is a service, not all requests are meant for visual consumption.

altCognito
well, as said before, you can add a hidden input named "_method" with the value "delete" to call your service from a html form, and tell it to behave like it would have received a delete method, like you would do with an ajax client...
opensas
"DELETE to VIEW" was a typo. Should be "DELETE or VIEW", i.e. by sending headers "DELETE /posts/5" or "GET /posts/5".
Mark
@opensas It can be done, but if you're looking for a truer rest, that's not the route to go, it should be done in the header.
altCognito
@altCognito, do you have a reference? I believe that's totally incorrect. It's not specified how you should overcome incomplete protocol implementation.
Wahnfrieden
No, because there is no specification other than basically what Fielding recommended. In his dissertation (http://www.ics.uci.edu/~fielding/pubs/dissertation/evaluation.htm#sec_6_3) Fielding points out that headers are the way that HTTP was meant to be extended.
altCognito
+4  A: 

With a restful server, the same url (say /books/1) can respond to many different verbs. Those verbs, GET, POST, PUT, and DELETE, together with the path, indicate what you want to do to the data on the server. The response tells you the answer to your request.

REST is about accessing data in a predictable and sensible way.

If you come from a strong PHP background, where every url has to map to a particular file, you're right, it doesn't really make sense. The two most visible RESTful development environments, ASP.NET MVC and Rails, each have special servers (or server logic) which read the verbs and do that special routing for you. That's what lets the "normal flow" of the application go through as you'd expect. For PHP, there are frameworks that help with this, such as WSO2's WSF.

How REST works with Web Browsers

Take, for instance, your example. We have posts, and we want to delete one.

  1. We start by visiting a url like /posts/4. As we would expect, this shows post 4, its attributes, and some actions you could take on it. The request to render this url would look like GET /posts/4. The response contains HTML that describes the item.

  2. The user clicks the "Delete Item 4" link, part of the HTML. This sends a request like DELETE /posts/4 to the server. Notice, this has re-used the /posts/4 url, but the logic must be different.

    Of HTML forms and web browsers, many of them will change a link with method="delete" into a method="post" link by default. You will need to use Javascript (something like this) to change the verb. Ruby on Rails uses a hidden input field (_method) to indicate which method is to be used on a form, as an alternative.

  3. On the server side, the "delete an item" logic is executed. It knows to execute this because of the verb in the request (DELETE), which matches the action being performed. That's a key point of REST, that the HTTP verbs become meaningful.

  4. After deleting the item, you could respond with a page like "yep, done," or "no, sorry, you can't do that," but for a browser it makes more sense to put you somewhere else. The item being deleted, responding with a redirect to GET /posts makes good sense.

If you look at the server log, it will be very clear what everybody did to the server, but that's not as important as...

How REST works with Arbitrary Data

Another key point of REST is that it works well with multiple data formats. Suppose you were writing a program that wanted to read and interact with the blog programmatically. You might want all the posts given in XML, rather than having to scrape the HTML for information.

GET /posts/4.xml is intuitive: "Server, please give me xml describing post #4." The response will be that xml. A RESTful server makes it obvious how to get the information you want.

When you made the DELETE /posts/4.xml request, you're asking, "Server, please delete item #4." A response like, "Okay, sure," is usually sufficient to express what's happened. The program can then decide what else it wants and make another request.

Andres Jaan Tack
Yes! This is much closer to the answer I was looking for. This part I understand though... I guess my question really is how can I issue a 'DELETE' request with PHP/Apache when a user clicks a link? How do I issue the verbs? How does RoR do it?
Mark
Nevermind. I was hoping I could somehow magically have <a href> URLs without stuff like "edit" in them. I just need to have a base script that catches this and issues the right verb... I get it now. Thanks :)
Mark
So, in your point #2, the user would actually click a link that points to /posts/4/delete, the server logic would catch this and issue a DELETE request to /posts/4.
Mark
You *dont* want to trigger the delete action with a GET request to "/posts/4/delete". Google for "rails GWA fiasco" for why this is a really bad idea. You can either use a (POST) from (with some hidden parameter telling the server that you really mean DELETE), or use javascript to send a real DELETE.
trendels
GET /posts/4.xml may be intuitive to you but your client has no clue what the format of the xml response is. That is why REST services should deliver specific media types. application/xml tells the client nothing other than, "here's a text document with some elements, attributes and maybe namespaces"
Darrel Miller
@Darrel You're right. I've been burned by people not following those specific formats, though, so I don't think there's a viable alternative to actually looking at sample output.
Andres Jaan Tack
@Mark, trendels is correct, although I really don't think it's as bad as he makes it out to be. :)I found a framework that helps PHP scripts provide REST services and interpret the request verbs. Unfortunately, I haven't any idea what it's like to use.
Andres Jaan Tack
@Tack The content-type should tell the client everything it needs to know about how to interpret the data.
Darrel Miller
@trendels: Seems kinda silly to create an entire form when all you want is a little link. And I don't like the idea of depending on JavaScript. I intend on validating the delete request to ensure the user owns the resource anyway, so what's the big deal?
Mark
@Darrel: I don't get it. How else are they supposed to know what the format of the XML is? Presumably there would be some API documentation if it were intended for public usage? As long as it actually *is* XML, isn't that okay?
Mark
@trendels: Are you referring to the content negotiation problem with the "rails GWA fiasco" thing? I don't see how this is a problem either... I'm only serving a response in one format?
Mark
@Darrel: Oh you mean like an RSS feed vs... something else that also comes in XML? Then why not use a .rss or .atom extension instead? That way the user can explicitly define what they want, you won't have the content negotiation problem, and the content-type can be set appropriately?
Mark
@Mark, the problem with GET links to delete content is simply that one day a web spider or "web accelerator" will come along and follow all of the links on your site. The HTTP standard explicitly says that GET links should be save to follow and not trigger any action on the server (such as deleting/updating a resource). For everything else, you should use POST (i.e. a form). Some people learned this the hard way after the "Google Web Accelerator" deleted their whole database by "clicking" delete links. If you don't like the look of form buttons, you can style them to look like links using CSS.
trendels
@trendels: Ah... didn't think about bots. Is this what people actually do in practice? Make every delete link like `<form method="post" action="/posts/delete/1"><input type="submit" value="my delete button that looks like a link"></form>`? That's a fair bit of HTML.
Mark
@Mark So what you just wrote there, even though it's a form, it's still not sending a DELETE request. Another thread (http://stackoverflow.com/questions/523843) addresses how to send a DELETE request from a link better than I could describe here, and that *is* how everybody actually does it in practice.
Andres Jaan Tack
@Mark There is a huge difference between sending a document with an RSS content type, or a HTML content type than sending application/xml or Json. It is the HTTP equivalent of passing a reference to an object versus a reference to some concrete class like Point or Address. The content-type is the contract between the client and the server. Sure the client has to understand the format of the contract types used, but it doesn't need to guess that the XML coming from this endpoint is probably of this format. The content-type is stated explicitly in the response.
Darrel Miller
This isn't REST, this is simply 'using HTTP correctly.'
Wahnfrieden
@Andres, you can't use DELETE with HTML4 forms anyway, so you have to use a workaround. HTML5 adds DELETE and PUT support to forms though.
Wahnfrieden
@Wahnfrieden Yeah, I know, I mentioned that. As far as REST vs. correct HTTP; have the two not become synonymous? Question, not a challenge.
Andres Jaan Tack
@Andres, if you read the REST specification, it doesn't mention HTTP anywhere. Unfortunately, many people have the mistaken notion that REST simply means using HTTP, which is why you see so many APIs falsely claiming to be RESTful. It's great that people are finally seeing how HTTP is meant to be used, but I hate seeing "REST" being tossed around to the point of losing all meaning. The constraints of REST that people ignore aren't just splitting hairs, they provide a real benefit.
Wahnfrieden
+1  A: 

If you really have no choice about using the DELETE verb then I would suggest something like the following:

POST http://mysite.com/Trashcan?resourceUrl=/Customer/75

What url you use really does not matter to REST, however, it is easier to understand the REST way of interacting if your urls avoid verbs completely.

I have seen so many questions from both Rails and ASP.NET MVC users who need to go beyond the standard "actions" and it is so tempting to just add a new action on the controller. The problem with doing this is that you just threw away the uniform interface constraint of REST.

The trashcan metaphor is not the only way of doing deletes restfully but I would argue that it is just as clear to read as putting a "delete" in the url.

Here are some more "noun-based" ways of replacing verbs.

POST http://mysite.com/Printer/75/PrintQueue?url=http://mysite.com/Document/xyz
POST http://mysite.com/CurrentLogins?user=bob
POST http://mysite.com/QueryProcessor?query=FindMyInformation
POST http://mysite.com/SearchEngine?searchTerms=cat,blue,furry
POST http://mysite.com/OrderProcessor?cart=http://mysite.com/user/2323/cart

Sometimes you have to think out of the box a little to come up with a noun based url, and may seem pedantic to try and do this, but for me the benefit comes from the ability to manage my variables. I am going to have a variable number of resources in my interface, no matter what I do, if I can fix the number of verbs that can operate on those resources then I reduce one of my variables.

Darrel Miller
A: 

Another way of doing it, assuming a webbased/webapplication-based request, is have 2 submitbuttons. Since PUT and DELETE use the same uri/url. You could add a specific delete form and attach a specific name to this delete-button, so when this is sent via a post, you can use this button-name to turn the action into a DELETE

mr.mstyle