16 May 2012

API Example Using REST

In the last post I talked about the non-RESTfulness of most "REST" api implementations. I will attempt to show a more RESTful implementation and some examples of how this benefits the software. While researching this topic, it became clear (by both lack of examples and poor examples) that this is a tough concept. Before I jump into the example, lets examine why its so hard - because these issues will drive some of the design.

Difficulties with API and REST

An Application Programming Interface (API) is supposed to be:

a set of functions, procedures, methods or classes used by computer programs to request services from the operating system, software libraries or any other service providers running on the computer.
And when creating a traditional API, you come up with methods and data formats to tell people how to "talk" to the system. But one of the primary REST tenets as mentioned by Roy Fielding is his blog is that you NOT have "out-of-band information driving interaction instead of hypertext." To put more simply, you should not pre-define the format of the data or the methods to be used, they should be discovered. But isn't that what an API is? How does one define the methods and the data formats but not have to know the methods or data formats? And why should I follow this "silly rule" anyway?

Well, the silly rule is the brilliance of REST and also what allows for the incredible flexibility that is the internet as we know today. If we know the format or the calls to make ahead of time, and write software against those, the control is no longer in the data providers hands. The control has shifted back from server to client. To understand the problem with this better, imagine that you wrote a custom browser and hard-coded it to a specific news article page with a fixed format and calling it silly that the news site wants to change the url or page format. (This example is stretched a bit far because an API has the understanding of being slightly more permanent than a generic webpage, but it still applies in spirit to RESTful APIs.)

The solution here is that there was a loophole of sorts, baked into the "Rules of REST" - note the last part in the rule: "out-of-band information driving information instead of hypertext." You can tell the client what it is allowed to do, as long as its part of the data (hypertext) being returned. The "media type" can have the information about what is allowed and what format things should be in! This, combined with the specifics of our chosen protocol (HTTP here), should give us all we need. So how do we do that?

REST Example

In the examples in the last post, the user logged in, searched for a product and created an order in both a traditional website and with a traditional API. So lets now make a REST version:

NOTE: I am going to ignore security at the beginning because it doesn't help in understanding the example, but I will discuss what could be done at the end.

Client starts with the root URL www.example.com/api/ and a discoverable media type apiIndex-v1+xml.

GET / www.example.com/api/ HTTP/1.1
Accept: application/vnd.example.coolapp.apiIndex-v1+xml

Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.example.coolapp.apiIndex-v1+xml
<apiIndex>
  <link>
    <description>Customers</description>
    <href>http://www.example.com/api/customers</href>
    <type>application/vnd.example.coolapp.customers-v1+xml</type>
  </link>
  <link>
    <description>Products</description>
    <href>http://www.example.com/api/products</href>
    <type>application/vnd.example.coolapp.products-v1+xml</type>
  </link>
  <link>
    <description>Carts</description>
    <href>http://www.example.com/api/carts</href>
    <type>application/vnd.example.coolapp.carts-v1+xml</type>
  </link>
  <link>
    <description>Orders</description>
    <href>http://www.example.com/api/orders</href>
    <type>application/vnd.example.coolapp.orders-v1+xml</type>
  </link>
  <link>
    <description>Sessions</description>
    <href>http://www.example.com/api/sessions</href>
    <type>application/vnd.example.coolapp.sessions-v1+xml</type>
  </link>
  <link>
    <description>API Help</description>
    <href>http://www.example.com/api/help</href>
    <type>text/html</type>
  </link>
</apiIndex>

Here I have defined a set of valid hyperlinks the client can travel to from the root. It is reasonable to assume that the client could get more stuff or less stuff depending on what the business wanted to provide at the root, or based on what the user is authorized to use. This exchange would be the equivalent of a generic "index.html" page for the web. The client could show the descriptions as buttons or a drop down or whatever makes sense for the client (but it doesn't matter at the API level because it is not providing a page to be rendered, just resources to be processed as the client sees fit).

Lets say the client chooses to view a list of products, but does not know the allowed operations - the client could then perform an HTTP OPTIONS call against the resource to get the list (there are few standards for the format of the response of an OPTIONS call, but I went with a custom response body for the API to show a useful example):

OPTIONS /api/products
Response:
HTTP/1.1 200 OK
ALLOW: HEAD,GET,OPTIONS
Content-Type:application/vnd.example.coolapp.options-v1+xml
Content-Length: 1032
<options>
  <methods>
    <method>
      <type>GET</type>
      <description>Retrieve a list of products</description>
      <parameters>
        <parameter>
          <name>Keyword</name>
          <type>string</type>
          <required>false</required>
        </parameter>
        <parameter>
          <name>MaxResults</name>
          <type>integer</type>
          <required>false</required>
        </parameter>
        <parameter>
          <name>StartIndex</name>
          <type>integer</type>
          <required>false</required>
        </parameter>        
      </method>
    </methods>
  ...
</options>

Now seeing the options and the calling parameters, the client then provides a product search entry form in its UI, and then decides to perform the search against the API:

GET /api/products?Keyword=green%20widget

Response:
HTTP/1.1 200 OK
Content-Type:application/vnd.example.coolapp.product-v1+xml
Content-Length: 1032
<products>
  <resultInformation>
    <totalItems>3923</totalItems>
    <maxResults>15</maxResults>
    <maxBytes>10000</maxBytes>
    <startIndex>1</startIndex>
    <endIndex>15</endIndex>
  </resultInformation>
  <product>
    <id>12343</id>
    <description>389349 green widget with bells</description>
    <price currencyCode="USD">3.56</price>
    <link>
      <description>Product 12343</description>
      <href>http://www.example.com/api/products/12343</href>
      <type>application/vnd.example.coolapp.product-v1+xml</type>
    </link>
  </product>
  <product>
    <id>2343</id>
    <description>2343 green widget copper clad</description>
    <price currencyCode="USD">4.93</price>
    <link>
      <description>Product 2343</description>
      <href>http://www.example.com/api/products/2343</href>
      <type>application/vnd.example.coolapp.product-v1+xml</type>
    </link>
  </product>
  ...
</products>

The client then processes the results and allows the user to add items to a cart. This can be done against a cart resource so that the cart object is validated by the server (minimum quantities, availability, etc) and so that the client can save the cart if it doesn't want to commit to an order just yet:

POST /api/carts
Content-Type:application/vnd.example.coolapp.cart-v1+xml
Content-Length: 1032
<cart>
  <customerId>1343</customerId>
  <lineItems>
    <lineItem>
      <productId>12343</productId>
      <quantity>4</quantity>
    </lineItem>
    <lineItem>
      <productId>39293</productId>
      <quantity>2</quantity>
    </lineItem>
    ...
  </lineItems>
</cart>

Response:
HTTP/1.1 201 Created
Location: /api/carts/323392

Now that the cart is all set, perhaps the client decides to create an order:

POST /api/orders
Content-Type: application/vnd.example.coolapp.order-v1+xml
Content-Length: 2939
<order>
  <customerId>1343</customerId>
  <lineItems>
    <lineItem>
      <productId>12343</productId>
      <quantity>4</quantity>
    </lineItem>
    <lineItem>
      <productId>39293</productId>
      <quantity>2</quantity>
    </lineItem>
    ...
  </lineItems>
</order>

Response:
HTTP/1.1 201 Created
Location: /api/orders/O293920

That is the basic REST API example.

Security Aside

Let me walk through some of the security handling in this example since it can be confusing the first time you work through it. When you hit the index page for the API, the server would likely be expecting a valid session token in the form of an "Authorization" header so that we can authorize access to resources appropriately. If that header is not present, the server could send back a 302 redirect to a session resource (so that the client could submit a username and password to get a valid session) like so:

GET /api HTTP/1.1
Accept: application/vnd.example.coolapp.apiIndex-v1+xml
Response:
HTTP/1.1 302 Moved
Location: http://www.example.com/api/session

At which point the client could do an OPTIONS to learn the valid session options (not shown), then POST credentials to get a new session resource back:

POST /api/session
Content-Type: application/vnd.example.coolapp.sessionCredentials-v1+xml
Content-Length: 100
<sessionCredentials>
  <username>joe</username>
  <password>opensesame</password>
</sessionCredentials>
Response:
HTTP/1.1 201 Created
Location: http://www.example.com/api.session/74823
Content-Type: application/vnd.example.coolapp.session-v1+xml
Content-Length: 203
<session>
  <id>74823</id>
  <token>293929FDAAECD3293FFA32</token>
  <username>joe</username>
</session>

Typically, you could do something similar to all resources, but probably using 401 Not Authorized instead of the redirect since you really want the user to go through the index page instead of "knowing" the URL ahead of time. This is just a quick example of security and there are a lot of security vulnerabilities here that you should be careful to avoid. Plus, the client would have to start over at the index page, using the valid token - which is a little awkward. There are dozens of different ways to handle security, like OAuth, BASIC Authentication, etc, so more research is warranted with this topic, but you get the basic idea.

So now let me talk about some of the nuances with the flow.

Notes about REST APIs

I am going to parallel these comments with my interpretation of the "rules" that Mr. Fielding presented in his REST blog post.

  1. The only thing the client should know ahead of time is the root URL.  It shouldn't know or expect as specific resource to be available. For example, the client can't assume an "order" resource or a "search" resource - those should be provided as choices to the client from the server.

The first thing to note is that although the client only knows the root URL, it still must be coded to handle the link structure that was defined for the root, plus the media types that were presented. It is very difficult to avoid writing something akin to a browser when consuming a REST API. To create a client properly in this example, it should handle the creation or deletion of links on the index page, and gracefully handle any unknown media types that are presented. Otherwise, you are just basically making an RPC call, because you both know the format and nothing can change without both sides changing. That destroys the REST concept and prevents changes from occurring as seamlessly as it should (such as the host deciding to change the URL, or alter the flow through the API.)

  1. "A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types."

The bulk of what can be done or what is available is meant to be part of the object that is returned. You will notice above that I included a special "resultInformation" block in the product search results. This allows the client to present a "1 of X" link in the app, or make multiple requests to cycle over the results from the server (and limit the bandwidth from the server). Also you will notice that the flow through the API does not jump around, for example, already "knowing" the URL of orders. You don't just jump to /api/orders/123, because the server may have moved it, or deleted it, or you may not be authorized to view it. If you want to give the client the ability to view orders, you create an orderView resource that returns a displayable form of the order and lets the client pick from a list. (server is in control what is available).

  1. "A REST API should not contain any changes to the communication protocols aside from filling-out or fixing the details of under specified bits of standard protocols, such as HTTP’s PATCH method or Link header field."

You will notice above that I presented a use of the HTTP OPTIONS method to assist with the consumption of the API, but tried to stay within the bounds of what is "standard" HTTP. In a normal non-REST API, these method signatures are predefined in a document and both sides code to them. If you do that in REST, you couple the client and server so that neither may change without the other changing. You want the server to decide what is presented and make the client smart enough to handle those choices. Again, it is very difficult to write a client that that is not browser-like and is a little unnatural for an API, but gives great power to the server to evolve.

Again, I have been more long-winded with my post that I would like, but hopefully it gives some value to the developers and REST-ees out there. This was a very difficult post for me to come up with because I had to constantly focus on the REST principles and avoid the classic API mindset. I found it very helpful to discuss with colleagues and to compare what a browser does with what we are trying to get out of the API. There are lots of things that I didn't have space to discuss, like versioning, content-negotiation, internationalization, etc that make this a very rich communication platform to build on. I would appreciate any comments or questions about this flow and REST in general. I know that there are things I can do better, and things that likely need fixing (and that everyone is going to do it differently for their purposes since there is no "right way") so be sure and add a comment.

25 comments:

  1. Hi Jeremy
    I had some questions about your post. What's a good email address for you? I'm on charles dot crouch at gmail dot com.
    Thanks
    Charles

    ReplyDelete
  2. Your article has finally made the whole REST paradigm make sense!!

    ReplyDelete
  3. Regarding the state management for REST: The idea is to not have a state (which is why HTTP is a "stateless" protocol). Each request is supposed to stand on its own without the server needing to know what you did before. So the client could be hitting multiple servers, providing different information concurrently (think multiple tabs in a browser). The client has choices defined by the current resource representation - but it always has the option of starting a new request on a different server. Also, lets say the client has a property that allows or disallows a rendering of an object in the resource - this is perfectly fine. Just like a browser may or may not choose to show an image on a web page - or a hyperlink to a "bad site." But the server should still be the one that decides what is possible from the client. So the server is in charge of state choices, but not state transitions(except possibly authorization), and the client controls which transition to make.

    You are correct - the client would have to know how to render new elements, and to handle constantly changing resources from the server. (just like a browser can handle it when something new is inserted into the flow of web page navigation). The way this was handled in web land was to invent HTML and have generic constructs like "img" and "button" and "a href", which then instruct the client to perform generic activities - not specific to one server. The same would be required of a REST client that was doing things according to Fielding's idea.

    I agree that writing such a client would be very daunting (possibly impractical). It's kind of what Fielding was getting at when he said you should spend all your time on the representations - because coming up with an API equivalent to HTML would be difficult (especially making it generic enough to be reused by many clients). This is why many people (rightfully so for many projects) say that doing REST properly is overkill and chose to just use fixed URLs and access them with prior knowledge in the client. There is nothing wrong with that and its used by many great products very successfully. But realize that its not what Fielding was aiming for with REST - and he seems to take issue with those being called "REST". Doing it the non-pure REST way provides many positives, like a consistent, well understood protocol (HTTP), great handling of changing or multiple representations (content negotiation), etc. But since both sides are coupled - its really just the same as designing a proprietary communication layer (except you are kind of using "open sourced" protocol and "open sourced" representations). So the application cannot evolve without both sides changing in step, or in such a way that the server can handle multiple versions of the client (which is perfectly acceptable for many applications).

    By the way, you don't necessarily have to "boil the ocean" to solve this one. For example, Atompub attempts to do proper HATEOAS, but only for its limited scope of rss feeds. So their format is fairly small and limited, but solves the problem for their scope.

    [aside: I am going to write about the benefits of "true" REST, but haven't had time to circle back around and do some research for it - because I have the same issues with REST as you]

    ReplyDelete
  4. Yes, there just needs to be a representation that the client can process. REST does NOT mean having no knowledge of what you are going to get from a server (the REST client ASKS for the representation it wants - and possible gives a list of representations it can accept). In the web, both the server and the client know HTML (the client can render it, the server can provide it). That is prior knowledge, but its flexible enough that any content can be provided and the client can navigate it - regardless of what the server allows you to link to. The browser can cache links, but its perfectly acceptable to deny that request by the server. For a RESTful API, the same applies - you should ask for the home page, then get to everything in the API from that root (where every link could be different between subsequent sessions - however the server sees fit to provide them). But you still have to code something that both sides understand - you just have to make it generic enough that the basic navigation is permitted and discoverable by the client.

    ReplyDelete
  5. awesome! Nothing to comment more, just sharing!
    Thanks for this effort!

    ReplyDelete
  6. Great read... I've seen a couple of good posts on this topic recently, but no actual code snippets. Do you know of any good example projects that show HATEOAS? A jax-rs based sample would be great, resteasy perhaps..

    ReplyDelete
    Replies
    1. I have looked for good examples that are using HATEOAS and not found anything I would call a great example. The only actual HATEOAS examples I have run across (other than the www itself)are the coffee example (http://www.infoq.com/articles/webber-rest-workflow), atompub (atompub.org), and HATEOAS by Example (http://www.zienit.nl/blog/2010/01/rest/hateoas-by-example). But each has its own set of problems for me, and I wouldn't say they are great. I have used resteasy/jax-rs and I really like the way they do the syntax mapping from URL to code segment (better than the way .net does it). It makes for very clean code that is easy to read and understand. But they don't mention HATEOAS and there are very few examples of people doing HATEOAS in their projects with those tools.

      I found it very difficult to follow HATEOAS in this post, so I bet people don't really want to gamble on their own projects with it yet. It's a shame, because it gives you such power to control things on the back end. I plan to circle back around to it at my own job and trying to add HATEOAS to our API, but I may not have time to do it properly either.

      Delete
    2. "I have looked for good examples that are using HATEOAS and not found anything I would call a great example."

      As I mentioned in my earlier comment, I think that might have something to do with it being nearly, if not completely, impossible to live up to and write anything people would actually recognize as an application or service. I haven't examined the ones you mentioned up close but I will check them out for curiosity's sake. The only other example I see often is Google's Web Crawler, but I have to laugh because a web crawler is about the only kind of app that I can theoretically conceive of being RESTful. So unless you want to write a web (or, to be more exact, an API) crawler, REST might not be the right choice. I'm becoming more and more convinced, despite really wanting to like REST, that REST APIs exist just to be crawled, like a cat wanting its belly scratched. The only way to really get traction is if the API only speaks (and strictly conforms) to near universal entity structures but that has its own problems too.

      "it gives you such power to control things on the back end"

      Indeed, but is that an objectively good thing? I'm not so sure.

      And since I didn't mention it earlir, excellent article. It really addresses the elephant in the room well.

      Delete
  7. Hi Jeremy. A little late to the party, but thank you for your perspective on REST.

    I have recently been working on creating a REST API for a client and have found that in general the practical side of RESTful APIs is simply exposing services over HTTP without actually addressing much of the principals which Fielding was proposing - in particular HATEOAS.

    I'm certainly no expert on the subject, but I have done quite a bit of reading in the area to add to my own experiences of REST to try to gain a better understanding of the practical uses of true REST.

    Personally, I'm not sure the HATEOAS concept within service APIs is actually of much benefit. Don't misunderstand me, in theory, I can see advantages, but in practice it appears somewhat flawed.

    I've read arguments that a client should behave similarly to a web browser in that it "knows" how to handle HTML resources. I think this is incorrect, as a browser doesn't actually decide anything, it simply renders the resource in its described format (HTML, CSS, etc.) and the user then decides where to navigate based on the contextual data presented before him/her. I.e. a user invokes the service navigation. A system which sends requests to a RESTful API would need to know all sorts of information before knowing how to proceed, if provided with links. I know Fielding addressed this by describing the prior knowledge of media types, etc.

    The argument that a server should own its URL structure is of course correct, but distribution is typically done using a documented approach. The client developers need to know what URLs it can call, either by discovery or at a fixed location. My question is what really is wrong with the latter? If an additional resource is added, then of course a new link could be provided which allows discovery, but the client would need to understand its media type anyway in order to understand the resource structure. Why not also look up the fixed URL?

    If services are changed/removed/added to a remote API, then this is typically done by using versioning and deprecation, rather than rediscovery. Is a client expected to invoke the discovery requests every time it needs to add/update/delete a resource? I suppose the links could be cached.

    In your blog you mention 'you should not pre-define the format of the data or the methods to be used, they should be discovered'. I'm not sure I understand the 'format of the data' part of that sentence. If this was true, then how would a client (i.e. another system) understand what it was being told. In an XML response all information is effectively driven by a key (A string element or attribute). To know what that actually "means" requires prior knowledge. In your example, you perform an 'OPTIONS' request to '/api/products' which provides the described response. How would a client system know that the 'Keyword' parameter name is describing the parameter where the keywords are put. The client system would need to have prior knowledge of what 'Keyword' means in the context of the resource type.

    ReplyDelete
    Replies
    1. Andrew, I'm very curious to hear a reply for your post from Jeremy because I think the same.

      I see no total real decoupling between client and service even when using a more discoverable approach. In the end you will need to follow a specific documented protocol like the ATOM and also other particularities of the service itself for a real implementation.

      Also, I dont know any real implementation that would meet all the so praised RESTFull principles yet. Usually they have only the 2 levels of the richardson matury model[1], plus mimetypes (in some cases). I think the next step still requires too much effort compared to its benefits.

      [1]http://martinfowler.com/articles/richardsonMaturityModel.html

      Delete
    2. Andrew, sorry for the delay - being slammed at work. To directly answer your question:
      The client developers need to know what URLs it can call, either by discovery or at a fixed location. My question is what really is wrong with the latter?

      The problem with the latter is that as soon as you have a fixed location - you have coupled the client and the server. Now they must be changed in sync to make changes (think of a browser that must change because a URL on a site changes). Once they are coupled they must move in step with one another and must be controlled together (even with deprecation and new versions). You certainly can implement a service this way, and most are - but as soon as they are coupled, it is really no different than a completely proprietary communication protocol to custom objects on both sides (other than being able to use standard HTTP tools and not having to explain the protocol and such - which is a huge advantage, but its NOT REST and it misses the benefits).

      I too question the value of using HATEOAS within a service API. I stated several times that it is difficult and of questionable value. However, if one could develop a framework that is generic and usable in a service API, it would eliminate that coupling between client and server (and greatly empower both sides to develop independently - very similar to the way websites and browser have developed). The missing piece in the equations is an HTML like idea for a service API. Others have noted this need as well, but making something generic that others can use too is quite difficult. I attempted to demonstrate a proper HATEOAS example using REST but there is no standardization in my calls other than HTTP and XML formats. I discovery/browser like concept would need to be invented to make it more usable.

      Delete
    3. L,
      With discovery, the client and server could be decoupled (and basically are in my example). You are following a protocol implementation, but it does not mean that changes on one side necessitate changes on the other. Just because the two sides agree on a protocol does not mean that they are coupled and either side can follow or not follow the protocol as they see fit. In the same way that a browser and a website both know HTML, does not mean that they are coupled - they just agree on media types and protocol. The client can choose to show or not elements of the HTML and the server can choose to provide or not provide elements within the HTML. Either side can choose to follow the spec or not - there are just no guarantees to behavior if the sides don't follow the rules.

      Delete
    4. "The problem with the latter is that as soon as you have a fixed location - you have coupled the client and the server. Now they must be changed in sync to make changes (think of a browser that must change because a URL on a site changes)."

      Sure, the code for the browser doesn't have to change but you still have to change what you type in the address bar if you want what you were expected from that source, and how different is that really from changing the URL in your jQuery.get call so that it `err` isn't populated? It's just moving the change from the developer to the user, but the change is still necessary.

      Delete
    5. Let me see if I can't make my worry more concrete. It's one thing if the API only ever speaks in broadly adopted standards, e.g. it makes it clear that a Person will always be a http://schema.org/Person (or the data will always be an HTML documents for rendering, as in your example). It's quite another thing, in my opinion, if the schemas for the API's resourses are unique to the API, a case that is probably far more the rule than the exception. In those cases, I'm just as coupled to the API designer's idea of what that resource looks like as I would be to any URI or workflow it provides. And if I have to go to the docs for that, I might as well grab and use the URI while I'm at it.

      Delete
  8. "REST does NOT mean having no knowledge of what you are going to get from a server"

    While I'm with you on not really seeing how you couldn't have some knowledge, doesn't this directly contradict what Fielding says in #1:

    "The only thing the client should know ahead of time is the root URL. It shouldn't know or expect as specific resource to be available. For example, the client can't assume an "order" resource or a "search" resource - those should be provided as choices to the client from the server."

    This is where I start to throw up my hands at the idea of "true" REST. It seems to me that if you take Fielding literally, the only truly RESTful client you could ever write (assuming it isn't simply conceptually ruled out all together) would be one that would aptly be named "Life," because you "never know what you're going to get." And that pretty much means, as far as I can tell, a highly-generic browser of some sort, that would just display the current "choices" to the user somehow without ever knowing what it was presenting. Anything you try to do more than that is bound to introduce compromise to REST principles. In a sense, they strike me as self-defeating principles, the Ouroboros of software architecture. It strikes me as an ideal that cannot be achieved in fact, and can only be approximated according to the trade-offs of the developers. That's all fine and good, but it probably explains the conspicuous lack of examples of "true" REST clients.

    /endrant

    ReplyDelete
  9. Either I don't understand all of this, or someone just re-writing the history, my question, isn't this what we had with WSDL? API discovery, method types, parameters. simple fact is people become lazy and then started writing certain code pattern, after a while they realize oh! now we have to define what our API's and parameters, then they come up with some definition to do so, then follow it for a while (WSDL , Web Services, XML schemas) then again think why don't we simply do this in simple format, then comes, REST, simple key value JSON format, again after a while they think ok we need to define what our end points and data types, going back to square 1. never ending same loop.

    ReplyDelete
    Replies
    1. I share your frustration, it does seem similar in concept to SOAP, but there are some important differences you are missing. With WSDLs, your clients don't/can't dynamically change their behavior based on the information presented in the WSDL. You read the WSDL, then write you client against functions and structures defined there. If something changes, you need to change the client. A properly designed REST client would be able to "roll with the punches," so to speak, (just like a browser handles new features in a web page) as changes happen on the data presented by the server. The REST endpoints shouldn't just be thought of as RPC methods that can be called - the theory is that REST is more fluid than that (and there is another layer of interpretation that needs to go on at the client level) and the server provided data can change, expand, reduce, all while being discover-able by the consuming client. This is why a REST+API is so hard - because you usually know (have fixed) what you want from the server when you access it via an API - but REST was designed so that the information is discoverable, not pre-known. In my mind, SOAP is complicated, web-based RPC call - you can get data just like you did before with RPC, or proprietary calls, but now the protocol is agreed on cross-company so that everyone can call things the same way; whereas REST is a browser on the web - new information comes and goes, and you have a model for accessing/finding/exploring it. In the end, are you still getting structured data via a defined protocol? Yes, but if that is all you see, you are missing the paradigm change of giving all the control to the server - a change with allowed the web to exist.

      Delete
    2. Well I have no frustration and my point is in general, this is same cycle we're going towards. That's why I mentioned the example of JSON, in 90's we had this key value based data schemas, no type no namespaces, but then people found the issue and conflicts then started using XML well formed valid schemas first with DTDs then again xml schema, (same applies to REST and Web Services, I'm just taking one example), then after many years people become lazy and someone again started using key value pairs (you can call it JSON) and many new developers who didn't exist in 90s thought ok this is really cool and something new. But now I again see people trying to introduce namespaces data types into JSON (JDON-LD http://www.w3.org/TR/json-ld/). That's why I mentioned this is same cycle we're in. But I'm surprised to see why no much of development in declarative languages. SQL is there for decades, but it didn't move beyond from database access, (LINQ) is some what improvement)

      So my whole point is not about single aspect of your article, my point is we have done this before, probably with very little differences. and we doing it again. that's all

      My long time argument, when Java came people were excited started talking about platform independence, it's run on platform specific JVM, in that sense dBaseIII+ is platform independent, :)

      Delete
  10. Thankyou for the information.
    I am looking forward for using the amazon ec2 web services to use in my application.
    My question is, is there any way how i can use it, can i use amazon api in web application.?
    Can you help me in high level how can i do it possible?

    ReplyDelete
    Replies
    1. Sorry, I don't have any direct experience with ec2 web services. All of the work I have done has been home-grown services. All of the work I am doing currently is with microsoft webapi 2, and in the past I have used custom build services as well as java services using resteasy.

      Delete
  11. I'm a bit confused to how (using the premises in the article) you figured out how to form the POST /api/carts object representation? The details of lineItem, productId, customerId etc and the schema seems to be pulled out of nowhere.

    Or it seems as if it has been exchanged out-of-bands through some xml schema for the media type "application/vnd.example.coolapp.carts-v1+xml".

    Either way, to be RESTful, one would have to have a preconceived notion of a "cart" and the idea that it needs information like customerId and lineItems with productIds. But then the actual client code needs to discover the media type + schema description and on the fly maps these pieces of information to an actual representation that the service (at the moment) will understand.

    This, in a way, contradicts the idea that the client should not know anything about the api. What if the client got an api that used different terms for "lineItem" and "cart"? The discovery process would turn into a NLP problem.

    Indeed you mention that it is hard to do this correctly. But has it ever been demonstrated?

    ReplyDelete
  12. Yep, after designing many APIs on huge applications covering terabytes of different resource data, I have concluded that a true HATEAOS design can only exist in small applications that have few features.

    ReplyDelete
  13. Actually Roy says in #1: "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API)". You left out the media types as prior knowledge, which would indeed make it very hard for a client to communicate with the server.

    ReplyDelete
  14. Q: Creating an order and listing all items in the cart (already created) seems redundant. Why don't we create an order using the id of the created cart?

    ReplyDelete
    Replies
    1. That would be more efficient. However, the first thing the client does after creating an order is show an "invoice" type page with the items purchased. This typically includes pricing and other validation of the items from the cart (plus newly calculated items like freight and tax). Rather than having the client turn around and request the information that you just generated, I repeat the newly validated (and enhanced) order information. But you are correct, it could be much more efficient if the client side has what it needs.

      Delete