tags:

views:

104

answers:

4

I think I have a basic understanding of REST, but something I'm stuck on is how to request an HTML form to edit a resource.

To my understanding, if the resource is

user/12

And you do a GET on that with content-type "text/html" then you would get some html back that would display the details of that user.

What I don't understand is how to get back html that will display a form that allows you to edit the details of a user (and ultimately send a PUT back to update the user.)

I've seen:

user/12/edit 
user/12;edit

Which don't feel super RESTful to me. Personally, knowing nothing else (including whether or not it is valid) I'd consider passing some kind of edit=true parameter on the "Accept:" line of the HTTP header.

Is there a definitive way of doing it?

Edit: I should have explained that I'm implementing the service and wanted to know the proper way of doing it if such existed.

A: 

REST is a concept, not an implementation. Meaning, while your description of a RESTful URL with a Content-Type of text/html returning html is certainly valid, it does not guarantee the return payload. It's up the implementor of the REST service to return the data in its form.

Work backwards from the REST entry you're requesting and look at the return payload. That will tell you everything you need to know about your usage of that URL, and how much work you'll need to do on your consuming side of the equation.

jro
+1  A: 

Returning an HTML form as a resource representation tightly couples your presentation and data. It would give you more control if you simply return the basic resource representation (which could be HTML, but I wouldn't expect it to have form elements), and then rely on my client to mark up the data in a way that's editable in HTML.

Additionally, if you were to return an HTML form with the resource marked up in it, how would the form data be sent back to the server? Browsers typically only support POST and GET for form actions - but doing a POST to a resource that already exists isn't RESTful; you would want to be doing a PUT instead. Until browsers support all (or at least more) of the HTTP methods, using RESTful APIs with browser forms directly will be fundamentally broken (at least within the bounds of REST constraints).

Edit:

To answer your question of how you would actually have the client inform the server about how it wants the resource back, you would use content negotiation. Based on the request headers the server returns the resource in an appropriate format. It might use the user agent from the header, or the client might specify a specific Accept header that the server can obey. It's up to you and your server application to process the header(s) and return the appropriate HTML representation, if available.

Edit2:

Redacted my statement about returning a form not being RESTful, see comments below.

Rob Hruska
I might be wrong, but my understanding was that the content-type in the GET request header dictated how the server returned the data. So it coming back as html when requested as html is pretty reasonable. I also thought you could use javascript to do proper PUT requests from the browser, though again I might be wrong. I'm a bit of a beginner. I'll read up on content negotiation though, thanks.
MichaelJones
Rob Hruska
Thank you for the additional comments. I realise that clients will also want html without forms, which is why I'm asking how they might differentiate between the two when requesting. However your point about getting the raw data and creating the form in javascript is fair, I'll look into that. Thanks again.
MichaelJones
There is absolutely nothing "unrestful" about returning a Form in an HTML document. REST is for building distributed applications, not just for exposing distributed data. REST is about exposing data and the "controls" in which it can be manipulated. As Justice mentions below if you want to expose a resource with the HTML form and one without, that's fine too.
Darrel Miller
I'll agree that returning an HTML form is not "unrestful" in itself, but I'm looking at the whole process. If you return the <form>...</form>, you're likely retrieving it asynchronously and adding it to a page's DOM - otherwise, what good is an HTML form on its own? You might as well just have your server return the resource "raw" as XML or JSON, which would give more control over the presentation. Plus, even if the returned form has the action populated, the form will still have to POST (in the absence of widespread browser PUT support), which shouldn't update the resource.
Rob Hruska
+1  A: 

Just for what it's worth - AFAIK, user/12;edit was only used in Rails, and only for a month or two. It was dropped fairly quickly.

jdelStrother
Thanks, I'll ignore that options then! Do you know what they went with instead? /edit?
MichaelJones
Yep. Which i don't think is too bad, practically speaking
jdelStrother
+1  A: 

There are no special methods or headers for this sort of thing (responding with the HTML of an editable form for a given resource). And using querystring parameters would only make this worse.

Instead, one might conceptually treat the editable form as resource in its own right, and assign it the path /user/12/edit. The "postback" would of course be PUT /user/12 (or, in Rails, POST /user/12 and prepend _method=PUT& to the POSTed entity).

When one does GET /user/12, one is asking for a representation of the user. When one does GET /user/12/edit, one is asking for a representation of a form for the user, rather than a representation of the user directly.

Is this an accurate extension of REST? Is this pure REST? Debatable. But, what else are you going to do?

Justice
I agree with most of this, my only question is whether PUT is the right verb to update a resource via a form. Doesn't seem right to me.
Darrel Miller
Here's how it works. `PUT /users/12` means "modify user #12 with the following stuff." But `POST /users` means "either find the right resource based on the following stuff and then update that resource based on the following stuff; and if the resource in question doesn't actually exist, then first make a new one and subsequently do everything else that I just said to do." So in fact, you *should* use `PUT /user/12` in this scenario, because that is what you want.
Justice