In our extensive Retrofit series we show developers how to implement all kinds of API interactions from the client side on Android. In our hapi.js series developers can learn how to provide API endpoints from the server side to clients.
Most of the technical tutorials assume some basic knowledge on HTTP, its methods and status codes. While there is a lot more to networking on an HTTP level, these are the important bits for developers.
In this tutorial you'll learn the basics of HTTP.
When you're developing a server or a client app, you'll most likely execute API requests via HTTP. HTTP (Hypertext Transfer Protocol) is a standardized protocol for communication on an application level for the World Wide Web (WWW).
HTTP is based on requests and responses. For this tutorial, the Android app will be the client and sends a request to the hapi server, which will send a response back. The identifier for the resource you want to request on the server is always with a URL (Uniform Resource Locator). The scheme of the URL indicates whether you're encrypting (e.g., https) the communication or not (e.g., http).
The Android app, which asks for a resource, is sending a request to the server. The request message contains four major parts:
- Request line
- Request headers (optional)
- Empty line to separate headers and body
- Request body (optional)
Next, we'll look at those parts in more detail.
The first part of a request is the request line. It contains two pieces of information: the request method and the request URL. We'll look at request methods in depth in the next section. For now we just use
GET as an example, which means the client doesn't send data and just asks the server for some information. The server knows which resource the client is asking for based on the passed request URL.
Let's look at an example:
The line above would be a valid request line asking the server to send back our university logo.
Sometimes the server needs more information than just the request method and resource location. For example, a lot of server implementations support a variety of clients. In the past we worked on a project, where the server sent different responses back depending if the client was an Android or an iOS app. But how does the server know what kind of app requests a resource? Request headers!
Request headers are a way of supplementing a request with additional data, which are structured as an array of simple text-based key-values. In the example above, the Android apps would add a
User-Agent: Android header and thus identify themselves to the server. There are many more standard headers, and even more custom headers, which you can develop tailored to your application. It's important to know that headers can be extremely useful in creating a clean application and reducing the amount of data you've to send in the request URL or the request body.
Unlike the headers, the request body supports complex data structures with a wide variety of formats. Common data formats are JSON, XML or binary. The request body usually contains the important part of the message. For example, if the client would open a request to the server to create a new user, the request body would contain the user's information (name, email, …).
You already learned that the very first part of a request is the request method, like
GET. This is not by accident. The nature of the request can be completely different depending on the request method.
GET https://futurestud.io/api/user/42 DELETE https://futurestud.io/api/user/42
For example, the lines above look almost identical. However, the first would request the data of user
42, while the second one would delete it! Thus, don't treat the request method lightly and be careful.
As we've mentioned multiple times, the
GET request method indicates to the server that the client would like to access some data. It's a simple read, it won't add, change or delete it.
POST & PUT
PUT are both ways of sending data to the server. However, the implications are different.
POST requests expect the server to add it to existing ones. For example, a
POST request with a user object would mean that the server creates a new account.
On the other hand, a
PUT request expects the server to update or replace the existing data item. Consequently, a
PUT request with a user object would be fitting if someone updates their own user profile.
Lastly, and probably the easiest one is
DELETE is used if you want to delete the data item you specified in your request URL.
Overall, you might recognize that the
DELETE is quite similar to the CRUD model from a lot of databases. The
GET equals a read, the
POST is creating a new data item,
PUT is editing one and
DELETE is —surprise, surprise— deleting one.
HEAD, PATCH, TRACE, OPTIONS, CONNECT
In the vast majority of the APIs you'll either write or interact with, those four request methods will be sufficient. However, in some rare cases another request method might be a better fit. Since they're beyond the introductory nature of this tutorial, we recommend to read up on special request methods later.
Lastly, we would like to encourage everyone to follow the request method standards. We've worked more than once in projects, which deviated from the standards and later on regretted that decision. In most cases it's much easier for the client, server and developer to follow the common approach to request methods.
In the previous section we only viewed the first half of the client-server interaction. Of course, the server's answer, the response, matters. The structure of a response also differs slightly from a request. It usually contains four parts:
- Status line
- Response headers (optional)
- Empty line to separate headers and body
- Response body (optional)
While the structure of the response headers and the response body is the same as their counterparts from a request, the first line is fulfilling a completely different function. The status line informs the client on the result of the request. In other words, it tells you if your request was successful.
Of course, there are a million different results depending on the content. Thus, the status line is split into two parts: the status code and a textual description. The text doesn't follow any standardization and can be any string describing the success or error. However, the status code are expected to behave a certain way. You'll learn more about them in the next section.
As you've learned in the previous section, the status code and the textual description are set by the server and send as the first line of the server response. The client will use this line to quickly comprehend what kind of response the server sent. Let's look at some status code examples:
200 OK 204 No Content 401 Unauthorized 503 Service Unavailable
The first part, the numerical status code, contains of three numbers. The numbers are grouped into hundreds, which we'll look at next.
While a few of these
1xx status codes exist, they're usually for more low-level stuff and you most likely won't ever have to deal with them in reality.
Hopefully, you'll use these status codes the most. All status codes leading with a
2 indicate that the request was successful.
A selection of important
2xx status codes:
200 OK- The standard response for indicating a successful request. Sadly, many APIs use this one exclusively and don't split success responses into other
201 Created- The request successfully lead to a creation of something new.
204 No Content- The request was successful, but the server doesn't respond with any data. This is often used to acknowledge a successful deletion of a resource.
The status codes in the
3xx group are all indicating that the specified URL isn't working, currently or permanently, for the server and you should direct your request somewhere else. This is mainly used for web servers, which delivery webpages and less for APIs.
4xx Client Error
Hopefully, you won't have to deal with the status codes in the
4xx group too often. They indicate that the request was in some form incorrect and could not be processed by the server. There are a few technical reasons, why this can happen, e.g., the request is too large for the server. However, usually the semantic of the request is the problem.
A few common
4xx status codes:
400 Bad Request- Similarly to the
2xxstatus codes this is a catch-all for all kinds of errors. Some APIs use this exclusively, which makes it more difficult for the client to understand the error. Ideally, the server only responds with the
400status codes if his request was in some form incorrect (missing data, data violates input constraints, …) and specifies the error in more detail in the response body.
401 Unauthorized- This status codes doesn't say anything about the content of the request, it tells you that the request couldn't be processed because the server could not authenticate the request (it doesn't know who the user behind the request is). Usually, this means the authentication token was missing or incorrect.
403 Forbidden- Often confused with
401, but here the server knows who the request sender, but doesn't allow the action. For example, a user could send a request to delete another user, but an admin access right is necessary for it.
404 Not Found- You have seen this one when browsing the Internet. It can be used for APIs as well. If the client is trying to access content, which doesn't exist (anymore), it should receive a
5xx Server Error
5xx group of status codes is particularly tricky. These indicate that the server has an issue and can't process your request. If you’re the server developer, these errors are something you should look out for. If you're the client developer, you should also look out for them and report them to the API guys right away.
Most commonly used
5xx status codes are:
500 Internal Server Error- Catch-all for various reasons why a request cannot be processed on the server side. Often hints toward a bug or incorrect configuration.
503 Service Unavailable- This simply means that (a part of) the server is down :(
Unfortunately, we feel the need to also remind all developers that the standard of sending [reasoned status codes](
https://en.wikipedia.org/wiki/ListofHTTPstatuscodes) is helpful for everyone. Don't mislead clients by trying to hide errors. Please make sure to understand which status codes are disposable to you and choose the correct one. If necessary, further specify errors in the response body. The client developers will thank you.
HTTP has survived for a surprisingly long time considering the fast development cycles in modern tech. There barely has been any movement in two decades. Recently, a lot of tech giants picked up the pace and pushed towards a modernization of HTTP. The newer model
HTTP/2 improves several weaknesses, but overall leaves the idea of HTTP the same. Consequently, this won't concern you until you're doing improvements on the micro level.
In this admittedly long tutorial you've seen an overview of HTTP and its element. When starting out as an Android app (client) or hapi.js (server) developer, you need to carry some basic knowledge on HTTP with you. Hopefully, this tutorial gave you a head start and some resources to further read up on more details, if necessary.
If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.
Make it rock & enjoy coding!