6

REST is Dying. Get Rid of It.

 2 years ago
source link: https://javascript.plainenglish.io/rest-is-dying-get-rid-of-it-d43e6ef80cbe
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

REST is Dying. Get Rid of It.

TIGER: Advanced Easier Webservices You Can Use Today

Image by Art9858 via DepositPhotos

I’ve been programming computers since the 1980s. In that time, I’ve seen and used a lot of languages and technologies that have come and gone. I watched as the web blossomed with new features, like browsers exchanging XML data asynchronously. Today we call this Asynchronous JavaScript and XML data exchange “AJAX”, but ironically, AJAX doesn’t typically even use XML anymore. Most of the time, this data is exchanged as JSON, or YAML, HTML or some other format.

In 1996, Microsoft engineers introduced the iframe tag in IE4. This allowed the browser to asynchronously exchange data with the same or a totally different server without a page refresh, and that data could be passed to the parent object that spawned the iframe object.

At the time, the new feature seemed little more than a wiz-bang “frames” feature to me (I know, you don’t know what HTML frames are; yes I’m that old, thanks for the reminder). However, my brother was using this technology in commercial projects in the mid-1990s to do just that—make “AJAX” data calls with XML even before the term “AJAX” had been invented.

A couple of years later Microsoft would create theXMLHttpRequest object in IE5. Other browser vendors would follow suit, and the era of “AJAX” was born.

REST is dying. Get rid of it.

Sometimes standards and technologies get invented that take root for reasons that are, well: the good, the bad, and the ugly. REST is one of these standards that embodies all three: good, bad, and ugly. But everyone keeps using REST because that’s what modern clients (browsers) implement.

The main problem I have with REST are its verbs: GET, POST, PUT, DELETE, etc., are too limiting and the responses are often inconsistent, or there’s no response at all, like with DELETE. Yes, you can send a success response (meaning a data payload) back with a DELETE call, but that’s not really the standard. Oooh, you got a 200 response, that means it worked. Not. Maybe it did, maybe it didn’t. Sending 202 or 204 responses can be just as cryptic.

To be fair, REST isn’t actually a data exchange protocol per se, like SOAP for instance. It’s actually an architectural style, or some would say “pattern”. As software developers, sometimes we follow the style/pattern explicitly, and sometimes we don’t.

Standards are fine if they work. But as use of the technology advances, often the “standard” starts to hold you back, and that is what REST is doing to the web.

Besides the limits on verbs, another of the many issues I have with REST are its endpoints. Whoever thought that having 37 different endpoints was ever a good idea?

REST also doesn’t natively implement API docs, like SOAP has with WSDL. Yes, the OpenAPI Spec (formerly Swagger) attempts to solve this, but it’s yet another REST bolt-on.

Because of this and other limitations of REST, many a software engineer have developed and evolved our own versions of webservices using small pieces of REST and/or borrowing from other protocols that work better, and I am no different.

TIGER: Easier Web Services That Work Better

TIGER is a name I coined for a loose standard of web services I developed about 12 years ago because I was tired of REST’s limitations and nonsense. TIGER is loosely based on a kind JSON-RPC (JSON remote procedure call) protocol that really just uses REST’s POST and/or GET verbs to send and receive data via the browser client. GET is used for quick grabs of data if you like, but POST is used almost exclusively to exchange data securely.

TIGER utilizes an easy-to-use “message pattern” to send and route data where it needs to go. Routing metadata are contained (co-mingled) within the “message” to the server.

As such, TIGER really needs only ONE endpoint.

Yes, you can have more than one endpoint, but you shouldn’t. Having an API with many endpoints creates huge code bloat, just like we see in typical RESTful services. Zend even created an entire REST framework called “Apigility” to manage and further bloat the API endpoints even more. It’s nonsense. Whatever happened to keeping things simple?

Where TIGER really shines is in the context of a Service-oriented MVC application. Instead of setting multiple endpoints, your AJAX data message simply includes the MVC’s controller /action or in the case of a SOA (Service-oriented Architecture) the service / method you wish to target your data payload for processing. BOOM! Done.

You can also include things like version properties within your message metadata to target specific service versions if you like.

The main goals behind TIGER Webservices were to:

  1. Create a single and secure point of entry for the API so that I wouldn’t have to manage and maintain dozens of versioned endpoints and thus bloat my code.
  2. Automagically validate, route, and authorize requests coming through the API.
  3. Create a flexible but also consistent contract between client and server messages and responses.

TIGER services are typically stateful. But they can be totally stateless if you like. You’re not limited someone’s idea of how an API should behave.

TIGER running within the context of an MVC necessarily authenticates every anonymous request as “guest”, or as some other authenticated role for authorization purposes. If you don’t have access to whatever resources you’re requesting, you don’t get in.

In that regard, TIGER Webservices do have a dependency on the client maintaining some kind of session state, but we already do that with all kinds of RESTful services anyway, so TIGER is no different in that regard.

TIGER Webservices in Action

The concepts in play here are quite simple. And therein lies the beauty of the pattern:

1*kfo__5GqW7SDe9WsJglUuA.jpeg?q=20
rest-is-dying-get-rid-of-it-d43e6ef80cbe

Here is what a typical TIGER AJAX request looks like using a jQuery call:

$.ajax({
type : 'POST',
url : '/api',
dataType : 'json',
data : {
service : 'user',
method : 'save',
firstname : 'Thundarr',
lastname : 'Barbarian'
},
beforeSend : beforeSend,
complete : complete,
success : success,
error : error
});

Note that the beforeSend, complete, success, and error are simply JavaScript vars representing the functions that will handle these AJAX events.

Within this simple example, we see that we’re posting JSON data to the server’s one and only /api endpoint. What the TIGER API service will be expecting to see within the message data are “service” and “method” properties. It will then route the entire message data object to that specific service and method.

You can also pass “controller” and “action” properties as well and TIGER will route the data to the specific action of whatever controller within your MVC.

In this example call, we’re contacting the “user” service’s “save” method to persist the user’s “firstname” and “lastname” fields in the database. It doesn’t get any simpler than this.

TIGER API Routing

Every API call is routed through the API Service. The API Service implements a basic factory pattern to do some sanity checks, validation, authorization, and then instantiates the requested controller or service.

In the case of the TIGER Platform, I use PHP’s __construct() method to pass the entire message into the service on construction and let the service route the message to whatever method from there.

The cool thing about processing the data this way is that when the newly instantiated service is finally returned, all the work has already been done and all I need to do is call the service’s getResponse() method for the response payload and we’re done.

Okay, so it just saved me a step in the factory process, but it’s still a slick extensible way of implementing the SOA in PHP. But I digress …

TIGER Responses

The beauty of TIGER is that I return the exact same response object each and every time. That response object always has properties I’m expecting. It’s like an interface, a contract between the client and the server. Within a response object I know I can always find at minimum the following properties:

{
result : 1, // or 0 on error
data : { ... }, // can also be an array
messages : ['An array of one or more messages, if any.'],
error : [ array of form errors, if any ]
}

But you’re not limited to just one type of response either. For instance, DataTables and Select2 require that I return a different kind of response for them to consume. No problem. I have separate consistent response objects to send back for those types of data requests.

Putting It All Together

I didn’t want to post a boatload of code within this article, so if you want to see TIGER Webservices in action, have a look at the TIGER Platform that uses these services on GitHub. Here are a few links:

Note that the above code is copyrighted because it’s part of a commercial product, but the pattern itself is not copyrighted. Feel free to “borrow” the ideas and write your own version. The TIGER code is specifically made public because I want folks to see how easy TIGER Webservices are to use and how they can make everyone’s life easier when building web services.

[Shameless product plug warning:] If you have an AWS account, you can also launch a TIGER Platform instance for free to see the TIGER Webservices in action. [End commercial.]

TIGER Discovery

While I have not implemented an OpenAPI-style “discovery” pattern or standard for TIGER yet, you can see that using TIGER’s message pattern would make discovery elementary by simply passing in a metadata property that tells TIGER to return whatever API docs and response model types you would like. It’s not a difficult problem to solve if you need to implement a public API.

Conclusion

As the web continues to evolve, REST is, and should be, slowly dying as new and better ideas emerge. JSON has all but totally replaced XML. Microservices are becoming a more popular variant of the more monolithic service-oriented architectures; and so on. It’s time we moved beyond REST and into more flexibility.

I won’t use pure RESTful services if I can avoid it, if for no other reason because of the code bloat; that bloat is just too much nonsense to maintain.

Some might argue that TIGER Webservices are too “loose” and do not adhere to any “recognized” standard. You’re right, they don’t, and for good reason. I don’t like the standards I’ve seen and used. They suck. So I don’t use them. As an application architect, I write my own. And so can you. You don’t have to use some wonky outdated standard just because everyone else does.

Your use case should drive the technology, not the other way around.

The point is, just because something is a so-called “recognized” standard doesn’t mean that it’s perfect or that it will best fit your application’s use case. Experience will teach you what works best and what doesn’t. Something doesn’t have to be a “recognized standard” as long as it’s well documented and streamlines your code for your unique use case.

There are much better patterns and protocols for exchanging data between the client and server today than REST. Check out TIGER Webservices and how they work. They might just give you some ideas of your own, ideas that could make coding for other engineers a year or two from now even easier.

____________________

Beau Beauchamp is a web application architect with over 20 years of experience developing enterprise-class applications in the cloud; he is the founder of WebTigers and lead developer behind the Tiger Platform.

More content at plainenglish.io. Sign up for ourfree weekly newsletter here.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK