Sunday 3 May 2015

Learn REST: A Tutorial

Credit! Following Materials from: http://rest.elkstein.org/

1. What is REST?

REST stands for Representational State Transfer. (It is sometimes spelled "ReST".) It relies on a stateless, client-server, cacheable communications protocol -- and in virtually all cases, the HTTP protocol is used.
REST is an architecture style for designing networked applications. The idea is that, rather than using complex mechanisms such as CORBA, RPC or SOAP to connect between machines, simple HTTP is used to make calls between machines.
  • In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-based architecture.
RESTful applications use HTTP requests to post data (create and/or update), read data (e.g., make queries), and delete data. Thus, REST uses HTTP for all four CRUD (Create/Read/Update/Delete) operations.
REST is a lightweight alternative to mechanisms like RPC (Remote Procedure Calls) and Web Services (SOAP, WSDL, et al.). Later, we will see how much more simple REST is.
  • Despite being simple, REST is fully-featured; there's basically nothing you can do in Web Services that can't be done with a RESTful architecture.
REST is not a "standard". There will never be a W3C recommendataion for REST, for example. And while there are REST programming frameworks, working with REST is so simple that you can often "roll your own" with standard library features in languages like Perl, Java, or C#.

2. REST as Lightweight Web Services

As a programming approach, REST is a lightweight alternative to Web Services and RPC.
Much like Web Services, a REST service is:
  • Platform-independent (you don't care if the server is Unix, the client is a Mac, or anything else),
  • Language-independent (C# can talk to Java, etc.),
  • Standards-based (runs on top of HTTP), and
  • Can easily be used in the presence of firewalls.
Like Web Services, REST offers no built-in security features, encryption, session management, QoS guarantees, etc. But also as with Web Services, these can be added by building on top of HTTP:
  • For security, username/password tokens are often used.
  • For encryption, REST can be used on top of HTTPS (secure sockets).
  • ... etc.
One thing that is not part of a good REST design is cookies: The "ST" in "REST" stands for "State Transfer", and indeed, in a good REST design operations are self-contained, and each request carries with it (transfers) all the information (state) that the server needs in order to complete it.

3. How Simple is REST?

Let's take a simple web service as an example: querying a phonebook application for the details of a given user. All we have is the user's ID.
Using Web Services and SOAP, the request would look something like this:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:body pb="http://www.acme.com/phonebook">
  <pb:GetUserDetails>
   <pb:UserID>12345</pb:UserID>
  </pb:GetUserDetails>
 </soap:Body>
</soap:Envelope>
(The details are not important; this is just an example.) The entire shebang now has to be sent (using an HTTP POST request) to the server. The result is probably an XML file, but it will be embedded, as the "payload", inside a SOAP response envelope.
And with REST? The query will probably look like this:
http://www.acme.com/phonebook/UserDetails/12345
Note that this isn't the request body -- it's just a URL. This URL is sent to the server using a simpler GET request, and the HTTP reply is the raw result data -- not embedded inside anything, just the data you need in a way you can directly use.
  • It's easy to see why Web Services are often used with libraries that create the SOAP/HTTP request and send it over, and then parse the SOAP response.
  • With REST, a simple network connection is all you need. You can even test the API directly, using your browser.
  • Still, REST libraries (for simplifying things) do exist, and we will discuss some of these later.
Note how the URL's "method" part is not called "GetUserDetails", but simply "UserDetails". It is a common convention in REST design to use nouns rather than verbsto denote simple resources.
The letter analogy
A nice analogy for REST vs. SOAP is mailing a letter: with SOAP, you're using an envelope; with REST, it's a postcard. Postcards are easier to handle (by the receiver), waste less paper (i.e., consume less bandwidth), and have a short content. (Of course, REST requests aren't really limited in length, esp. if they use POST rather than GET.)
But don't carry the analogy too far: unlike letters-vs.-postcards, REST is every bit as secure as SOAP. In particular, REST can be carried over secure sockets (using the HTTPS protocol), and content can be encrypted using any mechanism you see fit. Without encryption, REST and SOAP are both insecure; with proper encryption in place, both are equally secure.

4. More Complex REST Requests

The previous section included a simple example for a REST request -- with a single parameter.
REST can easily handle more complex requests, including multiple parameters. In most cases, you'll just use HTTP GET parameters in the URL.
For example:
http://www.acme.com/phonebook/UserDetails?firstName=John&lastName=Doe
If you need to pass long parameters, or binary ones, you'd normally use HTTP POST requests, and include the parameters in the POST body.
As a rule, GET requests should be for read-only queries; they should not change the state of the server and its data. For creation, updating, and deleting data, use POST requests. (POST can also be used for read-only queries, as noted above, when complex parameters are required.)
  • In a way, this web page (like most others) can be viewed as offering services via a REST API; you use a GET request to read data, and a POST request to post a comment -- where more and longer parameters are required.
While REST services might use XML in their responses (as one way of organizing structured data), REST requests rarely use XML. As shown above, in most cases, request parameters are simple, and there is no need for the overhead of XML.
  • One advantage of using XML is type safety. However, in a stateless system like REST, you should always verify the validity of your input, XML or otherwise!

12.2. Using REST in Java

Issuing HTTP GET Requests
The key class here is HttpURLConnection, obtained by invoking openConnection on a URLobject. Sadly, openConnection method's signature specifies that it returns the superclass type, URLConnection, and we have to downcast the result.
The following method issues a request and returns the entire response as one long string:
public static String httpGet(String urlStr) throws IOException {
  URL url = new URL(urlStr);
  HttpURLConnection conn =
      (HttpURLConnection) url.openConnection();

  if (conn.getResponseCode() != 200) {
    throw new IOException(conn.getResponseMessage());
  }

  // Buffer the result into a string
  BufferedReader rd = new BufferedReader(
      new InputStreamReader(conn.getInputStream()));
  StringBuilder sb = new StringBuilder();
  String line;
  while ((line = rd.readLine()) != null) {
    sb.append(line);
  }
  rd.close();

  conn.disconnect();
  return sb.toString();
}
(This code is very raw; it should be properly padded with try/catch/finally blocks to ensure the reader is closed, etc.)
Remember that if the request URL includes parameters, they must be properly encoded (e.g., a space is %20, etc.). The class URLEncoder can be used to perform this encoding.
Issuing HTTP POST Requests
URL encoding is also required for POST requests, as shown in the following method:
public static String httpPost(String urlStr, String[] paramName,
String[] paramVal) throws Exception {
  URL url = new URL(urlStr);
  HttpURLConnection conn =
      (HttpURLConnection) url.openConnection();
  conn.setRequestMethod("POST");
  conn.setDoOutput(true);
  conn.setDoInput(true);
  conn.setUseCaches(false);
  conn.setAllowUserInteraction(false);
  conn.setRequestProperty("Content-Type",
      "application/x-www-form-urlencoded");

  // Create the form content
  OutputStream out = conn.getOutputStream();
  Writer writer = new OutputStreamWriter(out, "UTF-8");
  for (int i = 0; i < paramName.length; i++) {
    writer.write(paramName[i]);
    writer.write("=");
    writer.write(URLEncoder.encode(paramVal[i], "UTF-8"));
    writer.write("&");
  }
  writer.close();
  out.close();

  if (conn.getResponseCode() != 200) {
    throw new IOException(conn.getResponseMessage());
  }

  // Buffer the result into a string
  BufferedReader rd = new BufferedReader(
      new InputStreamReader(conn.getInputStream()));
  StringBuilder sb = new StringBuilder();
  String line;
  while ((line = rd.readLine()) != null) {
    sb.append(line);
  }
  rd.close();

  conn.disconnect();
  return sb.toString();
}
As you can see, it's not a pretty sight (and that's before adding proper try/catch/finallystructures). The problem is that, out of the box, Java's support for handling web connections is pretty low-level.
A good solution can be found in the popular Apache Commons library, and in particular the httpclient set of packages. See Yahoo! guide to REST with Java for details and examples. The documentation covers several interesting extras, such as caching.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.