Earlier quoted context omitted.
It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…
To me the best advantage is that by following links, the client doesn't have to builds those links in the first place. So the client will keep working even if a few months from now you want to change the link to something else. A simple example: if retrieving articles can be done by requesting this link "/articles", I can potentially change it in the future to "/v2/articles" and the client would still work.
API Design Guide
181–190 of 192 posts
Re: API Design Guide
#182Do any of these API guides have good guidance around batch endpoints like handling a PATCH on multiple resources as a single request?
1. If it's a transaction (all-or-nothing) I POST a new transaction resource which references all the target resources. Remember that you can create as many resources as you want. There is no need to have a 1:1 mapping between your resources and the database.
2. If it's a batch statement (some-can-fail-some-can-lose) I simply stick to issuing multiple requests. This frees me and my clients from having to write complicated code that deal with partial success - and it can still be very fast especially with request pipelining.
If issuing multiple statements is too slow then I would attempt to increase the speed of the stack before adding the complexity of having to deal with partial success.
So in conclusion... No really good ideas on how to write batch statements. I don't really think REST APIs with their one HTTP response code maps very well for that use case. But I hope one of the two strategies above will be useful to you.
Re: API Design Guide
#183Earlier quoted context omitted.
How is: { "@context": "http://json-ld.org/contexts/person.jsonld", "@id": "http://dbpedia.org/resource/John_Lennon", "name": "John Lennon", "born": "1940-10-09", "spouse": "http://dbpedia.org/resource/Cynthia_Lennon" } Better than: (http://json-ld.org/contexts/person (id http://dbpedia.org/resource/John_Lennon) (name "John Lennon") (born 1940-10-09) (spouse http://dbpedia.org/resource/Cynthia_Lennon)) Note that the l…
The answer to that is really simple: JSON is a widely supported standard in many platforms and languages. Whatever the latter is, is not. What's better than writing a parser for the latter format, is not having to write anything and just using a library, which exists in practically every language for JSON.
Re: API Design Guide
#184Earlier quoted context omitted.
You can find smarter clients by Googling "hypermedia client". Also, O'Reilly just published a book on the topic: http://shop.oreilly.com/product/0636920037958.do
But would anybody really want to use a hypermedia client versus a regular client? Of course not. The regular client can be optimized properly at the level it needs to be to make the user's interaction smoother.
Re: API Design Guide
#185Earlier quoted context omitted.
The answer to that is really simple: JSON is a widely supported standard in many platforms and languages. Whatever the latter is, is not. What's better than writing a parser for the latter format, is not having to write anything and just using a library, which exists in practically every language for JSON.
Ever heard of LISP, or S-expressions?
There are data interchange formats that use S-Expressions, namely EDN[1]. But JSON remains the most popular format for its widespread support, and its few data types map to most languages.
Re: API Design Guide
#186Earlier quoted context omitted.
It's interesting that both of these guidelines kind of reject HATEOAS by mandating explicit versioning. It seems that HATEOAS was never really a thing. It's just too complicated to implement in practice. In that sense, REST in practice has always been just RPC without a clear spec for procedure call like XML or JSON RPC.
It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…
Your client then can machine read that documentation (which can have long-lived cache headers or be immutable, so your client doesn't spend it's whole time re-checking documentation).
There will be a set of definitions that the client understood when it was coded, and by checking a payload for matching meanings, it can consume the information.
If it finds something it doesn't understand, it could even try to take some compensating action (e.g. suppose it's a client which displays images to it's users, and it encounters a new type of image format. It could perhaps look up a registry of javascript canvas image renderers and download suitable code to display the new image).
Re: API Design Guide
#187Earlier quoted context omitted.
If you get back an URL to the document instead of the ID, then whenever you need to refer to that document, you need the whole URL. That means that it can't change, which I thought was one of the arguments for using HATEOAS, that you don't need to hardcode the URLs, and can "evolve" the API without breaking clients.
This is a point which is I think overplayed by HATEOAS fans and under-appreciated by HATEOAS haters; using URLs as IDs makes it easier to evolve the API in many cases, but it doesn't make it completely painless to do so. If you have an object which links to `/users/1/`, and want to change that URL to `/cool_users/1/`, what's the migration path? Without HATEOAS, you need to update all your clients' code to now generat…
No clients bother to do this, in the real world - they just hard code/compose the URLs that they need to use. Why make extra http calls when you don't have to? Why parse all the json-hal (or whatever) to "figure out" which URL to call next, when you don't have to?
Even if most clients did this, you can't enforce it, so not all of them will, so some will still break when you change URLs.
Re: API Design Guide
#188Earlier quoted context omitted.
This is a point which is I think overplayed by HATEOAS fans and under-appreciated by HATEOAS haters; using URLs as IDs makes it easier to evolve the API in many cases, but it doesn't make it completely painless to do so. If you have an object which links to `/users/1/`, and want to change that URL to `/cool_users/1/`, what's the migration path? Without HATEOAS, you need to update all your clients' code to now generat…
Yes, correct. However, this relies on clients using your API in a hateos way - which they have to go out of their way to do: starting at /, reading the responses, navigating down only using URLs that you return, etc... No clients bother to do this, in the real world - they just hard code/compose the URLs that they need to use. Why make extra http calls when you don't have to? Why parse all the json-hal (or whatever)…
Re: API Design Guide
#189Earlier quoted context omitted.
This is a point which is I think overplayed by HATEOAS fans and under-appreciated by HATEOAS haters; using URLs as IDs makes it easier to evolve the API in many cases, but it doesn't make it completely painless to do so. If you have an object which links to `/users/1/`, and want to change that URL to `/cool_users/1/`, what's the migration path? Without HATEOAS, you need to update all your clients' code to now generat…
Yes, correct. However, this relies on clients using your API in a hateos way - which they have to go out of their way to do: starting at /, reading the responses, navigating down only using URLs that you return, etc... No clients bother to do this, in the real world - they just hard code/compose the URLs that they need to use. Why make extra http calls when you don't have to? Why parse all the json-hal (or whatever)…
There's a good question about how long you can cache those URLs for as well; it's a non-starter for a client to have to traverse the whole tree from the root for every request. So can I cache the responses for the duration of my auth token, and get a new root node as part of my re-auth?
If you go down that route, now you need to maintain two versions again during migration (but you do keep the ability for 'well-behaved' clients to migrate versions without downtime).
As the sibling comment describes, you _can_ enforce this by obfuscating your URLs, but I've not had the guts to do that yet...
Another approach would be to write great client libraries yourself, so that you know that the clients are consuming the API correctly.
Re: API Design Guide
#190Earlier quoted context omitted.
Yes, correct. However, this relies on clients using your API in a hateos way - which they have to go out of their way to do: starting at /, reading the responses, navigating down only using URLs that you return, etc... No clients bother to do this, in the real world - they just hard code/compose the URLs that they need to use. Why make extra http calls when you don't have to? Why parse all the json-hal (or whatever)…
This is why my HATEOAS APIs always return urls in the form " https://mysite.com/{SHA256 hash}", and a façade API looks up the actual path from the cached hash. Hardcode that , bitches.
1) It makes manual testing annoying, 2) I have a nagging feeling that if my users are "doing it wrong" then maybe the API is doing it wrong...
Also I've been playing with autogenerating client implementations using autogenerated swagger specs, and that approach is incompatible with an actual opaque linked API. It would be nice to have the best of both worlds.