How to create a RESTful object with server calculated fields

1.4k views Asked by At

I have an object:

Account
{
    Id,
    Name,
    CurrentBalance
}

Id is an immutable key, Name is a mutable string, and CurrentBalance is calculated from all of the transactions associated with the account.

I am stuck on the fact that GET \Accounts\{Id} will not be idempotent because changes to a transaction will cause a change in CurrentBalance. Should I remove this field from the object and make a request like

POST \Accounts\{Id}\CurrentBalance

But now I have to make multiple calls to the server to get the CurrentBalance of all objects:

GET \Accounts
POST \Accounts\{Id1}\CurrentBalance
POST \Accounts\{Id2}\CurrentBalance
POST \Accounts\{Id3}\CurrentBalance
....

I guess I am just looking to see if there is already a standard way to handle this that I am missing?

UPDATE

Part 2 if the original object is ok via GET. My only way to update the Account.Name is via a PATCH as I cannot allow an update to CurrentBalance, correct?

NOTE

I realize I could put this on the client to have to get all transactions and calculate it, but I would prefer to do this on the server for multiple reasons

3

There are 3 answers

3
Darrel Miller On BEST ANSWER

Idempotency does not mean that you must always get the same response back.

Consider the resource /TodaysWeather. It would be pretty useless if it always returned the same value.

Idempotency simply states that if a client makes the same request multiple times instead of just once, the impact on the system (from the client's perspective) will be the same.

0
Justin Pihony On

I just re-read the HTTP specs and realized that if I want to be truly RESTful I have to make multiple calls because GET has to be safe.

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval.

I am not deleting this question because I think it could help others in the future, but if the majority disagree I will delete it

0
Kevin Stricker On

If it's important that you're able to PUT some data, then immediately retrieve the same data via GET, then you could simply treat it as a different resource entirely, e.g.:

# Change an account name
PUT \Accounts\{id}

# Get accounts/names/balances
GET \AccountDetails

# Get balance of an account
GET \AccountDetails\{id}\CurrentBalance

However, there's really no good reason to go through the trouble of doing that. Your PUT is idempotent as long as making the same request multiple times doesn't change the state of the system. Not changing the system's state if some spurious value is submitted is the correct behavior. In fact, if someone does try a PUT including CurrentBalance, you might want to return a 400 (Bad Request) status explaining that CurrentBalance can't be updated.