标签云

微信群

扫码加入我们

WeChat QR Code


It may be helpful to use the definitions in HTTPbis - Roy put a fair amount of work into clarifying them. See: tools.ietf.org/html/…

2018年10月23日12分46秒

Just to bring MarkNottingham's comment to the latest revision, here's POST and PUT, as defined on HTTPbis.

2018年10月23日12分46秒

It seems to me that this debate has arisen from the common practice of oversimplifying REST by describing the HTTP Methods in terms of CRUD operations.

2018年10月23日12分46秒

Unfortunally the first answers are wrong about POST. Check my answer for a better explanation of the differences: stackoverflow.com/a/18243587/2458234

2018年10月23日12分46秒

PUT and POST are both unsafe methods. However, PUT is idempotent, while POST is not. - See more at: restcookbook.com/HTTP%20Methods/put-vs-post/…

2018年10月23日12分46秒

I think one cannot stress enough the fact that PUT is idempotent: if the network is botched and the client is not sure whether his request made it through, it can just send it a second (or 100th) time, and it is guaranteed by the HTTP spec that this has exactly the same effect as sending once.

2018年10月23日12分46秒

Jörg W Mittag: Not necessary. The second time could return 409 Conflict or something if the request has been modified in meantime (by some other user or the first request itself, which got through).

1970年01月01日00分02秒

If I'm not mistaken, what we should be stressing is that PUT is defined to be idempotent. You still have to write your server in such a way that PUT behaves correctly, yes? Perhaps it's better to say "PUT causes the transport to assume idempotence, which may affect behavior of the transport, e.g. caching."

2018年10月23日12分46秒

JörgWMittag Idempotence catchphrase? How about "Send and send and send my friend, it makes no difference in the end."

1970年01月01日00分02秒

Thinks of them as: PUT = insert or update; POST = insert. So when you make two PUT - you get the one new record, when you do two POSTs - you get two new records.

2018年10月23日12分46秒

I agree, wherever idempotence is concerned it should trump any other concerns since getting that wrong can cause many many unexpected bugs.

2018年10月23日12分46秒

If POST can update a resource, how is that not idempotent? If I change a students age using PUT and do that 10x times the students age is the same if I did it once.

2018年10月23日12分46秒

Schneider, in this case your server is making an extra effort to guarantee idempotence, but it is not advertising it. Browsers will still warn the user if they try to reload such a POST request.

2018年10月23日12分46秒

Schneider POST may create a subsidiary resource; hence you can POST to collection, like POST /expense-reports and it would create as many entities (expense reports) on your server as the quantity of requests you've sent, even if they are completely similar. Think of it as inserting the same row in the DB table (/expense-reports) with auto-incremented primary key. Data remains the same, key (URI in this case) is generated by server and is different for every other insert (request). So, POST effect can be idempotent, but also may not. Hence, POST is not idempotent.

2018年10月23日12分46秒

Let's say we have entities which may have two properties - name and date. If we have an entity with an existing name and date, but then make requests to it specifying only a name, the proper behavior of PUT would be to obliterate the date of the entity, whereas POST may update only the properties specified, leaving the unspecified properties as they were before the request was made. Does that sound correct/reasonable, or is it an improper use of PUT (I saw references to PATCH, which it seems would be more appropriate, but doesn't exist yet)?

2018年10月23日12分46秒

Or from the other side of the fence: PUT if the client determines the resulting resource's address, POST if the server does it.

2018年10月23日12分46秒

I think that this answer should be edited to make it more clear what DanMan pointed in a very simple way. What I find the most valuable here is the note at the end, stating that a PUT should be used only for replacing the whole resource.

2018年10月23日12分46秒

PATCH isn't a realistic option for at least a few years, but I agree with the ideology.

2018年10月23日12分46秒

I'm trying to understand, but using PUT to create something would only make sense if the client knows for sure that the resource doesn't exist yet, right? Following the blog example, say you have created hundreds of blog posts in a couple of years, then accidentally pick the same title as you did for a post two years ago. Now you have gone and replaced that post, which wasn't intended. So using PUT to create would require the client to track what is taken and what is not, and could lead to accidents and unintended side effects, as well as having routes that do two entirely different things?

1970年01月01日00分03秒

You are correct. PUTting a blog post at the same url as an existing one would cause an update to that existing post (although you could obviously check first with a GET). This indicates why it would be a bad idea to use just the title as the URL. It would however work anywhere there was a natural key in the data... which in my experience is rare. Or if you used GUIDs

2018年10月23日12分46秒

This post was helpful to me in understanding that POST adds "something" as a child to the given collection (URI), whereas PUT explicitly defines the "something" at the given URI location.

2018年10月23日12分46秒

This is the best answer, here, I think: none of this "POST can update a resource" nonsense. I like your statement, "Update can only be performed with PUT".

2018年10月23日12分46秒

No, PUT is not for update or create. It is for replacing. Note that you can replace nothing with something for the effect of creating.

2018年10月23日12分46秒

7hi4g0 PUT is for for updating with a complete replacement, in other words, it replaces. You replace nothing with something, or something with a completely new something. PUT is not for making a minor change (unless you have the client make that minor change and provide the entire new version, even what is remaining the same). For partial modification, PATCH is the method of choice.

1970年01月01日00分04秒

thecoshman You could, but it wouldn't be too clear that create is also covered in there. In this case, it is better to be explicit.

2018年10月23日12分46秒

Actually, it should be POST /users. (Note that /users is plural.) This has the affect of creating a new user and making it a child resource of the /users collection.

2018年10月23日12分46秒

DavidRR to be fair, how to handle groups is another debate altogether. GET /users makes sense, it reads as you want, but I'd be ok with GET /user/<id> or POST /user (with payload for said new user) because it reads correctly 'get me users 5' is odd, but 'get me user 5' is more natural. I'd probably still fall down on the side of pluralisation though :)

2018年10月23日12分46秒

Sloppiness may have cause it to be commonly taught that there are only two verbs you need: GET and POST. GET to obtain, POST to change. Even PUT and DELETE were performed using POST. Asking what PUT really means 25 years later maybe a sign we learned it wrong at first. REST popularity drove people back to the basics where we must now unlearn past bad mistakes. POST was overused and now commonly taught incorrectly. Best part: "POSTing twice with the same data means create two identical [resources]". Great point!

2018年10月23日12分46秒

How can you use PUT to create a record by the ID, like in your example user 5 if it doesn't exist yet? Don't you mean update, replace if already exists? or something

2018年10月23日12分46秒

Coulton: I meant what I wrote. You insert user 5 if you PUT to /users/5 and #5 does not exist yet.

2018年10月23日12分46秒

Coulton: And PUT can also be used to replace the value of an existing resource in its entirety.

2018年10月23日12分46秒

"Prefer PUT over POST"... care to justify that?

2018年10月23日12分46秒

POST /items adds a new item to an already defined resource ('item'). It does not, as the answer says, "create a group." I don't understand why this has 12 votes.

2018年10月23日12分46秒

Out of the box, Rails does not support 'creating a group' via REST. To 'create a group' by which I mean 'create a resource' you have to do it via the source code.

2018年10月23日12分46秒

This is a fair guideline, but an oversimplification. As the other answers mention, either method could be used for both create and update.

2018年10月23日12分46秒

I agree with the answer with a slight modification. Use POST to create and PUT to update the resource completely. For partial updates, we can use PUT or PATCH. Lets say we want to update the status of a group. We can use PUT /groups/1/status with the status is the request payload or PATCH /groups/1 with the details about the action in the payload

2018年10月23日12分46秒

It should also be made clear that PUT /items/42 is also valid for creating a resource, but only if the client has the privilege of naming the resource. (Does Rails allow a client this naming privilege?)

2018年10月23日12分46秒

There's nothing wrong with allowing PUT to create resources. Just be aware that it means that the client provides the URL.

2018年10月23日12分46秒

There's something very wrong with allowing PUT to create resources: the client provides the URL. That's the server's job!

2018年10月23日12分46秒

Joshcodes It is not always the case that it is the server's job to create client ids. I have increasingly seen designs that let clients generate some sort of UUID as the resource id. This design lends itself in particular to increase scale.

2018年10月23日12分46秒

JustinOhms I agree with your point about client generated IDs (side note: all systems designed by me since circa 2008 require the client to create the ID as a UUID/Guid). That does not mean the client should specify the URL.

2018年10月23日12分46秒

Joshcodes It's matter of separating concerns. Where the URL is generated is actually of little consequence. Yes the server is responsible for delivering content from the correct URL but that does not limit a server from responding to a request on an incorrect URL. The correct response from the server in this case is a 308. A proper client will then retry the PUT on the correct URL. Another example is a distributed system where not all nodes know of all resource provided by clients. Here a PUT to create would be perfectly valid because for that server node the resource does not exist.

2018年10月23日12分46秒

Would a 409 Conflict response be the appropriate code for something like trying to create a new account with a username that already exists? I've been using 409 for versioning conflicts specifically, but after reading your answer, I wonder if it shouldn't be used for any "duplicate" requests.

2018年10月23日12分46秒

EricB. Yes, in the situation you describe "due to a conflict with the current state of the resource" the operation fails. Additionally, it is reasonable to expect that the user can resolve the conflict and the message body only needs to inform the user that the username already exists.

2018年10月23日12分46秒

Joshcodes can you say more about the conflict resolution process? In this case, if the username already exists is the client expected to prompt the end user for a different username? What if the client is actually trying to use POST to change the username? Should PUT requests still be used for updating parameters, while POST is used for creating objects whether it be one at a time or several? Thanks.

2018年10月23日12分46秒

BFar2 if the username already exists then the client should prompt the user. To change the username, assuming the username is part of an already created resource which needs modified, PUT would be used because you are correct, POST is used for create, always and PUT for updates.

2018年10月23日12分46秒

explaining things using short and effective language is also a desirable skill

2018年10月23日12分46秒

So in summary: POST for inserts, PUT for updates

2018年10月23日12分46秒

MobileMon No, REST methods are not CRUD.

2018年10月23日12分46秒

"POST can also be used for non-idempotent updates to existing objects (especially, changing part of an object without specifying the whole thing" That's what PATCH is for

2018年10月23日12分46秒

for PUT is similar to INSERT or UPDATE query

2018年10月23日12分46秒

actually PUT You can think of similar to "UPDATE STUDENT SET address = "abc" where id="123"; would be a statement for PATCH. "UPDATE STUDENT SET address = "abc", name="newname" where id="123" would be a correct analogy for PUT

2018年10月23日12分46秒

Put could also be used for INSERT. For example if you server detected you were trying to upload the same file multiple times, it would make your request idempotent. (No new file uploads are done).

2018年10月23日12分46秒

No, PUT implies that you know the URL. If you only know the ID then POST with that ID to get the URL.

2018年10月23日12分46秒

The id is part of the URL, so yes, use PUT if you know the URL (which includes the id).

2018年10月23日12分46秒

No, the URL is determined by the server and the ID is not necessarily part of the URL. Roy Fielding would tell you the same or you could just read his thesis.

2018年10月23日12分46秒

Joshcodes, is that assuming REST? In a RESTful architecture, the item id is most definitely part of the URL, as in: /people/123. I like this site for REST: microformats.org/wiki/rest/urls

2018年10月23日12分46秒

Beez the mircoformats link suggests a good way for servers to structure their URLs but the server determines the URL. The client next-to-never does. See my answer or associated article if you don't understand this.

2018年10月23日12分46秒

But how can you use PUT to create a new resource if it doesn't exist, while your ID generation method is on Auto Increment ? Usually ORM's does auto generate the ID for you, like the way you want it to be in a POST for example. Does it mean that if you want to implement PUT the right way you have to change your id auto generation ? This is awkward if the answer is yes.

2018年10月23日12分46秒

Really interesting, didn't see this blog post until now! Thanks for the link!

2018年10月23日12分46秒

Your short answer might be VERY wrong. HTTP PUT is free to be repeated by HTTP proxies. And so, if PUT is actually doing SQL INSERT it might fail second time, which means it would return different result and so it would not be IDEMPOTENT (which is the difference between PUT and POST)

2018年10月23日12分46秒

I'm a bit late to this - but someone saying something similar on another website got it to click for me. If you're creating a resource and using an auto-incremented ID as it's "identifier" instead of a user assigned name, it should be a POST.

1970年01月01日00分03秒

This isn't quite right - PUT can still create a resource by referring to it with a non-canonical name, as long as in the response, the server returns a Location header that does contain the canonical resource name.

2018年10月23日12分46秒

Joshcodes don't forget that you can have many URIs referencing the same underlying resource. So what Ether said is sound advice, the client can PUT to a URL (that might be more semantic, like PUT /X-files/series/4/episodes/max) and the server respond with a URI that provides a short canonical unique link to that new resource (ie /X-Ffiles/episodes/91)

2018年10月23日12分46秒

thecoshman the issue is the concern for the URL structure does not belong to the client. Reading about self-discovery (also part of REST) may help make this clear.

2018年10月23日12分46秒

Joshcodes then by that logic, a client should never use PUT to create as they shouldn't be concerned with with providing the URL. Well... unless the server provided a URL to PUT to if the client wants to put to it... something like "PUT /comments/new" and the server might respond "204 /comments/234532" but that seems a bit RPC to me, the client should just POST to /comments...

2018年10月23日12分46秒

This is incorrect. For POST, the state is also undefined only until the first successful retry. Then, either the server accepts the POST (message never arrived), throws a 409 conflict for a duplicate ID (message arrived, response was lost), or any other valid response.

2018年10月23日12分46秒

In general a useragent would not able to safely retry the POST operation since the POST operation gives no that guarantee that two operations would have the same effect as one. The term "ID" has nothing to do with HTTP. The URI identifies the resource.

2018年10月23日12分46秒

A useragent can "safely" retry a POST operation as many times as it wants. It will just receive a duplicate ID error (assuming the resource has an ID) or a duplicate data error (assuming that's an issue and the resource does not have IDs).

2018年10月23日12分46秒

Bangs head against wall. HTTP has no solution to the problem of reliability, and this is not well understood, not much discussed, and simply not catered for in the vast majority of web applications. Joshcodes I have an answer to this question. I essentially agree with Hans. There's a problem.

2018年10月23日12分46秒

bbsimonbb, HTTP has a robust and well documented set of error responses. My answer to this question (stackoverflow.com/questions/630453/put-vs-post-in-rest/…) covers how to use http according to specification to achieve consistency.

2018年10月23日12分46秒

If the comment is an object with property like user id, created date, comment-message, etc. and at the time of edit only comment-message is getting updated, PATCH should be done here?

2018年10月23日12分46秒

PUT is used by FB to update the comment because an existing resource is being updated, and that is what PUT does (updates a resource). PUT happens to be idempotent, in contrast to POST. An HTTP verb being idempotent affects the error handling but does not dictate usage. See my answer for a more detail explanation: stackoverflow.com/questions/630453/put-vs-post-in-rest/…

2018年10月23日12分46秒

Update => HTTP POST : POST is not for updating

2018年10月23日12分46秒

I think you've managed to provide one of the few good examples of how to use PUT, well done.

2018年10月23日12分46秒

Wont storing response be like maintaining a session? Which would cause (horizontal) scaling issues.

2018年10月23日12分46秒

What you describe POST as is actually how PATCH should behave. POST is supposed to mean something more akin to "append" as in "post to mailing list".

2018年10月23日12分46秒

For the most part, from reading through all this noise, you seem on the ball. I would say though, we should refer to PUT as the replace method, rather than the create/update. I think it better describes in one what it does.

2018年10月23日12分46秒

PUT is not for update, it is for replace, note that to create you are replacing nothing with something. POST is absolutely not for update in any shape of form.

2018年10月23日12分46秒

Does the http spec say that? Or are you basing your comment on something else?

2018年10月23日12分46秒

It's just common sense, how you update something when you don't know what it is you are updating? POST is for creating a new resource.

2018年10月23日12分46秒

thecoshman -- you are abusing semantics here -- a replace can be an update if it is the same resource with a few differences. A replace is only valid for put if replace is used to change the same resource. Replacing with a new and different resource is invalid (remove old and add new?), especially if the 'new' resource doesn't have a natural ID. POST, OTOH, is something that can create, update, replace, and delete -- using post depends on whether or not there is a message to interpret, such as 'apply the discount', which may or may not change the resource depending on logic.

2018年10月23日12分46秒

As for your second comment -- how about you 'get' the resource, modify the fields you need to, and then put it back? Or how about if the resource comes from a different source but uses a natural ID (the external ID) -- put would naturally update the resource at the URL when the original data changed.

2018年10月23日12分46秒

PUT is not for update, it is for replace, note that to create you are replacing nothing with something. POST is absolutely not for update in any shape of form.

2018年10月23日12分46秒

Its good differences are given here restfulapi.net/rest-put-vs-post

2018年10月23日12分46秒