You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
14 KiB
287 lines
14 KiB
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
<meta http-equiv="content-type" content="text/html; charset=utf-8"> |
|
|
|
<!-- Enable responsiveness on mobile devices--> |
|
<!-- viewport-fit=cover is to support iPhone X rounded corners and notch in landscape--> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, viewport-fit=cover"> |
|
|
|
<title>Julio Biason .Me 4.3</title> |
|
|
|
<!-- CSS --> |
|
<link rel="stylesheet" href="https://blog.juliobiason.me/print.css" media="print"> |
|
<link rel="stylesheet" href="https://blog.juliobiason.me/poole.css"> |
|
<link rel="stylesheet" href="https://blog.juliobiason.me/hyde.css"> |
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700|Abril+Fatface"> |
|
|
|
|
|
|
|
|
|
|
|
</head> |
|
|
|
<body class=" "> |
|
|
|
<div class="sidebar"> |
|
<div class="container sidebar-sticky"> |
|
<div class="sidebar-about"> |
|
|
|
<a href="https://blog.juliobiason.me"><h1>Julio Biason .Me 4.3</h1></a> |
|
|
|
<p class="lead">Old school dev living in a 2.0 dev world</p> |
|
|
|
|
|
</div> |
|
|
|
<ul class="sidebar-nav"> |
|
|
|
|
|
<li class="sidebar-nav-item"><a href="/">English</a></li> |
|
|
|
<li class="sidebar-nav-item"><a href="/pt">Português</a></li> |
|
|
|
<li class="sidebar-nav-item"><a href="/tags">Tags (EN)</a></li> |
|
|
|
<li class="sidebar-nav-item"><a href="/pt/tags">Tags (PT)</a></li> |
|
|
|
|
|
</ul> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="content container"> |
|
|
|
<div class="post"> |
|
<h1 class="post-title">Couchbase Example and REST</h1> |
|
<span class="post-date"> |
|
2016-01-12 |
|
|
|
<a href="https://blog.juliobiason.me/tags/rest/">#rest</a> |
|
|
|
<a href="https://blog.juliobiason.me/tags/couchbase/">#couchbase</a> |
|
|
|
<a href="https://blog.juliobiason.me/tags/example/">#example</a> |
|
|
|
<a href="https://blog.juliobiason.me/tags/restful/">#restful</a> |
|
|
|
</span> |
|
<p>Using the example Couchbase to show how REST works.</p> |
|
<span id="continue-reading"></span> |
|
<p>Let me start this by pointing that I'm a RESTnazi: I'm the kind of guy that |
|
will get into a fight with anyone that says things like "Ok, that's because |
|
this is just REST, not RESTful" because... well, because, there is no |
|
diference between REST and RESTful.</p> |
|
<p>And today I found something weird while reading |
|
<a href="http://developer.couchbase.com/documentation/server/4.1/travel-app/travel-app-walkthough.html">the Couchbase documentation</a> |
|
with them claiming that their example is REST while... well, it isn't.</p> |
|
<p>But hey, that's a good opportunity to explain a bit what is REST (and what is |
|
not).</p> |
|
<h2 id="what-is-rest">What is REST?</h2> |
|
<p>REST is an architecture/design pattern/pick your buzzword built on top of HTTP |
|
to provide information. It has two components:</p> |
|
<ul> |
|
<li> |
|
<p><strong>Resources</strong>: That's the elements in your system: Your users, your books, |
|
your airports, your flights and such.</p> |
|
</li> |
|
<li> |
|
<p><strong>Verbs</strong>: Those are the things you do with your resources: You GET them, |
|
you UPDATE them, and so on.</p> |
|
</li> |
|
</ul> |
|
<p>There is no true "guideline" on how to write resources. It's usually done with |
|
nouns in their plural form (or, at least, that's what <a href="http://apigee.com/about/">Apigee</a> |
|
concluded after checking a bunch of APIs around). Those resources are mapped |
|
through URLs with some base.</p> |
|
<p>Let's pick the example from Couchbase: It's a travel app, with airports, |
|
flights and flight paths. We could use a base URI scheme of |
|
<code>/travel/api/v1.0/</code> because:</p> |
|
<ol> |
|
<li> |
|
<p>The travel app could also provide a user interface through <code>/travel/</code>, so |
|
we keep the API endpoint on <code>api</code> to not mix things.</p> |
|
</li> |
|
<li> |
|
<p>We are versioning the API (here, v1.0). This is a recommendation from |
|
Apigee and, again, not part of the architecture/design patter/buzzword.</p> |
|
</li> |
|
</ol> |
|
<p>On the top of this base URI, we'll build our resource URLs:</p> |
|
<ul> |
|
<li><code>/travel/api/v1.0/airports/</code> and</li> |
|
<li><code>/travel/api/v1.0/flights/</code></li> |
|
</ul> |
|
<p>"Where is the flight path endpoint?", you must be asking? Well, I'll tell you |
|
later about it, hold on a second, but we'll use those two to explain the very |
|
basic of REST first, ok?</p> |
|
<p>Besides those two URIs, we need two more: One for each resource to access |
|
direct elements. So now we have:</p> |
|
<ul> |
|
<li><code>/travel/api/v1.0/airports/</code>;</li> |
|
<li><code>/travel/api/v1.0/airports/{airport_id}</code>;</li> |
|
<li><code>/travel/api/v1.0/flights/</code> and finally</li> |
|
<li><code>/travel/api/v1.0/flights/{flight_id}</code>.</li> |
|
</ul> |
|
<p>So, now that we have our resources, we need ways to manage their contents. For |
|
this, we use the "verbs" I mentioned before. The thing about rest is that |
|
those actions are directly tied to the HTTP verbs:</p> |
|
<ul> |
|
<li><strong>GET</strong> will retrieve elements in the resource;</li> |
|
<li><strong>POST</strong> will insert a new element in the resource;</li> |
|
<li><strong>PUT</strong> is used to update the information of an element [#put]_;</li> |
|
<li><strong>DELETE</strong> is used to remove an element from the resource [#delete]_.</li> |
|
</ul> |
|
<div style="border:1px solid grey; margin:7px; padding: 7px"> |
|
<p>If you want an easy mnemonic, "PUT" has and "U", for "update". Yes, it's silly, |
|
but it works (at least, for me). Also, a "PUT" directly on a resource means |
|
"replace the whole database with this information" and, thus, not not really |
|
widespread.</p> |
|
|
|
</div> |
|
<div style="border:1px solid grey; margin:7px; padding: 7px"> |
|
<p>You can add a DELETE for your whole resource, if you're crazy and bold enough.</p> |
|
|
|
</div> |
|
<p>And adding those two we have:</p> |
|
<ul> |
|
<li>Get a list of all airports: <code>GET /travel/api/v1.0/airports/</code></li> |
|
<li>Add a new airport: <code>POST /travel/api/v1.0/airports/</code></li> |
|
<li>Get information of a single airport: <code>GET /travel/api/v1.0/airport_3577</code></li> |
|
<li>Update the information of an airport: <code>PUT /travel/api/v1.0/airport_3577</code></li> |
|
</ul> |
|
<p>... and so on.</p> |
|
<p>Easy as pie, right?</p> |
|
<h2 id="the-flight-path-resource">The "Flight Path" resource</h2> |
|
<p>Now let's go back to the "flight path" resource, which I left behind. Thing |
|
is, a flight path does not exist on its own. If a flight doesn't exist, the |
|
flight path doesn't exist either, right? And if I flight exist, it should have |
|
a path, right?</p> |
|
<p>So a flight path is a resource linked directly to our resource of flights. For |
|
this, REST allows resource chaining by just adding another layer on top of |
|
existing URIs. As we pointed before, a flight path <strong>needs</strong> a flight (a |
|
flight <em>element</em>, just to make more clear where I'm going for with this), so |
|
we should build the resource on top of an element URI:</p> |
|
<ul> |
|
<li><code>/travel/api/v1.0/flights/airline_24/paths</code> and</li> |
|
<li><code>/travel/api/v1.0/flights/airline_24/paths/{path_id}</code></li> |
|
</ul> |
|
<p>... although the last one only makes sense if a flight could have two (or |
|
more) different paths, which would make sense if it goes one way in a path and |
|
goes back in a different path, which I do not know enough about flights to |
|
know if this is possible, but for the sake of explaining everything about |
|
REST, let's go with it, mkay?</p> |
|
<p>And now you may be wondering: Why not simply do |
|
<code>/travel/api/v1.0/flightpaths/{path_id}</code>? Again, because flight paths are tied |
|
to flights, this means the base resource for the flight won't even exist and, |
|
thus, it's sub-resources won't be available, which makes a lot of sense.</p> |
|
<h2 id="filtering-results">Filtering results</h2> |
|
<p>Ok, now we know how to retrieve all airports, which is nice, but we don't want |
|
them all: the user will type something and we'll show them only the airports |
|
that match their search. We could screw the user and send the whole list to |
|
them and let the application filter it locally, abusing the user bandwidth and |
|
CPU power -- which isn't nice, since we have a database on our side that can |
|
do this filtering faster.</p> |
|
<p>Because we can use URIs only to point to resources and resource elements, we |
|
need a different way of passing this to the server. And guess what? HTTP have |
|
the proper way to do this: querystrings and forms.</p> |
|
<p>Querystrings, for those unfamiliar with HTTP, are the things can come after |
|
the "?" in the URL. For example, in the URL: |
|
"<code>http://example.com/sayname?name=julio</code>", "<code>name=julio</code>" is the querystring. |
|
It provides a key ("name") and a value ("julio"). Forms are basically the |
|
same, but instead of being part of the URL, they are sent in the body of the |
|
HTTP request (and can be much, much larger than querystrings).</p> |
|
<p>There is one more thing about querystrings and forms: The only way to send |
|
information to the server in a <code>GET</code> request is through querystrings, since |
|
GETs do not have a body. DELETEs can have a body, but the RFC says it should |
|
be ignored. POST and PUT do have bodies and, thus, information about the |
|
element to be added/updated should come in there.</p> |
|
<p>So, for filtering, we could have a "filter" querystring to filter elements. |
|
Couchbase filters airports with a single querystring, so we could simply do</p> |
|
<p><code>GET /travel/api/v1.0/airports/?filter=<user input></code></p> |
|
<p>So the user will see a bunch of airports with their input. And, since we have |
|
all the airport, we could also link the flights as a subresource of it, with:</p> |
|
<p><code>GET /travel/api/v1.0/airports/<airport_id>/flights/</code></p> |
|
<p>... which we didn't mention before, but it is now making sense, right?</p> |
|
<p>Couchbase example also allows showing which flights connect two airports and |
|
the REST way is, again, using querystrings:</p> |
|
<p><code>GET /travel/api/v1.0/airports/<airport_id>/flights/?connectedTo=<airport_id></code></p> |
|
<p>And, if you want to be nice enough, you could even add a "fields" parameter, |
|
so your API consumers could filter out fields they don't want in the results, |
|
to reduce the bandwidth required. But it's all up to you.</p> |
|
<p>Weird how things make absolute sense here, and we never called the "flights" |
|
resource, right? That's one of the things about REST: you build resources in a |
|
way that make sense for the <strong>consumer</strong> of the API, not to reflect your |
|
database.</p> |
|
<h2 id="pagination">Pagination</h2> |
|
<p>Just for the sake of completeness, let's talk a bit about pagination.</p> |
|
<p>Pagination, in REST, works for getting all the elements in the resource, so |
|
it's used in the GET request for the resource. And, because it's part of the |
|
GET request, it should come in the querystring.</p> |
|
<p>There are a couple of ways of doing pagination, in this case:</p> |
|
<ul> |
|
<li> |
|
<p>Let the consumer specify page size and page count: In this case, you could |
|
have a query string like <code>count=15&page=2</code> to retrieve the elements from the |
|
second page of 15 elements each. This is the most common way of doing |
|
pagination and Twitter is one good example of this.</p> |
|
</li> |
|
<li> |
|
<p>Have a hardcoded pagesize: Same as before, but the only option available is |
|
<code>page=2</code>.</p> |
|
</li> |
|
<li> |
|
<p>Have the consumer specify the last seen element and page size. So the first |
|
request would have something like <code>count=15</code> to retrieve the first 15 |
|
elements, but the next request would have the last element in the list as a |
|
parameter, like <code>count=15&lastSeen=16</code> and the server would return all |
|
elements that come after the element with id "16". This prevents duplication |
|
in the results in case a new element is added. Reddit uses this in their |
|
API.</p> |
|
</li> |
|
</ul> |
|
<h2 id="the-type-of-response">The type of response</h2> |
|
<p>Again, for the sake of completeness, you may have noticed that not even once I |
|
mentioned the type of data to be returned in each step. That's because REST |
|
does not have a format: You could build a whole service that returns HTML |
|
pages in REST format, and that's ok; you could return JSON, which the |
|
Couchbase documentation points correctly that it is the most widely used |
|
format; you could return XML; if you're crazy enough and want to return in |
|
COBOL format, go for it!</p> |
|
<h2 id="so-where-the-example-fails-to-be-rest">So, where the example fails to be REST?</h2> |
|
<ol> |
|
<li> |
|
<p>All paths are marked with "findAll". "findAll" is <strong>not</strong> a resource and, |
|
thus, shouldn't be in the URL.</p> |
|
</li> |
|
<li> |
|
<p>As I pointed, flight paths are actually a sub-resource of flights and |
|
should be linked. Flight paths should <strong>not</strong> exist if the flight doesn't |
|
exist.</p> |
|
</li> |
|
</ol> |
|
<p>The flight path query uses querystrings to retrieve the information for paths |
|
that go through two airports, which is the right way of doing, but again, it |
|
shouldn't be a resource on itself.</p> |
|
<h2 id="how-to-fix-the-documenation">How to fix the documenation</h2> |
|
<p>Easy way? Remove the "REST" mention in the pages. I <em>am</em> nitpicking the word |
|
"REST" there, I fully reckonize it, and I understand that for the sake of |
|
example it doesn't have to be REST, but it seems wrong to tell people |
|
something is REST when it isn't.</p> |
|
<p>If Oracle decided to say "we added a field type that can store huge amounts |
|
of JSON data, and although you can't query its content, we can now say |
|
OracleDB is a NoSQL database", people would lose their minds. But that's kinda |
|
like I'm feeling about this whole thing.</p> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
</div> |
|
|
|
</body> |
|
|
|
</html>
|
|
|