Although the current REST behaviour, providing a lto of 204 codes, on successful transactions, is correct, it is pretty confusing for developers, and there seems to be no agreement on minimal responses that might trigger 200 or 201 responses that would be expected by a lot of devs.
Could we agree that return=minimal should (at minimal!!) return the contents of the ETag
e.g.
/composition - the uid
/ ehr - the ehr_id/value
etc.
IMO this will make the API much easier to navigate and use.
While I understand the general problem here, I think it is actually correct how it is.
Returning âthe contents of the ETagsâ is problematic, because just the content is no valid document. For instance, it is neither JSON nor XML. Of course it could be formatted that way, but then we have a full (yet small) valid body and therefore no 204 situation anymore.
On top of that, I just donât see the necessity here, as the ETag header already contains that information. As a developer, I can easily access the header data. And why transfer the same piece of data twice?
But Iâm not very experienced in web standard implementations and donât know how other big tools or APIs are handling that. So if the best practice is to navigate around 204s I would like to learn more about that.
Some references, just for the sake of completeness:
10.2.5 204 No Content
The server has fulfilled the request but does not need to return an entity-body [âŚ]
4.2. The âreturn=representationâ and âreturn=minimalâ Preferences
[âŚ] The âreturn=minimalâ preference, on the other hand, indicates that the client wishes the server to return only a minimal response to a successful request. Typically, such responses would utilize the 204 (No Content) status [âŚ]
My understanding is that @sebastian.iancu and the other designers of the REST API tried very hard to do the design âcorrectlyâ - exactly as you suggest.
The problem I see is that this is not actually how most of the real-world rest services actually operate. In that sense I am a good example of a naive web-app developer. I had never seen a 204 before (for a valid response) and the Rest client library I was using (fairly mainstream) made it very hard to extract a header tag in the response, compared to parsing the response body - trivial.
We might be in danger of doing the âright thingâ in IETF terms but confusing the rest of the world who have never head or seen 204 being used for a successful transaction.
Thanks for the references. My suggestion is that we construct some simple very minimal âdefaultâ response bodies - essentially the ETags. If people want to go super-minimalistic they can set return=minimal and get a 204.
Yes @jake.smolka you are very right about it, this is the way it should be if you follow REST standards - it might not look very friendly (but not confusing), âŚbut it is anyway consistent.
ETag is not a valid option to rely for that id, I would rather suggest the Location header.
We have a ticket now, SPECITS-50 and weâll consider of making this a bit more user friendly, for instance by adding extra openEHR-headers for uid, or using another (own) return type that allows references or a sort of âoperationOutcomeâ - we need to investigate which one is better.
I would definitely push for something coming back in the body.
It is just much,much easier to access/process that from typical REST libraries. Handling response Headers is often very obscure and badly documented, in my (limited but probably typical) experience. The exact format is not so important.
It is very common to need to do some sort of operation on a key identifier being produced e.g the compositionID or ehrId, templateId. Queries work fine as they are - 204 for an empty result is fine
Should I think in this direction: Http - FHIR v5.0.0, returning a sort of operation outcome, or just only the uid-reference of the resource created or updated?
ACtually that is quite confusing - the details for the different operations suggests sending 200s and 204s but does not specify any default body content. Implies to me (may be quite wrong) that the correct response to e.g a successful POST is a 201, even if the body response is emptyâ unless return=minimal is set when it should be a 204.
THe Operation-Outcome seems overly complicated. For the few resource where this is an issue, I would favour just a very simple uid-reference being returned. It is very convenient to have it there and it prevents the 204 issue unless someone explicitly sets âminimalâ. THe only exception might be templates where having uid as well as templateId might be helpful
Once you get used to it, it becomes clear; it might be confusing in the beginning if you are not doing this on the daily bases. Not all programmers are web-programmers, and even if they are, then not all of them are programming/design/using restful services. It is apparently simple, and yet it isnât. It requires experience to be gained. It is perhaps like designing good archetypes, implementing the right design pattern: everybody using AD can create an archetype, but thatâs not always the best archetype, and a lot of AD features might remain unused and unknown to those user.
Back to our specs, I think we should always try to make things clear and easier, although we should also comply with standards and best practices, even when they might be apparently confusing.
To further explain on the problem/principle you started above:
RESTful services are dealing with Resources, in our case any of COMPOSITION, EHR, FOLDER, etc.
when you create (POST), you get back the persisted resource (representation) with code 201 and location, or an ok-but-no-content 204 and the location, in case the preference is to keep http low (return-minimal, just headers)
when you update (PUT) or create at your location (create using PUT), you get back 200 if update was ok or 201 if you created something new, both with resource in the body (i.e. representation) or you get 204 with no-body and only header, if you prefer minimal response (i.e. headers only)
in standard interaction with restful services you cannot expect that the returned resource has different (semantic) type than the resource in the request - i.e. you cannot usually save composition and get back an id (as body)
http negotiation is important: server should be able to deal with many client preferences, and clients should know what/how to ask the server; so headers, status codes
adding extra returned headers is allowed and should be easy to for clients to process
changing return body type is acceptable as long as is requested (with prefer header), and there we could add only the uid value - not very restful interaction, but at least is consistent and could be nicely documented.
Hope this clears some confusions - I am myself not a REST expert, just following places like:
@ian.mcnicoll They would be the perfect resource to do a field study on. Can you please show us the real-world REST services that apply REST different than the openEHR REST API
Also, can you share what REST client library you worked with? From the client perspective, Iâm working with tools like Postman and Insomnia on a daily basis and both can access response headers easily. So I never had any problem with them.
Currently the spec says:
In case no Prefer header is present in request, the default response policy is return=minimal.
Maybe we could switch the defaults here. Would that be less confusing, if a request without any specific Prefer header would just respond with the full response object (incl. its object or version ID)?
The negative implications I can think of right now would only impact performance or bandwidth. Would there be more to consider @sebastian.iancu?
We could switch the default behavior to representation, if thatâs what raised and acceptable by SEC group (need to discuss if there would be side effects in existing implementations).
I would say that may bring the default closer to what is more convenient for the developer.
Iâm currently implementing a bunch of examples to connect a clinical applicationâs backend to our current REST implementation (which is pretty out of date tbh) and when I put myself into the position of the developer whoâll use my code as a starting point; I can see that the most convenient thing would be to have whatever composition he/she POSTâed to the endpoint returned as the payload of the response.
Thatâs whatâd feel more natural to me, because in the happy path/scenario, Iâll push a composition and get back one with a uid value in the composition payload, which I can then use or throw away.
Itâs not only about the uid value (whichâll be in the location header as well) I have a habit of trying to switch to persisted representation of clinical data as early as possible in the code. So if I need to push something to CDR and then use it for any purpose, Iâd rather use the persisted version than the one I sent over the wire, because if anything went wrong (I forgot to map an optional data item to the composition dto etc), using the persisted version will break my tests and Iâll know about it.
Yes, I can still make another req and get the persisted version but having it around in the body of 201 is more convenient. I appreciate this is highly subjective, and I may be violating some REST principal but from a productivity point of view, I find this to be a pragmatic approach.
This is highly subjective, so I wonât get into a discussion to defend it, but I wanted to make the point that there is at least one member of SEC who thinks itâd help to have the default returning the full representation
Iâd still prefer a representation that had something simpler than the full resource as default - are we going to do the same for the POST /template and return the full .opt
However ⌠at least defaulting to return=representation will prevent âaccidentalâ 204 messages.
Appreciate that what I am suggesting is âREST-heresyâ but all of these little tings just put barriers in the way for folks who do not have time to understand the âcorrectâ approach.
Examples of the fiddly things that come into play when you use response headers with typical client libraries.
None of this means that Response headers are wrong but they are fiddly to process and not well supported âout-of-the boxâ in typical REST library documentation.
I would not be too bothered if opt POST endpoint behaved the same, but thatâs a much less frequently invoked call compared to a POST to âŚ/composition endpoints, so the benefit I see and describe above does not apply.
for compositions, I donât think we can ever agree on a brief subset of a composition to be returned in the body, thatâs just too subjective to be a useful default. If you can identify a useful subset which you can then request with representation=ians_super_duper_composition_subset header, then it may be a nice convenience, but unlikely to be hit the 80/20 mark as a default behaviour.
youâre just asking for a content level representation of what is in the headers. In this case, you shall not have my sympathy Dr. McNicoll Just parse your headers like everybody else.
Typically, such responses would utilize the 204
(No Content) status, but other codes MAY be used as appropriate, such
as a 200 (OK) status with a zero-length response entity. The
determination of what constitutes an appropriate minimal response is
solely at the discretion of the server.
So then could state (perhaps in R1.1.0) that minimal is to return the uid like you suggested @ian.mcnicoll above?!
This of course requires further discussions, like âŚassuming the client preference is to return minimal, when should the server return a status 204 without any content body, and when should return just the uid and status 200/201. Or we could just say that minimal is always at least the id/uid (so status 204 is not used).
The other option is to introduce a new Prefer: return=uid or similar request header, which will instruct the server in returning only the unique identifier in the body (content type text/plain), beside the other standard headers. Or we could specify an extra response header openEHR-uid to be sent always upon POST/PUT/DELETE.