Adding a RESTfully Resource Attribute

This is a continued update of the RESTfully value with the message

How to simply add a resource attribute using REST. Imagine that I have a client. Balance and balance are int. Let's say I just want to tell the server to add 5 to the current balance. Can I do it calmly? If so, how?

Keep in mind that the client does not know the existing balance of the client, so he can’t just

  • get customer
  • customer.balance + = 5
  • send a message

(there would also be problems with concurrency with the above.)

+4
source share
3 answers

Simple, a little ugly:

This is a simpler version of my answer to your other question .

I think that you are still within the limits of REST if you do the following. However, I am curious what others think about this situation, so I hope to hear from others.

Your URI will be:

/customer/21/credits 

You send a credit resource to the URI (maybe <credit>5</credit> ), then the server can take the client’s balance and += with the value provided. In addition, you can support negative loans (for example, <credit>-10</credit> );

Please note that /customer/21/credits does not support all methods. POST support is only perfectly acceptable.

However, this is a little strange if loans are not a true resource in your system. HTTP spec says:

If the resource was created on the source server, the response MUST be 201 (created) and contain an object that describes the status of the request and refers to the new resource and the Location header.

Technically, you are not creating a resource here, you are adding to the client’s balance (which is really the totality of all previous loans in the system). Since you do not support the loan (presumably), you really cannot return the link to the newly created loan resource. Perhaps you could return the client’s balance or <customer> , but this is a little unintuitive for customers. That is why I believe that considering each loan as a new resource in the system is easier to work with (see below).

My preferred solution:

It depends on my answer in another question. Here I will try to approach it in terms of what the client / server does:

  • Customer:

    • Creates a new credit resource:

       <credit> <amount>5</amount> </credit> 
    • POST Resources for /customer/21/credits

      POSTing here means: "add this new <credit> , which I am providing to the <credit> list for this client.

  • Server:

    • Gets POST on /customer/21/credits
    • Accepts the amount from the request and += to the client’s balance
    • Saves credit and its information for later search
    • Sends a response to the client:

       <credit href="/customer/21/credits/credit-id-4321234"> <amount>5</amount> <date>2009-10-16 12:00:23</date> <ending-balance>45.03</ending-balance> </credit> 

This gives you the following benefits:

  • Access to loans can be obtained later using id (with GET /customer/21/credits/[id] )
  • You have a complete credit history audit trail.
  • Clients can, if you support it, update or delete loans by id (using PUT or DELETE)
  • Customers can get an ordered list of loans if you support it; e.g. GET /customer/21/credits may return:

     <credits href="/customer/21/credits"> <credit href="/customer/21/credits/credit-id-7382134"> <amount>13</amount> ... </credit> <credit href="/customer/21/credits/credit-id-134u482"> ... </credit> ... </credits> 
  • It makes sense, because the client balance is indeed the end result of all loans applied to this client.
+2
source

To think about it with REST-ful, you will need to think about the action itself as a resource. For example, if it was a banking business and you wanted to update the balance in your account, you would create a deposit resource and then add one of them. The consequence of this would be to update the customer balance

It also helps to cope with concurrency problems, because you will be sending a +5 action, rather than requiring prior knowledge of client balance. And you can also remember this resource (for example, deposit / 51 for a deposit with identifier 51) and see other information about it (i.e. the reason for the deposit, date of deposit, etc.).

EDIT: I realized that using identifier 5 for deposit actually confuses the problem, so I changed it to 51.

0
source

Well, there is an alternative besides @ Rob-Hruska's solution.

The basic idea is the same: think of each credit / debit transaction as a separate transaction. However, I once used a backend that supports storing data without a schema in json, so I end up defining the API as PUT with dynamic field names . Something like that:

 PUT /customer/21 {"transaction_yyyymmddHHMMSS": 5} 

I know this is NOT suitable in the context of a credit / debit because an active account can have growing transaction records. But in my context, I use this tactic to store the final data (in fact, I kept different lots of GPS route points during the trip).

Cons: This api style has a lot of dependency on a circuit without being tied to a backend scheme.

Pros: At least my approach is completely RESTful from a semantic point of view.

Unlike @ Rob-Hruska, the “Simple, slightly ugly” solution 1 does not have a valid Location header to return in the “201 Created” response, which is not the usual RESTful behavior. (Or maybe we can allow @ Rob-Hruska solution 1 to also return a dummy location header that points to the “410 Gone” or “404 Not Found” page. Is this more RESTful? Comments are welcome!)

0
source