4 ms·
This is a wrong understanding of that point. The HATEOAS model is designed for one thing: clients and servers that are developed independently of each other. T
by simiones 4y ago
This is a wrong understanding of that point.
The HATEOAS model is designed for one thing: clients and servers that are developed independently of each other. This matches how the Web is designed (browsers and servers are not developed together), but does not match how most Web Apps are developed (there is almost universally a single entity controlling both the server and the client(s) for that app).
The point of HATEOAS-style REST APIs is that the client should decide what it can do based entirely on the responses it receives from the server and its understanding of the data model - not in any way on its own knowledge of what the server may be doing. This allows both to evolve separately, while still being able to communicate.
To contrast the two approaches, let's say we are building a clone of HN. In the more common web app approach, our client may work like this:
1. Send a POST to https://auth.hnclone.com/login with {"username": "user", "password": "pass"}; wait for a 200 OK and a cookie
2. Send a GET request to https://hnclone.com/threads?id=user (including the cookie) and display the results to the user
In the REST approach, our client and server could work like this:
1. Send a GET to https://hnclone.com; expect a body that contains {"links": [{"rel": "threads", "href": "https://hnclone.com/threads", "query_params": [{"name":"id", "role": "username"}]}]}
2. Send a GET request to the URL for rel="threads", populating the query param with role="username" with the stored username -> get a 401 NOT AUTHORIZED response with a body like {"links": [{"rel": "auth_page", "href": "https://auth.hnclone.com"}]}
3. Send a GET request to the URL for auth_page and expect a response that contains {"links": [{"rel": "login", "href": "https://auth.hnclone.com/login"}]}
4. Send a POST request to the link with rel == "login" with a body of {"username": "user", "password": "pass"}, expecting a 200 OK response and a cookie
5. Re-send the request to the URL for rel="threads" with the extra cookies, and now get the threads you want to show
More complicated, but the client and server can now evolve more independently - they only have to agree on the meanings of the documents they exchange. The server could move its authentication to https://hnclone.com/api/auth https://hnclone.com/api/auth and the client from 2 years ago would still work. The server could add (optional) support for OAUTH without breaking old clients.
You could even go further and define custom media formats and implement media format negotiation between client and server - the JSON format I described could be an explicit media format, and your API could evolve by adding new versions, relying on client Accept headers to decide which version to send.
Now, is this extra complexity (and slowness!) worthwhile to your use case? This depends greatly. For a great many apps, it's probably not. For some, it probably is. It has definitely proven to be extremely useful for building web browsers that can automatically talk to any HTTP server out there without custom Google/Facebook/Reddit/etc. plugins to work properly.
- Jasper_ 4y agoHow do you know that the specific login page is where you send the username/password? What if the sevrer changes the login flow to be a 2-part process? What if the clone wants to add an extra challenge like TOTP? The kinds of changes people are interested in are usually related to changing URLs, and those don't seem very valuable to me for the amount of complexity this flow adds. And ironically enough, the "URL changing" part we already have covered in the old system fine, with HTTP Redirect messages.