Updating a value RESTfully with Post
I'm rather new to REST so forgive me if this is a stupid question.
So, I have a customer resource. A customer has many credits. So, I imagine a URL for getting customer credits would be
customer/21/credits
(where 21 is a customer ID)
Now, how do I add to the credits, if I don't have the full amount of credits? E.g. a customer has 10 credits and I want to add 5. As I understand, if I'm using post I would do something like:
customer/21/credits?amount=15 (is this even correct?)
However, what if I just want to add to the existing credits? That is I want to send 5 credits and say add them to whatever the customer currently has? Do I define a kind of phantom resource such as addedCredits?
custome开发者_JAVA百科r/21/addedCredits?amount=5
then behind the scenes, I just do credits += 5?
You need to define how you're going to treat "credits" in your system; it matters whether or not you intend to define them as resources or as an attribute of your customer resource.
In the examples below, I'm going to use XML to represent the resources/entities. This may work for you, but you'll need to have some consistent way of representing your resources in requests and responses - this will help you avoid using query parameters (e.g. http://example.com?foo=bar) to define data that belongs in the request body.
A couple of ways of representing credits:
If a "credit" is an attribute of your "customer":
<customer id="21"> <balance>10</balance><!-- aka credit --> </customer>
Then you might as well just GET the customer, update the credit/balance with your client, and then PUT the
<customer>
back to/customer/21
.If a "credit" is its own resource:
You can POST the following to
/credit
:<credit> <dateApplied>2009-10-15 15:00:00</dateApplied> <customer href="/customer/21"/> <amount>5</amount> </credit>
Or you can POST the following to
/customer/21/credits
(assuming that URI is a list of all of the<credit>
s applied to the customer):<credit> <dateApplied>2009-10-15 15:00:00</dateApplied> <amount>5</amount> </credit>
This would "append" a new
<credit>
to the existing list. And also eliminates the need to provide the<customer>
in the entity, since it's already present in the URI.
I would use the same URL.
POST to customer/21/credits
with a POST variable called extraCredit set to 5. POST is supposed to be used for annotation of existing resources (or creating subordinate resources). There is no reason why you should need a new URL.
If an individual credit is a resource in your system that deserves its own URL, then the response URL from POSTing to customer/21/credits
should include the URL of the new credit resource e.g. customer/21/credit/12
.
You could define an XML representation of credits to POST to customer/21/credits
, but I would not consider it worthwhile in this simple example. REST payloads do not have to be XML.
A URL like customer/21/addedCredits?amount=5
doesn't make sense to me because it doesn't really identify a resource. If someone issues a GET to customer/21/addedCredits?amount=5
what would you return to them?
The one thing you should definitely not do is change the state of the customer resource when someone GETs a URL like customer/21/addedCredits?amount=5
. Since the title of your question acknowledges that you will need to use POST your probably realise this. GET is supposed to be safe, which means that issuing a GET shouldn't change a resource's state.
Ultimately the implementation is up to you. WHile URI query parameters are generally frowned upon, it doesn't mean you can't use them. Personally I would make the post URI something like:
customer/21/credits/add/5
but nothing says you can't do something like what you have or :
customer/21/credits/add?value=5
For starters using the URI query parameters should be a "bad smell" to you. Second you need to look at defining some mime types that your clients and server can talk in so for instance with your credit example:
If I do a GET on customer/21/credits I might get a document like this:
Content-type : application/vnd.creditstore+xml
<credits>
<user>21</user>
<credits>10</credits>
<a href="/customer/21/credits/add" rel="add">Add credits to this account</a>
</credits>
This tells a client who understands your vocab that if they want to add credits to this user they need to post something to that link. This is HATEOAS (god I hate that acronym, I probably even spelled it wrong).
Now this is all completely off the top of my head, and I probably butchered that XML example but it should get you thinking in the right direction.
精彩评论