You have a project and need help?

Let's talk

Please enter a valid email address.
Please enter a valid phone number
hire-us

HOME / BLOG / REST in peace (R.I.P.)

REST in peace (R.I.P.)

REST in peace (R.I.P.)

Using HTTP transport layer for API service is like using sewage system, network of pipes for mail package delivery. It will work but things will get messy

It is time to rethink REST

Background

Since the beginning of computer networks there existed a need for orchestrated and regulated communication between servers and clients. Most significant example of this is Hyper Text Transfer Protocol (HTTP) that was designed for delivery of documents using Hyper Text Markup Language  (HTML)  And that is it, designed for web.

Somehow, somewhere, someone (Bad Boy Roy) came up with “amazing” idea to use HTTP for something it was not designed for. That idea is Representational state transfer (REST).

General purpose of RESTful services is the communication between the application server and clients, and it is amazing. It is widely and relatively simple to use. I respect that, I use it almost always as a client and as API service developer. It is quite OK, but!

Why is it not good?

Well… first of all it works, and it works quite fine, but fundamentally it is wrong. It is like using sewage system, network of pipes for mail package delivery. It will work but things will get messy*

Let’s start with methods, there are 9 of them:

  • GET
  • HEAD
  • POST
  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH

Most of them are used to manipulate some resources (like a web page, HTML document). But, what if your API makes an action? For example LaunchSpaceRocket there is no such method and you should make a compromise and choose for example PUT or POST, that makes sense? Right…

Even if you can get over that limitation and if you make things right your client gets HTTP status 200, which brings us to the next “interesting” feature:

Status codes

While designing your API you can safely rely on around 63 ready made, out of the box and amazing HTTP status codes. Codes that are designed to give an internet browser a clue what went wrong with request or if it is OK(200).

What REST developers do is squeezing their API specific errors into existing HTTP status codes. That is why your clients should always have a map of response codes that needs to always have by their side to decipher what you had in mind when you threw 425 (Too early). And what about 410 what does it tell your clients? That server is gone? Programmer gone? Resource gone? Reason gone?

Utter nonsense.

Because REST relies on HTTP, that is why your clients are probably using HTTP clients (as a library). And here comes an interesting issue, if your API throws 501, some HTTP client libraries throw that error, thus crashing client app.

As being a good developers, your clients should probably handle that error (try/catch). However, if you decide to send some explanatory error data in the HTTP body, and at the same time throw 501, some libraries do not populate body at all. And there is no way your client could retrieve body data in case of an HTTP error. Interestingly, maybe your intention is not to cause the error, maybe your intention is just to use different status code for normal operation, nevertheless you can’t be sure how client implementation works.

This is a problem because there is no strict standard on using the errors, and developers do that on their own, and clients are at their mercy.

Different transport technology.

Imagine you are working on API service. Suddenly, your superior demanded to provide the same service using Bluetooth. What will you do? Rewrite the whole service logic?

FYI, Bluetooth doesn’t have HTTP error codes, it has its own set of codes What now? Should you use Bluetooth protocol error codes? If yes, can you be sure that Bluetooth client or even drivers will respond properly on your choice of errors and payload sizes? Will you make your own error-proof Bluetooth client just to stubbornly push through your idea of using transport protocol for more than just transporting data?

A proper way of thinking about API service

Of course not! you will make a service that is transport technology agnostic (TTA), independent, free,... It is worth mentioning that maintainability of such omnichannel API service is waaay better than handling each transport technology API individually. Communication channels and technologies emerge quite frequently and you need to be aware of that if you want your service to be available everywhere and for everyone (especially early adopters).

You are probably wondering how TTA API service it should look like?

This is an easy one, just follow the rules:

  1. Just keep focus on service and logic, do not interweave your logic into transport layer.
  2. Adapters for transport technology should be lightweight and exist as one of the layers of your software architecture. With careful design this layer can be easily replaced or coexist with others.
  3. Define request structure, for example:
{
    "action": "LaunchSpaceRocket",
	"version": "1",
    "requestID": "some request ID",
    "payload":
    {
        "date": "1.1.2022",
        "destination": "Mars"
    }
}
  1. Define response structure, for example:
{
    "status": "OK",
    "version": "1",
    "responseID": "some response ID",
    "requestID": "responding request ID",
    "payload":
    {
        "dateOfArrival": "1.8.2022",
        "selfie": [ImageByteArray],
        "weather": "Freezing"
    }
}
  1. Use minimum transport protocol technology features.
    For HTTP example use POST on a single endpoint. Request body contains JSON request object. This endpoint should always return 200 (OK) with appropriate body: JSON response.
    Let’s just for example imagine email case: email address may be equivalent of endpoint URL, and email body is JSON request object. Result (response) is a reply to that email (or new email with matching ID)
  2. If there is an error, the response might be like this:
{
    "status": "ERROR",
    "version": "1",
    "responseID": "some response ID",
    "requestID": "responding request ID",
    "payload":
    {
        "errorCode": "1337",
        "message": "Fuel ran out"
    }
}

And in the case of HTTP transport technology this is response on POST request. Although it is an error, HTTP status code should be 200, because rule number 3.

This is it, simple, easy, and can be used on anything. All of the data and instructions are contained in a single place, unlike RESTful services where data can be transported using: query string, HTTP headers or body. And what is even worse, data can be transported at the same time at various locations! It’s like playing hide and seek with the data.

Conclusion

There is much more to this story, for example API security, but that’s a topic for another time.

Remember, technology is changing rapidly, faster than you can say word SOAP. Be smart and avoid painful refactoring of code and architecture when suddenly something new comes in place. One day that may be Silverlight or REST and next day it will be gRPC, you'll never know until it hits you.
When architecting, always ask yourself, if it works on HTTP will it work on yogurth** as well?

And yes, don't use drugs kids!


Extra

While talking about abominations, have you heard of REST streaming?

Side story: HTTP was designed to have a beginning (request) and the end (response). If request takes too long you it will end with an error:

408 Request Timeout
The server timed out waiting for the request. According to HTTP specifications: "The client did not produce a request within the time that the server was prepared to wait.”

That makes sense, especially for web resources.

But wait! Imagine you can have HTTP call that doesn’t have an end, no timeouts? Just endless stream of body. That is REST streaming***; that is the beast.

There is no need to reinvent the wheel, use websockets instead, or TCP socket if you’re feeling HC.

REST in peace (R.I.P.)

* Shitty
** Replace with anything, zigbee, bluetooth, or, 433 MHz Dash7
*** For example check Twitter streaming API

YOU MIGHT ALSO LIKE

You have a project and need help?

Let's talk

Please enter a valid email address.
Please enter a valid phone number
hire-us