1

When using routing in a SPA web app (angular, react, etc), the user doesn't have to start at the entry point of the application. They can use a URL in the browser to drill down into any part of the application.

When implementing HATEOAS in a RESTful backend API, we assume that the front-end only knows the URL to the entry point of the API, and then the API provides links to other parts of the application from there.

So this begs the question, if a user enters a URL in the browser that loads a specific part of the SPA (not the entry point), how does the SPA get the appropriate API link needed for just that part of the SPA?

Does the SPA just make a bunch of API calls all at once, starting at the entry point of the API and following links until it gets the link it needs for the state it needs to load? And what happens when the API does not include the link needed because it's not a valid link based on the current state of the application?

HATEOAS doesn't seem to be very compatible with a modern SPA where you can load the application at very specific sections/states.

wired_in
  • 322
  • 1
  • 2
  • 8
  • `how does the SPA get the appropriate API link needed for just that part of the SPA?` -- What? The SPA already has it; the user just typed it into the browser. – Robert Harvey May 08 '20 at 17:02
  • 1
    @RobertHarvey I think OP means the api(ajax) uri for a given page in a SPA – Esben Skov Pedersen May 08 '20 at 18:44
  • It obtains that URI the same way it always does. Typing a SPA URL into the browser by hand doesn't change that. – Robert Harvey May 08 '20 at 19:22
  • @RobertHarvey Yes it does... The point of HATEOAS is for the client to not have to know all of the API's URIs. The client app knows the URI to the entry point of the API, and then "discovers" and follows links from the entry point. If the web app doesn't start off at the entry point of the application, then they somehow have to get the API URI for any given part of the application, without the previous knowledge of all URIs in the API. If the client already knows every API URI up front, then it's defeating one of the main reasons to use HATEOAS in the first place. – wired_in May 08 '20 at 22:25
  • OK. So what do you suggest? Your assertion is that it can't be done. – Robert Harvey May 08 '20 at 22:26
  • @RobertHarvey If I had a suggestion I wouldn't have come here to ask for suggestions... – wired_in May 08 '20 at 22:27
  • Presumably, there is *some* correspondence between the URL that the SPA sees, and the URI that's required to obtain the data to display the SPA page. Otherwise, there wouldn't be any coherence between the SPA pages and the API. For example, if the user types in a SPA URL such as `https://yourapp/customers/displaycustomer/123`, the SPA should be smart enough to know that it needs to go to `https://someAPI/customers/123` to get the required data. – Robert Harvey May 08 '20 at 22:29
  • @RobertHarvey, I'm not sure if you are familiar with HATEOAS or not. If you aren't, I'm not sure why you are chiming in here. But the "rel" part of links returns from the API describes what the link is. The client needs to be coupled to the name of the resource, and needs knowledge of the structure returned from the resource, BUT the client doesn't need to know anything about the URI. The URI is provided dynamically by the API. – wired_in May 08 '20 at 22:33
  • @RobertHarvey This allows both the client and server to evolve independently. The API is free to change its URIs, remove resources, add resources, all without breaking the client. So no, there does not have to be any coupling in the URIs between client and server – wired_in May 08 '20 at 22:33
  • 1
    Might I suggest that you don't actually need HATEOAS? HATEOAS is a discovery mechanism, intended to facilitate machine-to-machine document discovery and navigation. It probably doesn't apply to your application; you're only using it because it's the latest flavor of the week. – Robert Harvey May 08 '20 at 22:34
  • 1
    And it's not me that's saying this. *You're saying it,* in your own question: *"HATEOAS doesn't seem to be very compatible with a modern SPA where you can load the application at very specific sections/states."* – Robert Harvey May 08 '20 at 22:36
  • You may be right that I don't need HATEOAS. This would be the reason I came here to ask the question.... So I could ascertain if that is indeed the case. – wired_in May 08 '20 at 22:39
  • The vast majority of SPA applications would fare just fine with some sort of ordinary JSON service. It doesn't even have to be REST compliant. The only reason you would do REST things like HATEOAS is if the API was being offered by a different company that provided HATEOAS with their API. If it's your own internal API, you already know its architectural structure, and you can already evolve it concurrently with your SPA application. – Robert Harvey May 08 '20 at 22:42
  • Even then, there's a cost to that discovery. There might be some allure to writing a SPA application that self-heals if the underlying API changes, but all that indirection is costly, and for performance reasons you're more likely to simply adapt your SPA to the changes yourself, rather than relying on the HATEOAS links to do that for you. – Robert Harvey May 08 '20 at 22:44
  • But that's just my own personal opinion. It might turn out that you only need one HATEOAS hop for each endpoint to get all your work done. – Robert Harvey May 08 '20 at 22:45
  • "Need" is a strong word, but there is definitely value in using "HATEOAS" in any SPA where you want state to be primarily driven by the server side. The client doesn't have to worry about business logic and authorization checks to determine what operations are possible at any given point in the application. They simply use the operations the server gives them. It's also a huge benefit that the client doesn't have to hardcode API URIs on their side, which is not only a pain, but it increases coupling between client and server and makes the application more brittle. – wired_in May 08 '20 at 23:02
  • How would your client know what those links actually do? Is your SPA application smart enough to know when the API has changed an "employee" to an "associate," and what to do if that occurs? (See [here](https://restfulapi.net/hateoas/) for an actual example). The only operations that HATEOAS can encode are the same operations that a REST interface can provide, namely GET, PATCH, PUT and the like. Seems to me like you still need a human being to interpret those operations and give them some actual business-related meaning. – Robert Harvey May 08 '20 at 23:24
  • @RobertHarvey The only thing that has to remain constant (the interface) is the name of the "rel" attribute for links and the structure that the link returns. Everything else can evolve independently. The URI's, when and where operations are available, etc. You can even change "rel" attribute names in a lot of situations without breaking the client, because the client would only see it as that operation is no longer available, so it won't include it. Without HATEOAS you essentially have to code the entirety of the API's interface on the client, and any changes in the server's interface breaks – wired_in May 09 '20 at 00:35
  • What is it about a SPA specifically that makes all that problematic? Why do the benefits of such an interface not extend to a SPA? – Robert Harvey May 09 '20 at 01:34
  • https://academy.realm.io/posts/kyle-fuller-resilient-api-clients/ -- Which seems to suggest that a lot of the logic driving a HATEOAS application takes place on the *server,* not the client. This is probably why SPA seems incompatible... in a SPA, most of the application logic resides in the *client,* not the server. – Robert Harvey May 09 '20 at 01:41
  • And [this](https://datatracker.ietf.org/meeting/interim-2016-t2trg-01/materials/slides-interim-2016-t2trg-1-1). Overall, HATEOAS seems like the old Hypermedia idea in a new suit. No doubt it's useful, but if an API decides to pull the plug on a resource, your application still has to be smart enough to adapt to that change, however automatic that adaptation is. – Robert Harvey May 09 '20 at 01:50
  • Finally, my impression is that it takes more than just the textbook definition of HATEOAS to make this work. You need an *implementation,* a rather robust one involving multiple techniques and technologies. See also [here](https://softwareengineering.stackexchange.com/questions/388325/advantages-of-hateoas-based-restful-service). – Robert Harvey May 09 '20 at 02:06
  • `Does the SPA just make a bunch of API calls all at once, starting at the entry point of the API and following links until it gets the link it needs for the state it needs to load? ` Of course, the API is stateless! All the way back to the resource behind the APP state should be re-discovered. If the resource is no longer available the APP will just say so. – Laiv Jun 08 '20 at 14:28
  • Thought work. Change the SPA with an iOS or Android app. How would you implement the "share" link? How it would work if the link is shared with someone who doesn't have the app? Or it has it, but it never asked for such a resource? The link must provide all the info required for the target to reproduce the whole dance of requests. Or at least the required ones. Usually, it takes sharing IDS which are the URIs of the resources. – Laiv Jun 08 '20 at 14:41

1 Answers1

2

When implementing HATEOAS in a RESTful backend API, we assume that the front-end only knows the URL to the entry point of the API, and then the API provides links to other parts of the application from there.

There might be some confusion here. The front-end (the client) may know only the entry point initially. As the user follows links and submits forms, i.e. navigates through state-changes, the user/client is completely free to "bookmark" (remember) any states in goes through, and can return to those states any time.

The concept of bookmarks, and returning to bookmarked states is completely compatible with REST and HATEOAS.

So obviously as the SPA changes state, it should always change the url to the appropriate state on the backend to reflect the state the frontend is in. This should always be possible, the SPA shouldn't have meaningful states that is not reflected on the backend! This also means if the user returns to this url, it will automatically return to the appropriate state on the backend too.

Robert Bräutigam
  • 11,473
  • 1
  • 17
  • 36
  • If I'm understanding correctly, you are suggesting that the SPA caches (bookmarks) the API URI for each state transition the first time the application is accessed from the entry point? What happens when the REST API changes a URI? After all, a key reason to use HATEOAS is because the URI is abstracted away. The client only needs to follow links given by the server, not know or understand the URI. The server should be free to change its URI if clients are simply requesting and following links based on the "rel" attribute. – wired_in May 08 '20 at 22:42
  • The SPA *could* cache all the state transitions, but that is a bit overkill. You are at some state, you only have to know the URL (or handful of URLs at most) of that state on the backend. If the URI changes, the server should provide redirects to the new URLs, and the client should update its state to the new URL on permanent redirect. – Robert Bräutigam May 09 '20 at 10:18
  • That doesn't make sense... In order for a user to be able to bookmark any client URL, all backend URLs that correspond to the state at any given client URL need to be "cached". An SPA allows navigating to anywhere within the app via a URL. Thus the SPA would need knowledge of every backend URL needed to load state at any given client URL. However, the REST API is not under any obligation to adhere to any interface based on URL, since HATEAOS abstracts away the URL. So none of this is really compatible. Sounds like you are just trying to make it fit when it really doesn't. – wired_in Apr 06 '21 at 18:00