3

Let's say that I want to create a website where users will be able to create, edit and delete some kind of resources, for example posts.

I have created a RESTful API, so user can create a post by sending a PUT request to http://www.example.com/posts/my-new-awesome-post, delete it by sending DELETE request, etc.

But most users don't know anything about HTTP requests. They want to click a "New post" button and have the new post created. But HTML only allows me to use GET and POST.

How can I create a "New post" button that will send a PUT request? Or is "RESTful creation/deletion" implemented in a totally different way?

Let's say I'm using Spring + Thymeleaf.

SingularityFX
  • 133
  • 1
  • 4
  • 3
    HTML pages do not normally interact directly with REST APIs. Those are meant for web service clients to use, although I suppose you _could_ have HTML in a browser be the client. I think you need to take a step back and reevaluate your overall system design. –  Jul 10 '15 at 14:51
  • What's wrong wtih `POST`? – JᴀʏMᴇᴇ Jul 10 '15 at 15:40
  • @JayMee religious objections, from those who feel that if you're not using PUT, DELETE, etc., your API is *wrong* – Carson63000 Jul 11 '15 at 02:48
  • Rest is an anti pattern – Ewan Jul 13 '15 at 17:24
  • @Ewan Could you please elaborate why? – SingularityFX Jul 23 '15 at 10:49
  • REST attempts to squeeze all possible requests into the HTML Method verbs, but unless you are doing some pretty basic CRUD style 'webdev' you'll. soon bump into stuff that just doesn't fit. Even here with this simple problem we run into the cold hard fact that web browsers just don't do PUT as standard – Ewan Jul 23 '15 at 17:25
  • @Ewan Unfortunately, that's how the web works. We're stuck with it and might as well embrace it since he whole HTTP food chain (clients, proxies, caches, servers) is built around those verbs. The fact that PUT isn't supported as a form method in current HTML standards is an entirely [unrelated issue](http://programmers.stackexchange.com/a/211790/15150). – guillaume31 Feb 05 '16 at 09:56
  • @guillaume31 the point is no one is forcing you to use http for api calls and even if you do, no one is forcing you to use POST for some requests and PUT for others. – Ewan Feb 05 '16 at 10:29
  • No one is forcing you but the whole ecosystem is geared towards it. HTTP is an application protocol, not a transport protocol. Ignoring it can lead you to hiccups in the HTTP chain such as those listed in the "Other considerations" section of the answer I linked to. – guillaume31 Feb 05 '16 at 11:16

2 Answers2

5

The 'New Post' button would go to a form for the user to input the information for a new post. When the user submits that form the browser rightly sends that data via HTTP POST (use POST for create).

An edit submission would use PUT or PATCH depending on whether it is a replace (delete the missing properties) or update (only change the submitted properties), respectively.

We usually make an XMLHTTPRequest (XHR) using JavaScript for events other than GET or POST.

jQuery.ajax('/products/42', {method: 'PUT', data: product_data});

jQuery Docs: http://api.jquery.com/jquery.ajax/

Additionally, Rails will use a '_method' param in POSTs to force a different action on the server ( like PUT or PATCH).

Karl Wilbur
  • 166
  • 4
1

How can I create a "New post" button that will send a PUT request?

Don't. Not when you are returning HTML.

Or is "RESTful creation/deletion" implemented in a totally different way?

Slightly the wrong question. REST doesn't care how you do it, beyond the rule that you are using hypermedia controls and media-types. HTTP affords PUT and DELETE as methods. But HTML is a well specified media-type that doesn't support PUT and DELETE.

So if you want "New Post", in a restful html application, then you specify a form with the POST method. If you want "Delete Post" then you specify a form with the POST method.

PUT and DELETE are idempotent. If you want that for POST, you have to do a bit of extra work. The html forms should already have in them unique URIs (the URI identifies the resource, but it doesn't promise that the "resource" already exists). You add checks to the handling of the posted forms that check to see if a message with that unique identifier has already been processed.

A browser reading your html won't know that the form is idempotent, but you can document that it is, and other consumers can use that knowledge. If you were really going all out, you would presumably have two different media-types: text/html for browsers, and a text/vnd.infranoise+html representation available for other clients. Disclaimer: I don't know of any API's that actually do that for html representations.

The unique identifiers require some special handling. When all copies of your form start in the same state, then the URI /x/y/myform takes care of you. But here, we want a unique version of the form -- we want the form to specify which item we are creating/deleting. For delete, we may be able to use the itemId: /z/y/x?itemId=12345. For create, we don't have an id yet -- so we solve this with 303 (See Other). We make the "create" link go to /a/b/c, and have that generate a new id, and then redirect the browser to /a/b/c?itemId=...

Finally, there's the question of what URI spellings to use. REST doesn't care. But common URI design guidelines correctly point out that resources are nouns.

There are a lot of APIs for manipulating resources in collections, but most that I have found are not restricted to the HTML methods. One approach would be to maintain two collections; post to one collection to create the document, post to the opposite collection to remove the document -- think "trash can", rather than delete.

Another possibility would be to embrace the fact that your resources for dispatching create/delete commands are forms, and can be obtained from the forms collection

/forms/createPostForms?itemId=12345
/forms/deletePostForms?itemId=12345

Wanna go bike shedding?

/forms/createPostForms?itemId=12345
/forms/post/12345/create
/forms/post?type=create&itemId=12345
/forms/post/12345,create
/posts/12345/create
/posts/12345/forms/create
/posts/12345/forms?type=create
/nonsequiturs?itemId=12345&type=post&action=create

REST doesn't care. HTML doesn't care. Compliant browsers don't care. Your HttpRequestHandler only cares insofar as it needs to know the right URI template(s) to use.

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79