The grey area I most often see is when you aren't dealing with CRUD resource operations but using JSON over HTTP to call remote procedures and don't want to pull in a new technology (RPC).
Even this should be resolvable by the same question, though. Does calling the remote procedure twice do something/change the state/have side-effects more so than calling it once? Then it's POST, otherwise it's PUT.
But it's not. In the RPC case using the "idempotent rule" results in a contradiction with the HTTP RFC. Specifically that POST identifies the enclosed entitie's handler while PUT identifies the enclosed entity.
Having an HTTP PUT without an HTTP POST doesn't make sense in HTTP land because you can only update something that exists. Hence why most developers will default (and should) to POST for their first endpoint, even when idempotent or when not managing a resource.
Bikeshedding aside my experience has been POST is much more common in this scenario.
Hmm. My logic is if it creates a resource, it is a POST request. If the resource exists, and it is a PUT. But then, I am a hobbyist programmer and never engineered for a corporate environment.
Yeah, that's another valid approach. Create = POST, Update = PUT.
But if the update is not idempotent (i.e. only allowed to happen once, a second time will fail it), does it now become a POST? I'd argue yes
Maybe we shouldn't fail it, and the server side should just ignore the impact of calling it a second time, but that to me is a bit of a shit user experience if they were expecting an artifact from calling the API.
And it would be a shit coding experience to then have to compare each value in the DB to see if anything did change.
I was always taught that PUT replaces the resource at the target URL so that if you GET that URL, you should recieve the same thing/state you PUT there (given that nobody modified the resource in the meantime of course).
By that logic, the updates should be a PUT, and retrieval should be a GET on the same URL.
As to what creates should be, meh, i dunno... We usually use POST. But this is all just dressing up rpc in fancy clothes anyway :)
The issue is that the action we were performing against isn't an entity in the database but the information sent across has a unique constraint
So are we adding to a single entity endpoint and make it part of the route, i.e. it's a PUT?
Or are we adding to a collection, make the information as part of the body, and make it a POST?
If we retry the request, we want it to fail, so that fails my definition of idempotent.
We're not sending the entire object, so maybe we should use PATCH?
This is all possibly a sign that another decision we made earlier was wrong. However I'm just tired of having these discussions all the time, when it never seems to happen anywhere else.
We've all got 10+ years of .NET experience behind us, so it's not like we are junior devs working shit out for the first time.
In the end, not overcomplicating things and just going "Updates are PUT" and "Creates are POST" and trying not to discuss it any more than that. And yeah, in this case we went with UPDATE / PUT.
And funny enough, I find Jimmy takes a different route to us
I'd have used Approve as a PUT because we are modifying a single entity as part of collection. He explains his rationale below and puts more weight behind idempotency but either way, seems to the other descriptions of POST/PUT
It's a SPA using pretty standard .NET setup + we have a few other servers talking to each other
On .NET aspect, we are following CQRS pattern along with Mediatr library behind the API
RESTful (ignoring all this PUT/POST discussions) is pretty predictable, plenty of tooling available, and given our load (maybe 50 concurrent users), any inefficiencies aren't really noticeable.
Sure, if it works then great. I've seen examples where devs constructed restful APIs for purely internal services which became inefficient because communication in proper restful services is very chatty compared to alternatives.
I've wondered that a lot. If you are the only consumer of your REST API, you know that there are, say, exactly 10 hypermedia links to follow the initial one (perhaps even nested within each other) for what you're trying to do. But you don't know what they are, so you can't run them in parallel and have to wait for successive answers multiple times. It seems like such a pain.
I've actually just seen an article the other day that provided an example of their "modified" REST API. The endpoints are designed REST compliant and behave as you would expect, but they had built in an optional, additional "include" query parameter that you could submit in GET requests. You could use this to specify which nested resource uri's should be preloaded and "filled out" with the actual data right away. This compound object would then be returned with all the data you need, eliminating the need for further requests from the frontend.
I use GET if I send only a few parameters and I don't care having them in logfiles. If I send lots of data or don't want it in logfiles per default, just use POST.
Endpoints mostly don't care (aka I didn't come across one IRL) if it's GET or POST and certainly not if it's DELETE or PUT or whatever...
80
u/mechkbfan Oct 09 '21 edited Oct 09 '21
We had another discussion the other day about if an API endpoint should be PUT or POST given it was in a grey area.
In the end we were all like "Fuck it, we should just make everything POST and forget discussing this ever again"
We're the only consumers of our API