HATEOAS client design

I read a lot of discussions here on SO, looked at John Moore's presentation (which explained a lot, by the way) and read the Roy Fielding blog post on HATEOAS, but I still feel a little ignorant when it comes to client design.

API Question

I am currently just returning xhtml with forms / anchors and definition lists for representing resources. The following snippet details how I post forms / anchors / lists.

# anchors <li class='docs_url/#resourcename'> <a rel='self' href='resource location'></a> </li> # forms <form action='action_url' method='whatever_method' class='???'></form> # lists <dl class='docs_url/#resourcename'> <dt>property</dt> <dd>value</dd> </dl> 

My question mainly relates to forms. In a conversation with John, he documents the types of forms, such as (add_location_form), etc., and the data they need. I don’t have many resources, but I was thinking about abstract types of forms (add, delete, update, etc.) And just remember in the documentation which for (add, update) that you have to send a valid representation of the target resource and with deleting, you must send the identifier.

Question 1: With the concept of HATEOAS, we should not just make the client “discover” the form (by classifying, adding, deleting, updating, etc.) and just send all the data we gave them? My real question here (shouldn't be a discussion) is that this follows good practice?

Customer question

Following HATEOAS, our resource actions that you can discover how this affects client code (consumer api) and their ui. It sounds great that after these principles, the user interface should only show the actions available, but how is this implemented?

My current approach parses the answer as xml and usin xpath to find actions known during client development (documented form classes, i.e. add, delete, update) and display ui controls, if available.

Question 2: Am I wrong in my path to discovery? Or is it too much magic, as far as the client is concerned (knowing the classes of forms)? Wouldn’t this suggest that the client knows what actions are available for each resource (which may be good, because this is a kind of reason for creating the client, right?) And the mapping of actions (form classes) to resources should be documented, or simply document form classes and allow the client (and client developer) to examine and discover them?

I know that I am everywhere with this, but any understanding is much appreciated. I will mark the answer that answers either of these two questions. Thanks!

+8
rest hateoas api-design
source share
1 answer

No, you are pretty much calm.

Browsers simply display the HTML payload and rely on Man to actually interpret, make sense, and potentially fill out forms accordingly.

Machine clients, so far, tend to do pretty poorly on the "interpreted" part. Therefore, developers must make decisions in advance and guide the machine client into an excruciating detail.

Ideally, a HATEOS smart client should have certain facts and know the context so that it can better match these facts with the requirements of the service.

Because what we do is not it? We see the form "Oh, they need a name, address, credit card number." We know not only what “name”, “address” and “credit card” mean, we can also understand that they mean the MY name or the name of the person on the credit card or the name of the person sent to.

Machines also work successfully with the "intuit" part. As a developer, you get the code in the logic of what you think is necessary to determine the right facts and how they are posted.

But back to the ideal client, he will see each form, “find out” what the fields need, consult his internal list of “facts”, and then correctly fill in the payload for the request and, finally, make the request.

You can see that a trivial and clearly fragile way to do this is to simply map the parameter names to the internal data. When the parameter name is "name", you can write it like this: firstName + "+ lastName. Or you can think about the actual relation to know what they say about delivery and use: shipTo.firstName +" "+ shipTo.lastName .

For a long time, ideally, you could put together a collection of comparisons so that, if suddenly the payload introduces a new field, and it turns out to be a field that you already know about, you can fill it in the same way as “automatically”, without changing to the customer.

But the truth is simply that, although this can be done, it is largely not done. The semantics are usually fuzzy, you will have to introduce a new “intuition” each time for each new payload, so you can also copy the code into the payload and do with it.

The main thing, however, especially about HATEOS, is that you do not "force" your data on the server. The server tells you what it wants, especially if they provide you with forms.

So, the thought process isn’t "Oh, if I need a delivery invoice, I see that right now they need the name, address and order number, and they want it to be encoded, and they want it to be sent to http : //example.com/shipping_invoice , so I will always send: name + "&" + address + "&" + orderNumber every time until http://example.com/shipping_invoice . Easy! ".

Most likely you want: “I see that they want to have a name, address and order number. So I will do for each request, I will read their form. I will check which fields they want every time. If they need a name, I will give their name. If they want to get the address, I will give them the address. If they want the order number, I will give them the order number. And if they have PRELIMINARY POPULATIONS of fields (or even "hidden"), I will send them back, and I I’ll send them in the encoding they requested, provided that I support it, the URL that I received from the FORM tag action field. "

In the first case, you can see that you want them to receive this payload each time. Just as if you were hard-coded. While with the second, they may have decided that the name and address are redundant, so they no longer ask for it. They may have added some nice default settings for new features that you still cannot support. Maybe they changed the encoding to multi-part? Or the endpoint URL has changed. Who knows.

You can only send what you know when you encode the client, right? If they change things, then you can only do what you can do. If they add fields, we hope they add fields that are not required. But if they break the interface, hey, they break the interface, and you can log the error. Not much you can do there.

But the more you use the HATEOS part, the more it is provided to you, so you can be more flexible: forms to fill out, proper redirects, paying attention to the encoding and media types, the more flexible your client becomes.

After all, most people simply do not do this in their clients. They hardcode the trait of them because it is simple, and they assume that the back does not change fast enough to make a difference, or that any downtime, if such a change occurs, is acceptable until they fix the client. More typically, especially with internal systems, you simply receive an email from the developers: “They changed the XYZ API, and it will live on March 1. Update your customers and coordinate them with the development team during integration testing. Thank you.”

It is just a reality. This does not mean that you should not do this, or that you should not make your servers more friendly to smarter clients. Remember a bad client that assumes that everything does not invalidate a good REST-based system. These systems work great with terrible clients. wget ftw, eh?

+6
source share

All Articles