Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h2>Why aim for a RESTful design?</h2> <p>The RESTful principles <strong>bring the features that make web sites easy</strong> (for a <em>random human user</em> to "surf" them) <strong>to the web services API design</strong>, so they are easy for a programmer to use. <a href="http://www.tbray.org/ongoing/When/200x/2009/03/20/Rest-Casuistry" rel="noreferrer">REST isn't good because it's REST, it's good because it's good.</a> And it is good mostly because it is <strong>simple</strong>.</p> <p>The simplicity of plain HTTP (without SOAP envelopes and single-URI overloaded <code>POST</code> services), what <strong>some may call <em>"lack of features"</em></strong>, is actually <strong>its greatest strength</strong>. Right off the bat, HTTP asks you to have <em>addressability</em> and <em>statelessness</em>: the two basic design decisions that keep HTTP scalable up to today's mega-sites (and mega-services).</p> <p>But REST is not the silver bulltet: <strong>Sometimes an RPC-style</strong> ("Remote Procedure Call" - such as SOAP) <strong>may be appropriate</strong>, and sometimes other needs take precedence over the virtues of the Web. This is fine. What we don't really like <strong>is needless complexity</strong>. Too often a programmer or a company brings in RPC-style Services for a job that plain old HTTP could handle just fine. The effect is that HTTP is reduced to a transport protocol for an enormous XML payload that explains what's "really" going on (not the URI or the HTTP method give a clue about it). The resulting service is far too complex, impossible to debug, and won't work unless your clients have the <strong>exact setup</strong> as the developer intended.</p> <p>Same way a Java/C# code can be <em>not</em> object-oriented, just using HTTP does not make a design RESTful. One may be caught up in the rush of <strong>thinking</strong> about his services <strong>in terms of actions and remote methods</strong> that should be called. No wonder this will mostly end up in a RPC-Style service (or a REST-RPC-hybrid). The first step is to think different. A RESTful design can be achieved in many ways, one way (the simplest, some might say) is to <strong>think of your application in terms of resources, not actions:</strong></p> <ul> <li>Instead of thinking in terms of actions ("do a search for places on the map"),</li> <li>Think in terms of the results of that action ("the list of places on the map matching a search criteria").</li> </ul> <p>I'll go for examples below. (Other key aspect of REST is the use of HATEOAS - I don't brush it here, but I talk about it quickly <a href="https://stackoverflow.com/a/30607633/1850609">at another post</a>.)</p> <h2>About the first design</h2> <p>Let's take a look a the proposed design:</p> <pre><code>ACTION http://api.animals.com/v1/dogs/1/ </code></pre> <p>First off, we should not consider creating a <strong>new HTTP verb</strong> (<code>ACTION</code>). Generally speaking, this is <em>undesirable</em> for several reasons:</p> <ul> <li><strong>(1)</strong> Given only the service URI, how will a "random" programmer know the <code>ACTION</code> verb exists?</li> <li><strong>(2)</strong> if the programmer knows it exists, how will he know its semantics? What does that verb mean?</li> <li><strong>(3)</strong> what properties (safety, idempotence) should one expect that verb to have?</li> <li><strong>(4)</strong> what if the programmer has a very simple client that only handles standard HTTP verbs?</li> <li><strong>(5)</strong> ...</li> </ul> <p>Now let's <strong>consider using <code>POST</code></strong> (I'll discuss why below, just take my word for it now):</p> <pre><code>POST /v1/dogs/1/ HTTP/1.1 Host: api.animals.com {"action":"bark"} </code></pre> <p>This <em>could</em> be OK... but <strong>only if</strong>:</p> <ul> <li><code>{"action":"bark"}</code> was a document; and</li> <li><code>/v1/dogs/1/</code> was a "document processor" (factory-like) URI. <sub>A "document processor" is a URI that you'd just "throw things at" and "forget" about them - the processor may redirect you to a newly created resource after the "throwing". E.g. the URI for posting messages at a message broker service, which, after the posting would redirect you to a URI that shows the status of the message's processing.</sub></li> </ul> <p>I don't know much about your system, but I'd already bet both aren't true:</p> <ul> <li><code>{"action":"bark"}</code> <strong>is not a document</strong>, it actually <strong>is the method</strong> you are trying to <em>ninja-sneak</em> into the service; and</li> <li>the <code>/v1/dogs/1/</code> URI represents a "dog" resource (probably the dog with <code>id==1</code>) and not a document processor.</li> </ul> <p>So all we know now is that the design above is not so RESTful, but what is that exactly? <strong>What is so bad about it?</strong> Basically, it is bad because that is complex URI with complex meanings. You can't infer anything from it. How would a programmer know a dog have a <code>bark</code> action that can be secretly infused with a <code>POST</code> into it?</p> <h2>Designing your question's API calls</h2> <p>So let's cut to the chase and try to design those barks RESTfully by thinking <strong>in terms of resources</strong>. Allow me to quote the <a href="https://rads.stackoverflow.com/amzn/click/0596529260" rel="noreferrer">Restful Web Services</a> book:</p> <blockquote> <p>A <code>POST</code> request is an attempt to create a new resource from an existing one. The existing resource may be the parent of the new one in a data-structure sense, the way the root of a tree is the parent of all its leaf nodes. Or the existing resource may be a special <em>"factory"</em> resource whose only purpose is to generate other resources. The representation sent along with a <code>POST</code> request describes the initial state of the new resource. As with PUT, a <code>POST</code> request doesn’t need to include a representation at all.</p> </blockquote> <p>Following the description above we can see that <strong><code>bark</code></strong> can be modeled as <strong>a subresource of a <code>dog</code></strong> (since a <code>bark</code> is contained within a dog, that is, a bark is "barked" <strong>by</strong> a dog).</p> <p>From that reasoning we already got:</p> <ul> <li>The method is <code>POST</code></li> <li>The resource is <code>/barks</code>, subresource of dog: <code>/v1/dogs/1/barks</code>, representing a <code>bark</code> "factory". That URI is unique for each dog (since it is under <code>/v1/dogs/{id}</code>).</li> </ul> <p>Now each case of your list has a specific behavior.</p> <h2>1. bark just sends an e-mail to <code>dog.email</code> and records nothing.</h2> <p>Firstly, is barking (sending an e-mail) a synchronous or an asynchronous task? Secondly does the <code>bark</code> request require any document (the e-mail, maybe) or is it empty?</p> <p><br></p> <h3>1.1 bark sends an e-mail to <code>dog.email</code> and records nothing (as a synchronous task)</h3> <p>This case is simple. A call to the <code>barks</code> factory resource yields a bark (an e-mail sent) right away and the response (if OK or not) is given right away:</p> <pre><code>POST /v1/dogs/1/barks HTTP/1.1 Host: api.animals.com Authorization: Basic mAUhhuE08u724bh249a2xaP= (entity-body is empty - or, if you require a **document**, place it here) <strong>200 OK</strong> </code></pre> <p>As it records (changes) nothing, <code>200 OK</code> is enough. It shows that everything went as expected.</p> <p><br></p> <h3>1.2 bark sends an e-mail to <code>dog.email</code> and records nothing (as an asynchronous task)</h3> <p>In this case, the client must have a way to track the <code>bark</code> task. The <code>bark</code> task then should be a resource with it's own URI.:</p> <pre><code>POST /v1/dogs/1/barks HTTP/1.1 Host: api.animals.com Authorization: Basic mAUhhuE08u724bh249a2xaP= {document body, if needed; NOTE: when possible, the response SHOULD contain a short hypertext note with a hyperlink to the newly created resource (bark) URI, the same returned in the Location header (also notice that, for the 202 status code, the Location header meaning is not standardized, thus the importance of a hipertext/hyperlink response)} <strong>202 Accepted Location: http://api.animals.com/v1/dogs/1/barks/a65h44</strong> </code></pre> <p>This way, each <code>bark</code> is traceable. The client can then issue a <code>GET</code> to the <code>bark</code> URI to know it's current state. Maybe even use a <code>DELETE</code> to cancel it.</p> <p><br></p> <h2>2. bark sends an e-mail to <code>dog.email</code> and then increments <code>dog.barkCount</code> by 1</h2> <p>This one can be trickier, if you want to let the client know the <code>dog</code> resource gets changed:</p> <pre><code>POST /v1/dogs/1/barks HTTP/1.1 Host: api.animals.com Authorization: Basic mAUhhuE08u724bh249a2xaP= {document body, if needed; when possible, containing a hipertext/hyperlink with the address in the Location header -- says the standard} <strong>303 See Other Location: http://api.animals.com/v1/dogs/1</strong> </code></pre> <p>In this case, the <code>location</code> header's intent is to let the client know he should take a look at <code>dog</code>. From the <a href="https://tools.ietf.org/html/rfc2616#section-10.3.4" rel="noreferrer">HTTP RFC about <code>303</code></a>:</p> <blockquote> <p>This method exists primarily to allow the output of a <strong><code>POST</code>-activated script</strong> to redirect the user agent to a selected resource.</p> </blockquote> <p>If the task is asynchronous, a <code>bark</code> subresource is needed just like the <code>1.2</code> situation and the <code>303</code> should be returned at a <code>GET .../barks/Y</code> when the task is complete.</p> <p><br></p> <h2>3. bark creates a new "<code>bark</code>" record with <code>bark.timestamp</code> recording when the bark occured. It also increments <code>dog.barkCount</code> by 1.</h2> <pre><code>POST /v1/dogs/1/barks HTTP/1.1 Host: api.animals.com Authorization: Basic mAUhhuE08u724bh249a2xaP= (document body, if needed) <strong>201 Created Location: http://api.animals.com/v1/dogs/1/barks/a65h44</strong> </code></pre> <p>In here, the <code>bark</code> is a created due to the request, so the status <code>201 Created</code> is applied.</p> <p>If the creation is asynchronous, a <code>202 Accepted</code> is required (<a href="https://tools.ietf.org/html/rfc2616#section-10.2.2" rel="noreferrer">as the HTTP RFC says</a>) instead.</p> <p>The timestamp saved is a part of <code>bark</code> resource and can be retrieved with a <code>GET</code> to it. The updated dog can be "documented" in that <code>GET dogs/X/barks/Y</code> as well.</p> <p><br></p> <h2>4. bark runs a system command to pull the latest version of the dog code down from Github. It then sends a text message to <code>dog.owner</code> telling them that the new dog code is in production.</h2> <p>The wording of this one is complicated, but it pretty much is a simple asynchronous task:</p> <pre><code>POST /v1/dogs/1/barks HTTP/1.1 Host: api.animals.com Authorization: Basic mAUhhuE08u724bh249a2xaP= (document body, if needed) <strong>202 Accepted Location: http://api.animals.com/v1/dogs/1/barks/a65h44</strong> </code></pre> <p>The client then would issue <code>GET</code>s to <code>/v1/dogs/1/barks/a65h44</code> to know the current state (if the code was pulled, it the e-mail was sent to the owner and such). Whenever the dog changes, a <code>303</code> is appliable.</p> <p><br></p> <h2>Wrapping up</h2> <p>Quoting <a href="http://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post" rel="noreferrer">Roy Fielding</a>:</p> <blockquote> <p>The only thing REST requires of methods is that they be uniformly defined for all resources (i.e., so that intermediaries don’t have to know the resource type in order to understand the meaning of the request).</p> </blockquote> <p>In the above examples, <code>POST</code> is uniformly designed. It will make the dog "<code>bark</code>". That is not safe (meaning bark has effects on the resources), nor idempotent (each request yields a new <code>bark</code>), which fits the <code>POST</code> verb well.</p> <p>A programmer would know: a <code>POST</code> to <code>barks</code> yields a <code>bark</code>. The response status codes (also with entity-body and headers when necessary) do the job of explaining what changed and how the client can and should proceed.</p> <p><sub>Note: The primary sources used were: "<a href="https://rads.stackoverflow.com/amzn/click/0596529260" rel="noreferrer">Restful Web Services</a>" book, the <a href="https://tools.ietf.org/html/rfc2616" rel="noreferrer">HTTP RFC</a> and <a href="http://roy.gbiv.com/untangled" rel="noreferrer">Roy Fielding's blog</a>.</sub></p> <p><br> <br></p> <hr> <p><strong>Edit:</strong></p> <p>The question and thus the answer have changed quite a bit since they were first created. The <strong>original question</strong> asked about the design of a URI like:</p> <pre><code>ACTION http://api.animals.com/v1/dogs/1/?action=bark </code></pre> <p>Below is the explanation of why it is not a good choice:</p> <p>How clients tell the server <strong>WHAT TO DO</strong> with the data is the <em>method information</em>.</p> <ul> <li>RESTful web services convey method information in the HTTP method.</li> <li>Typical RPC-Style and SOAP services keep theirs in the entity-body and HTTP header.</li> </ul> <p><strong>WHICH PART</strong> of the data [the client wants the server] to operate on is the <em>scoping information</em>.</p> <ul> <li>RESTful services use the URI. SOAP/RPC-Style services once again use the entity-body and HTTP headers.</li> </ul> <p>As an example, take Google's URI <code>http://www.google.com/search?q=DOG</code>. There, the method information is <code>GET</code> and the scoping information is <code>/search?q=DOG</code>.</p> <p>Long story short:</p> <ul> <li>In <strong>RESTful architectures</strong>, the method information goes into the HTTP method.</li> <li>In <strong>Resource-Oriented Architectures</strong>, the scoping information goes into the URI.</li> </ul> <p>And the rule of thumb:</p> <blockquote> <p>If the HTTP method doesn’t match the method information, the service isn’t RESTful. If the scoping information isn’t in the URI, the service isn’t resource-oriented.</p> </blockquote> <p>You can put the <em>"bark"</em> <em>"action"</em> in the URL (or in the entity-body) and use <code>POST</code>. No problem there, it works, and may be the simplest way to do it, <strong>but this isn't RESTful</strong>.</p> <p>To keep your service really RESTful, you may have to take a step back and think about what you really want to do here (what effects will it have on the resources).</p> <p>I can't talk about your specific business needs, but let me give you an example: Consider a RESTful ordering service where orders are at URIs like <code>example.com/order/123</code>.</p> <p>Now say we want to cancel an order, how are we gonna do it? One may be tempted to think that is a <em>"cancellation"</em> <em>"action"</em> and design it as <code>POST example.com/order/123?do=cancel</code>.</p> <p>That is not RESTful, as we talked above. Instead, we might <code>PUT</code> a new representation of the <code>order</code> with a <code>canceled</code> element sent to <code>true</code>:</p> <pre><code>PUT /order/123 HTTP/1.1 Content-Type: application/xml &lt;order id="123"&gt; &lt;customer id="89987"&gt;...&lt;/customer&gt; &lt;canceled&gt;true&lt;/canceled&gt; ... &lt;/order&gt; </code></pre> <p>And that's it. If the order can't be canceled, a specific status code can be returned. <sup>(A subresource design, like <code>POST /order/123/canceled</code> with the entity-body <code>true</code> may, for simplicity, also be available.)</sup></p> <p>In your specific scenario, you may try something similar. That way, while a dog is barking, for example, a <code>GET</code> at <code>/v1/dogs/1/</code> could include that information <sup>(e.g. <code>&lt;barking&gt;true&lt;/barking&gt;</code>)</sup>. Or... if that's too complicated, loosen up your RESTful requirement and stick with <code>POST</code>.</p> <h3>Update:</h3> <p>I don't want to make the answer too big, but it takes a while to get the hang of exposing an algorithm (an <em>action</em>) as a set of resources. Instead of thinking in terms of actions (<em>"do a search for places on the map"</em>), one needs to think in terms of the results of that action (<em>"the list of places on the map matching a search criteria"</em>).</p> <p>You may find yourself coming back to this step if you find that your design doesn't fit HTTP's uniform interface.</p> <p>Query variables <strong>are</strong> <em>scoping information</em>, but do <strong>not</strong> denote new resources (<code>/post?lang=en</code> is clearly the <strong>same</strong> resource as <code>/post?lang=jp</code>, just a different representation). Rather, they are used to convey <strong>client state</strong> (like <code>?page=10</code>, so that state is not kept in the server; <code>?lang=en</code> is also an example here) or <strong>input parameters</strong> to <em>algorithmic resources</em> (<code>/search?q=dogs</code>, <code>/dogs?code=1</code>). Again, not distinct resources.</p> <h2>HTTP verbs' (methods) properties:</h2> <p>Another clear point that shows <code>?action=something</code> in the URI is not RESTful, are the properties of HTTP verbs:</p> <ul> <li><code>GET</code> and <code>HEAD</code> are safe (and idempotent);</li> <li><code>PUT</code> and <code>DELETE</code> are idempotent only;</li> <li><code>POST</code> is neither.</li> </ul> <p><strong>Safety</strong>: A <code>GET</code> or <code>HEAD</code> request is a request to <strong>read</strong> some data, not a request to change any server state. The client can make a <code>GET</code> or <code>HEAD</code> request 10 times and it's the same as making it once, or <em>never making it at all</em>.</p> <p><strong>Idempotence</strong>: An idempotent operation in one that has the same effect whether you apply it once or more than once (in math, multiplying by zero is idempotent). If you <code>DELETE</code> a resource once, deleting again will have the same effect (the resource is <code>GONE</code> already).</p> <p><sup><sub><code>POST</code> is neither safe nor idempotent. Making two identical <code>POST</code> requests to a 'factory' resource will probably result in two subordinate resources containing the same information. With overloaded (method in URI or entity-body) <code>POST</code>, all bets are off.</sub></sup></p> <p>Both these properties were important to the success of the HTTP protocol (over unreliable networks!): how many times have you updated (<code>GET</code>) the page without waiting until it is fully loaded?</p> <p>Creating an <em>action</em> and placing it in the URL clearly breaks the HTTP methods' contract. Once again, the technology allows you, you can do it, but that is not RESTful design.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload