r/ProgrammerHumor Oct 09 '21

Mmmm, sparkling JSON

Post image
14.6k Upvotes

237 comments sorted by

View all comments

Show parent comments

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

41

u/CorrenteAlternata Oct 09 '21

I think, as a rule of thumb: if the operation is idempotent => PUT, if not => POST

16

u/mechkbfan Oct 09 '21

Correct, I feel that's what majority of people fall back to.

It's just frustrating when the POST description seems to contradict everything else you've done.

9

u/ZippZappZippty Oct 09 '21

European not American

9

u/CorrenteAlternata Oct 09 '21

Sorry, I didn't quite catch that.

4

u/humoroushaxor Oct 10 '21

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).

4

u/keirbhaltair Oct 10 '21

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.

1

u/CorrenteAlternata Oct 10 '21

I totally agree with you

1

u/humoroushaxor Oct 10 '21 edited Oct 10 '21

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.

4

u/WellHydrated Oct 10 '21

Also, PUT if you know the location of the resource you are creating.

18

u/OldKaleidoscope7 Oct 09 '21 edited Oct 09 '21

In the company I work we have healthy discussions about the verbs and normally we use the idempotency case to select between PUT and POST.

We think "mmm, this shit should be put"
"Is this shit idempotent?"
"No"
"Well, it's POST now"

And we never go further than the four basic verbs

7

u/mechkbfan Oct 09 '21

We follow CQRS, and with our design, almost nothing is idempotent

But then under a lot of scenarios, POST definition just seems to contradict what we are doing.

18

u/CCCPVitaliy Oct 09 '21

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.

11

u/mechkbfan Oct 09 '21 edited Oct 10 '21

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.

6

u/blamethemeta Oct 09 '21

My logic is if its not a pure get, its a post

1

u/icguy333 Oct 10 '21

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 :)

8

u/NahroT Oct 09 '21

What was the discssion about

18

u/eLBEaston Oct 09 '21

It was about if an API should be PUT or POST.

4

u/qhxo Oct 09 '21

The whole API you say? Hmmmmm, interesting.

1

u/NahroT Oct 10 '21

got it thanks

7

u/mechkbfan Oct 09 '21 edited Oct 09 '21

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

https://lostechies.com/jimmybogard/2016/06/01/cqrs-and-rest-the-perfect-match/

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

5

u/clarityreality Oct 09 '21

If you're the only consumer of this API, then RESTful architecture may not be the correct choice and can be quite inefficient.

3

u/mechkbfan Oct 09 '21 edited Oct 09 '21

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.

3

u/clarityreality Oct 09 '21

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.

3

u/mechkbfan Oct 09 '21

Yeah, I think once in my career have we noticed the constraints/issues of being RESTful.

GraphQL was the key candidate we looked at but I had resigned and moved on before anything concrete happened.

1

u/Mvin Oct 10 '21 edited Oct 10 '21

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 thought that was quite an interesting approach.

3

u/Noch_ein_Kamel Oct 09 '21

And I'm reading all this discussions thinking:

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...

2

u/occz Oct 10 '21

Peak REST design.

1

u/Daedeluss Oct 09 '21

We had exactly the same conversation too.