0

The intended effect (semantics) of the POST method is resource specific, e.g. executing a command with arguments:

POST /command HTTP/1.1

{"parameter-1": "argument-1", "parameter-2": "argument-2"}

The intended effect (semantics) of the PUT method is to create or replace the state of the target resource with the state defined by the enclosed representation, but the side effect of the PUT method is resource specific, e.g. executing a command with arguments:

PUT /command HTTP/1.1

{"parameter-1": "argument-1", "parameter-2": "argument-2"}

Cf. RFC 7231, § 4.3.4:

A PUT request applied to the target resource can have side effects on other resources. For example, an article might have a URI for identifying "the current version" (a resource) that is separate from the URIs identifying each particular version (different resources that at one point shared the same state as the current version resource). A successful PUT request on "the current version" URI might therefore create a new version resource in addition to changing the state of the target resource, and might also cause links to be added between the related resources.

So what are the benefits of executing a command as the intended effect of POST versus as the side effect of PUT?

5
  • 1
    If this is essentially, RPC (Remote Procedure Call), I wouldn't use a PUT for this. Semantically speaking, the result of executing an arbitrary command is, well, arbitrary, and is therefore the province of a POST, not a PUT. Commented Jun 28, 2021 at 17:48
  • @RobertHarvey Do you mean that if the state of the /command resource has no purpose (the user is not interested in retrieving it with GET), use POST instead of PUT?
    – Géry Ogam
    Commented Jun 28, 2021 at 18:26
  • 1
    No, that's not what I meant. What I meant was: PUT has a semantic meaning that doesn't encompass arbitrary code execution. POST is the wild-card verb; you can use it for anything you want, including arbitrary code execution. Commented Jun 28, 2021 at 21:54
  • In the first place, A PUT request applied to the target resource. It's not like you are pointing or handling any resource, you are merely executing remote procedures. Don't know if method semantics applies here. I would dare to say that it doesn't matter whether you use POST or PUT. I'm somewhat sure that you are not returning the header "Resource-Location" + 204 Status after POSTing a command. So why you care about semantics?
    – Laiv
    Commented Jun 29, 2021 at 8:00
  • @Laiv I care about semantics because the difference between an intended effect and a side effect is important. For instance if the command is placing an order on an e-commerce website, it is very important that the customer intended that HTTP request effect i.e. be aware for it. You do not want to place an order as a side effect of an HTTP request i.e. without the customer’s consent.
    – Géry Ogam
    Commented Jun 30, 2021 at 0:20

2 Answers 2

1

As you state in the question the difference is intent. A side effect of a PUT should not matter to the caller and they are not responsible for it. The intended effect of a POST is what the caller is doing and is their responsibility. If you control both the client and server, you are pretty free to do what you like but I don't see any good reason to break convention.

However, if your intended effect (not side-effect) is idempotent, PUT can be used (RFC7231 section 4.2.2)

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

55
  • 1
    @Maggyero For example, let's say I ran a web server for home automation, I could have a resource for a garage door. When you put it's state to close, it closes (or stays closed), that's the intended effect and this would be a valid use of PUT. If I have one for my fish feeder, calling it repeatedly would dump more food in the tank and probably kill the fish. PUT would not be appropriate for that.
    – JimmyJames
    Commented Jun 28, 2021 at 17:55
  • 2
    @Maggyero Closing the door (if it's open) is part of the intended effect i.e. when I call it, I intend to make the door close if it is open. A non-idempotent side effect would be something like the state of the electric meter changed to reflect the energy used. Closing the door multiple times results in the same state for the door but not for the meter. It's a 'side effect' because the services intent is to modify the door state, not to change the meter reading. PUT calls are allowed to have non-idempotent side effects but not non-idempotent intended effects.
    – JimmyJames
    Commented Jun 28, 2021 at 18:27
  • 2
    @Maggyero Placing an order is not a reasonable side effect unless the caller of this operation bears no responsibility for that order. In other words, as a web site operator you can place orders all you want as a side effect of a PUT but you (the web site operator) must pay for them because there was no intention to place them by the user. 'Side effect' means something other than the 'intended effect'. The whole point is you can do basically whatever you want to execute the intended effect but none of those side effects are the user's responsibility.
    – JimmyJames
    Commented Jun 28, 2021 at 19:38
  • 1
    It might help to look at 4.2.1 which is referenced by 4.2.2 "... does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it." That's the point. The user is only accountable for their intended actions and PUT should be designed so that the intended result is the same if you call it once or 100 times.
    – JimmyJames
    Commented Jun 28, 2021 at 19:46
  • 1
    @Maggyero I would say that the RFC specifically calls out examples of 'real world' effects such as "charging an advertising account" that are not 'fully defined' i.e. they aren't defined at all. I don't speak for you but if you are denying that, then yes, I disagree with you on that point.
    – JimmyJames
    Commented Jul 6, 2021 at 21:17
3

If I PUT a resource representation, then the expectation is that a GET of the same resource returns an equivalent representation. For example, if I PUT /command with body print("hello world"), when a later GET /command might get back the command, or the result of executing the command.

A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.

(RFC 7231)

With a POST, there is no expectation of the resource at that URL being created or updated. It is quite common that a POST to an URL creates a different resource (to which a 303 See Other or 201 Created response might redirect). But a POST might not touch upon any resources, and be invoked purely for its side effects.

For example, let's consider a HTTP-based version control system. Each version is identified by an URL like /version/d1623a5. There are also floating labels like /version/latest. How would different designs create a new version?

  • In a PUT-based design, I might directly create a version resource by PUTting a new representation to its URL:

    > PUT /version/c0af447
    >
    > the new content
    
    < 201 Created
    

    As a side effect, this might update the resource that /version/latest points to. Such a PUT is also idempotent. If it fails, I can safely retry it. If the version resource already exists, I would probably get a 204 No Content response.

    Alternatively, I might PUT the latest version:

    > PUT /version/latest
    >
    > the new content
    
    < 204 No Content
    

    As a side effect, this might create the resource /version/c0af447.

  • In a POST-based design, I would not directly POST to the version resources, but to a URL that creates new versions:

    > POST /version/new
    >
    > the new content
    
    < 303 See Other
    < Location: /version/c0af447
    

    This cannot be retried safely: a repeated POST request would typically create another version.

    In practice, using POST is still very popular because it is quite general-purpose, and is less constrained than a PUT. It is a reasonable default for changing “something” on the server.

3
  • PUT /version/latest As a side effect, this might create the resource /version/c0af447.’ So a repeated PUT request would create another version resource, like with POST /version/new.
    – Géry Ogam
    Commented Jun 28, 2021 at 19:42
  • 2
    @Maggyero Not necessarily. PUT is about replacing the representation. If I PUT /version/latest and the representation that I PUT is equivalent to the representation that already is there, the request wouldn't change anything. This is quite different to /version/new which has no current representation.
    – amon
    Commented Jun 28, 2021 at 20:06
  • Interesting, I hadn’t thought of that PUT optimization.
    – Géry Ogam
    Commented Jun 29, 2021 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.