Live data from Hacker News

REST Anti-patterns

marcelo-cure.blogspot.com

11–20 of 133 posts

Re: REST Anti-patterns

#11
What about error representation? Most of the time I find that actually representing errors is the hard part of creating a REST api.

You usually want some representation of each field, plus maybe a generic one. I always have troubles with this. Is there a standard or a proper way to define/do this? I would be very interested.

Re: REST Anti-patterns

#12
post #2

Why is POST /accounts/4402278/close correct in the first example? According to the rest of the post, PUT should be a better option. Closing an account seems to me like its updating a resource, not creating one. Also, will calling that url close the account multiple times? POST is not supposed to be idempotent

Because the action is designed to affect the /accounts/4402278 resource. Requiring a PUT here would (semantically) imply that /accounts/4402278 is a container that has various sub-resources.

Also, there is nothing wrong with having an idempotent POST effect. "POST is not supposed to be idempotent" is not the same as "POST should never be idempotent". In this case, the POST acts on a boolean flag; it is harder to make it not idempotent.

Re: REST Anti-patterns

#13
post #9

Earlier quoted context omitted.

Or, if you really want to be dogmatic, use DELETE when destroying something...in this case the customer account.

I don't think I would assume that "close" is the same as a delete.

Then why not cater for your own verb instead?

Re: REST Anti-patterns

#15
post #5

"Correct POST /accounts/4402278/close" bullshit. POST should not contain all details in URL. POST can have body and each query should not be unique. Stopped reading after that.

I disagree. In the example, account 4402278 is a resource represented at /accounts/4402278; actions on that resource should be performed … on that resource, not on some other resource (e.g. all accounts, at /accounts).

This also gives increased future-proofing, since someday one might have uncloseable accounts; those accounts could still live under /accounts, but would simply have no /close endpoint (as opposed to having /accounts/close, which sometimes works and sometimes doesn't).

Re: REST Anti-patterns

#16
Other commenters are correct that POST /accounts/4402278/close is not right (and also fairly hilariously contradicted in the next section).

Account status (open, closed, suspended, whatever else) is a property of the account, in the same way that the account owner's name is a property of the account. If you went to all the trouble to represent each account as its own resource, which I assume responds correctly otherwise to GET, POST and PUT requests, why is this one property special enough to get its own endpoint? Why would you not just PUT or PATCH the account to change the "status" property to "closed"?

In my experience, programmers typically break best practices in this way when there is special logic that needs to happen when the property changes. In other words, PUT is fine as long as it's only overlaying new data and not triggering other processes, but closing an account kicks off a whole host of internal processes at the business, so it seemed reasonable to someone to make it a separate endpoint.

This either represents a friction between good API design and what programmers find reasonable ("I have to make a bunch of special things happen, so I'll bundle them into their own function and expose them"), or the API framework isn't flexible enough to supply hooks to insert logic at field-level changes, or both.

Re: REST Anti-patterns

#17
post #2

Why is POST /accounts/4402278/close correct in the first example? According to the rest of the post, PUT should be a better option. Closing an account seems to me like its updating a resource, not creating one. Also, will calling that url close the account multiple times? POST is not supposed to be idempotent

Or, if you really want to be dogmatic, use DELETE when destroying something...in this case the customer account.

Closing it may not delete it, but simply mark it as closed.

Re: REST Anti-patterns

#18
post #2

Why is POST /accounts/4402278/close correct in the first example? According to the rest of the post, PUT should be a better option. Closing an account seems to me like its updating a resource, not creating one. Also, will calling that url close the account multiple times? POST is not supposed to be idempotent

You may be operating under the misapprehension that "POST" means "CREATE".

It WOULD make a nice set with CRUD operations:

POST - Create

GET - Read

PUT - Update

DELETE - Delete

But that's not actually how the HTTP verbs are defined[1]. Instead, my own mental mapping looks something like this:

GET - read information. Must be idempotent and side-effect free so this one really IS just for reading.

DELETE- delete. Usually pretty obvious except for arguments about whether a "soft delete" (mark as deleted but don't remove from the underlying DB -- like a bank account which can be closed but continues to exist (its account number, for instance, is never freed up).

PUT - update things. Must be idempotent. If you're a stickler for doing things right, this should NOT be use for a "partial update" (where you supply a few fields and everything else is left "as is") but only for a "total update" (where the new thing you sent in replaces whatever was there).

POST - "do it". Means to do the obvious thing (whatever that is for this URL).

PATCH - great idea. Maybe in a few years support for it will be ubiquitous enough that we can actually start using it. If we DID us it, this would be the partial update variant of PUT.

OPTIONS and HEAD - occasionally used at a framework level. You won't ever use it.

everything else - don't use it.

[1] - https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Re: REST Anti-patterns

#19
post #15
post #5

"Correct POST /accounts/4402278/close" bullshit. POST should not contain all details in URL. POST can have body and each query should not be unique. Stopped reading after that.

I disagree. In the example, account 4402278 is a resource represented at /accounts/4402278; actions on that resource should be performed … on that resource, not on some other resource (e.g. all accounts, at /accounts). This also gives increased future-proofing, since someday one might have uncloseable accounts; those accounts could still live under /accounts, but would simply have no /close endpoint (as opposed to ha…

[deleted]

Re: REST Anti-patterns

#20
post #2

Why is POST /accounts/4402278/close correct in the first example? According to the rest of the post, PUT should be a better option. Closing an account seems to me like its updating a resource, not creating one. Also, will calling that url close the account multiple times? POST is not supposed to be idempotent

You could PUT the entire value of the resource representing account 4402278 (to include owner's name, contact information, history, &c. &c. &c., or you could PUT a custom range to just update the account status, or you could POST just the update. Honestly, if custom ranges worked a bit better, that'd probably be the best option.

Given that they don't, really, I think POST isn't terrible. At least it's not GET!

Post reply on HN