45

In this article the author claims that

Sometimes, it is required to expose an operation in the API that inherently is non RESTful.

and that

If an API has too many actions, then that’s an indication that either it was designed with an RPC viewpoint rather than using RESTful principles, or that the API in question is naturally a better fit for an RPC type model.

This reflects what I have read and heard elsewhere as well.

However I find this quite confusing and I would like to get a better understanding of the matter.

Example I: Shutting down a VM through a REST interface

There are, I think, two fundamentally different ways to model a shutdown of a VM. Each way might have a few variations, but let's concentrate on the most fundamental differences for now.

1. Patch the resource's state property

PATCH /api/virtualmachines/42
Content-Type:application/json  

{ "state": "shutting down" }

(Alternatively, PUT on the sub-resource /api/virtualmachines/42/state.)

The VM will be shutting down in the background and at some later point in time depending of wether shutting down will succeed or not the state might be internally updated with "power off".

2. PUT or POST on the resource's actions property

PUT /api/virtualmachines/42/actions
Content-Type:application/json  

{ "type": "shutdown" }

The result is exactly the same as in the first example. The state will be updated to "shutting down" immediately and maybe eventually to "power off".

Are both designs RESTful?

Which design is better?

Example II: CQRS

What if we have a CQRS domain with many such "actions" (aka commands) that might potentially lead to updates of multiple aggregates or cannot be mapped to CRUD operations on concrete resources and sub-resources?

Should we try to model as many commands as concrete creates or updates on concrete resources, where ever possible (following the first approach from example I) and use "action endpoints" for the rest?

Or should we map all the commands to action endpoints (as in the second approach of example I)?

Where should we draw the line? When does the design become less RESTful?

Is a CQRS model a better fit for an RPC like API?

According to the quoted text above it is, as I understand it.

As you can see from my many questions, I am a little bit confused about this topic. Can you help me to get a better understanding of it?

leifbattermann
  • 736
  • 1
  • 5
  • 9
  • "creating an action" does not seem RESTful, except if the executed action has its own resource identifier afterwards. Otherwise changing the "state" property via PATCH or PUT makes more sense. For the CQRS part, I don't have a good answer yet. – Fabian Schmengler Dec 22 '16 at 12:05
  • 3
    @Laiv Nothing wrong with that. It's an academical question, I'd like to get a deeper understanding of the matter. – leifbattermann Dec 22 '16 at 14:10

5 Answers5

33

In the first case (shut-down of VMs), I'd consider none of the OP alternatives RESTful. Granted, if you use the Richardson maturity model as a yardstick, they are both leve 2 APIs because they use resources and verbs.

Neither of them, though, use hypermedia controls, and in my opinion, that's the only type of REST that differentiates RESTful API design from RPC. In other words, stick with level 1 and 2, and you're going to have an RPC-style API in most cases.

In order to model two different ways of shutting down a VM, I'd expose the VM itself as a resource that (among other things) contains links:

{
    "links": [{
        "rel": "shut-down",
        "href": "/vms/1234/fdaIX"
    }, {
        "rel": "power-off",
        "href": "/vms/1234/CHTY91"
    }],
    "name": "Ploeh",
    "started": "2016-08-21T12:34:23Z"
}

If a client wishes to shut down the Ploeh VM, it ought to follow the link with the shut-down relationship type. (Normally, as outlined in the RESTful Web Services Cookbook, you'd use an IRI or more elaborate identification scheme for relationship types, but I chose to keep the example as simple as possible.)

In this case, there's little other information to provide with the action, so the client should simple make an empty POST against the URL in the href:

POST /vms/1234/fdaIX HTTP/1.1

(Since this request has no body, it'd be tempting to model this as a GET request, but GET requests should have no observable side-effects, so POST is more correct.)

Likewise, if a client wants to power off the VM, it'll follow the power-off link instead.

In other words, the relationship types of the links provide affordances that indicate intent. Each relationship type has a specific semantic significance. This is the reason we sometimes talk about the semantic web.

In order to keep the example as clear as possible, I intentionally obscured the URLs in each link. When the hosting server receives the incoming request, it'd know that fdaIX means shut down, and CHTY91 means power off.

Normally, I'd just encode the action in the URL itself, so that the URLs would be /vms/1234/shut-down and /vms/1234/power-off, but when teaching, that blurs the distinction between relationship types (semantics) and URLs (implementation details).

Depending on which clients you have, you may consider making RESTful URLs non-hackable.

CQRS

When it comes to CQRS, one of the few things that Greg Young and Udi Dahan agrees about is that CQRS isn't a top-level architecture. Thus, I'd be cautious about making a RESTful API too CQRS-like, because that'd mean that clients become part of your architecture.

Often, the driving force behind a real (level 3) RESTful API is that you want to be able to evolve your API without breaking clients, and without having control of clients. If that's your motivation, then CQRS wouldn't be my first choice.

Mark Seemann
  • 3,860
  • 23
  • 27
  • Do you mean that the first examples are both not RESTful because they don't use hypermedia controls? But I didn't even post any responses, only the request URLs and bodies. – leifbattermann Dec 22 '16 at 12:52
  • 5
    @leifbattermann They're not RESTful because they use the message body to communicate intent; that's clearly RPC. If you used links to arrive at those resources, then why would you need to communicate intent through the body? – Mark Seemann Dec 22 '16 at 13:25
  • That makes sense. Why do you suggest a POST? Isn't the action idempotent? In any case, how do you tell your client which HTTP method to use? – leifbattermann Dec 22 '16 at 14:01
  • @leifbattermann I suppose in this (degenerate) case you could also use PUT... – Mark Seemann Dec 22 '16 at 14:03
  • So this: https://www.infoq.com/articles/rest-api-on-cqrs according to your answer is not a good design because it exposes the CQRS as a top level architecture, correct? Additionally no hypermedia controls, so at most it's REST level 2. The command type is specified via the content type header. This seems odd to me. What's your opinion? – leifbattermann Dec 22 '16 at 14:05
  • `DELETE` seems to me like a more appropriate, idempotent verb to shut down a VM – guillaume31 Dec 22 '16 at 14:05
  • 2
    @guillaume31 `DELETE` seems strange to me because after shutting down the vm will still exist, only in state "power off" (or sth. like that). – leifbattermann Dec 22 '16 at 14:07
  • 1
    The resource doesn't have to reflect an VM atemporally, it can represent an execution instance of it. – guillaume31 Dec 22 '16 at 14:09
  • @guillaume31 I see, yes, that's true. Anyway shutting down might fail and then you should be able to power off, as well. – leifbattermann Dec 22 '16 at 14:13
  • Well, shutting down and powering off result in the same terminal state, right? Why not use the same verb for both? The media type could distinguish between the two. – guillaume31 Dec 22 '16 at 14:19
  • @guillaume31 Do you mean to specify it in the content-type header? – leifbattermann Dec 22 '16 at 14:33
  • Yes, I'll add an answer to be more specific – guillaume31 Dec 22 '16 at 14:34
  • This answer sort of implies that URLs are links to follow to carry out an action (if you want to shut down the service follow this URL, if you want to power off the service follow this URL). That isn't RESTful. URLs represent resources, not actions to carry out on resources. The actions are defined in the HTTP spec – Cormac Mulhall Dec 23 '16 at 16:29
  • Mark, you said: ‘They're not RESTful because they use the message body to communicate intent; that's clearly RPC. If you used links to arrive at those resources, then why would you need to communicate intent through the body?’ Do you mean that resources should follow the *single responsibility principle* in programming, i.e. one resource = one intent? – Géry Ogam May 16 '21 at 23:13
  • 1
    @Maggyero You can subject resources to different actions via HTTP verbs. The intent behind a `GET` request is (hopefully) distinct from the intent behind a `DELETE` request. Usually, in REST, that's sufficient to distinguish between intent. The OP is a little special because it asks how to distinguish between two kinds of intent that don't easily map to two distinct HTTP verbs, which is why it's necessary to model the two distinct intents as two distinguishable resources. The [RESTful Web Services Cookbook](http://amzn.to/YFnkRg) calls these *Controller resources*. – Mark Seemann May 17 '21 at 05:40
  • ‘*Controller resources*’ I really like that name as it makes it explicit that instead of the client controlling resources’ states with the CRUD HTTP methods `GET` (read), `PUT` (create and update) and `DELETE` (delete)—direct control—, the client *delegates* the control of resources’ states to a controller resource with the HTTP method `POST`—indirect control. In other words, low-level state management is replaced with high-level state management, i.e. the abstraction level is raised. Alan Kay [wrote on this topic](https://stackoverflow.com/a/65150628/2326961). – Géry Ogam May 17 '21 at 13:01
  • What hypermedia format do you suggest? Mike Kelly’s [JSON Hypertext Application Language](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-08)? Mark Nottingham’s [HTTP Link Hints](https://datatracker.ietf.org/doc/html/draft-nottingham-link-hint-02)? And how do we assign semantics to link types for a Web application? – Géry Ogam May 17 '21 at 15:50
  • 1
    @Maggyero By default, I use `href` and `rel` as originally defined by ATOM. Again, I just went with [Subbu Allamaraju's recommendations](http://amzn.to/YFnkRg). Here's an example: https://blog.ploeh.dk/2020/10/26/fit-urls – Mark Seemann May 17 '21 at 17:03
  • Thanks for the recommendation and the informative article. I have just realized that Mark Nottingham published [RFC 8288: Web Linking](https://datatracker.ietf.org/doc/html/rfc8288) which generalizes [RFC 4287: Atom](https://datatracker.ietf.org/doc/html/rfc4287) and [HTML](https://html.spec.whatwg.org) linking to any formats. – Géry Ogam May 17 '21 at 22:45
  • Mark, what do you think of [Cormac Mulhall](https://softwareengineering.stackexchange.com/a/338785/184279)’s answer? I disagree with it and gave my thoughts in comments, but I would like to have your point of view as I feel it is a fundamental aspect to understand. – Géry Ogam Jun 11 '21 at 09:49
  • @Maggyero I must admit that re-reading this entire page confuses me. I remember the question as different from what's there, but no edit history is visible. It may be my memory that fails me, but based on what's on display, I find my own answer incongruent with the question... I'm not sure it's helpful to keep barking up this tree. – Mark Seemann Jun 11 '21 at 12:03
11

Shutting down a VM through a REST interface

This is actually a somewhat famous example, put forth by Tim Bray in 2009.

Roy Fielding, discussing the problem, shared this observation:

I personally prefer systems that treat monitored state (like power status) as non-editable.

In short, you have one information resource that returns a current representation of the monitored state; that representation might include a hypermedia link to a form that to request a change to that state, and the form has another link to a resource to handle (each) change request.

Seth Ladd had the key insights in the problem

We've turned Running from a simple state of a person to a true Noun which can be created, updated, and talked about.

Taking this back to rebooting machines. I would argue that you would POST to /vdc/434/cluster/4894/server/4343/reboots Once you've posted, you have a URI which represents this reboot, and you can GET it for status updates. Through the magic of hyperlinking, the representation of the Reboot is linked to the Server that is rebooted.

I think minting URI space is cheap, and URI's are even cheaper. Create a collection of activities, modeled as Nouns, and POST, PUT, and DELETE away!

RESTful programming is Vogon bureaucracy at web scale. How do you do anything RESTful? Invent new paperwork for it, and digitize the paperwork.

In somewhat fancier language, what you are doing is defining the domain application protocol for "shut down a VM", and identifying the resources that you need to expose/implement that protocol

Looking at your own examples

PATCH /api/virtualmachines/42
Content-Type:application/json  

{ "state": "shutting down" }

That's OK; you aren't really treating the request itself as its own separate information resource, but you could still manage.

You've missed a little bit in your representation of the change.

With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version.

For example, the JSON Patch media type formats instructions as though you were directly modifying a JSON document

[
    { "op": "replace", "path": "state", "value": "shutting down" }
]

In your alternative, the idea is close, but not obviously correct. PUT is a complete replacement of the state of the resource at the target URL, so you probably wouldn't choose a spelling that looks like a collection as the target of a representation of a single entity.

POST /api/virtualmachines/42/actions

Is consistent with the fiction that we are appending an action to a queue

PUT /api/virtualmachines/42/latestAction

Is consistent with the fiction that we are making an update to the tail item in the queue; it's a bit weird to do it this way. Principle of least surprise recommends giving each PUT it's own unique identifier, rather than putting them all to one place and modifying multiple resources at the same time.

Note that, in so far as we are discussing the spelling of URI -- REST doesn't care; /cc719e3a-c772-48ee-b0e6-09b4e7abbf8b is a perfectly cromulent URI as far as REST is concerned. Readability, as with variable names, is a separate concern. Using spellings that are consistent with RFC 3986 will make people a lot happier.

CQRS

What if we have a CQRS domain with many such "actions" (aka commands) that might potentially lead to updates of multiple aggregates or cannot be mapped to CRUD operations on concrete resources and sub-resources?

Greg Young on CQRS

CQRS is a very simple pattern that enables many opportunities for architecture that may otherwise not exist. CQRS is not eventual consistency, it is not eventing, it is not messaging, it is not having separated models for reading and writing, nor is it using event sourcing.

When most people talk about CQRS they are really speaking about applying the CQRS pattern to the object that represents the service boundary of the application.

Given that you are talking about CQRS in the context of HTTP/REST, it seems reasonable to assume you are working in this latter context, so let's go with that.

This one, surprisingly, is even easier than your previous example. The reason for this is simple: commands are messages.

Jim Webber describes HTTP as the application protocol of a 1950s office; work gets done by taking messages and putting them into inboxes. Same idea holds - we get a blank copy of a form, fill it out with the specifics that we know, deliver it. Ta da

Should we try to model as many commands as concrete creates or updates on concrete resources, where ever possible (following the first approach from example I) and use "action endpoints" for the rest?

Yes, insofar as the "concrete resources" are messages, rather than entities in the domain model.

Key idea: your REST API is still an interface; you should be able to change the underlying model without clients needing to change the messages. When you release a new model, you release a new version of your web endpoints that know how to take your domain protocol and apply it to the new model.

Is a CQRS model a better fit for an RPC like API?

Not really -- in particular, web caches are a great example of an "eventually consistent read model". Making each of your views independently addressable, each with their own caching rules, gives you a bunch of scaling for free. There's relatively little appeal to an exclusively RPC approach to reads.

For writes, it's a tricker question: sending all commands to a single handler at a single endpoint, or a single family of endpoints, is certainly easier. REST is really more about how you find communicate where the endpoint is to the client.

Treating a message as its own unique resource has the advantage that you can use PUT, alerting the intermediary components to the fact that the handling of the message is idempotent, so that they can participate in certain cases of error handling, is a nice to have. (Note: that from the point of view of the clients, if the resources have different URI, then they are different resources; the fact that they may all have the same request handler code on the origin server is an implementation detail hidden by the uniform interface).

Fielding (2008)

I should also note that the above is not yet fully RESTful, at least how I use the term. All I have done is described the service interfaces, which is no more than any RPC. In order to make it RESTful, I would need to add hypertext to introduce and define the service, describe how to perform the mapping using forms and/or link templates, and provide code to combine the visualizations in useful ways.

VoiceOfUnreason
  • 32,131
  • 2
  • 42
  • 79
2

The example in the linked article is predicated on the idea that starting the machine and shutting it down have to be directed by commands instead of by changes in the state of modeled resources. The latter is pretty much what REST lives and breathes. Better modeling of the VM requires a look at how its real-world counterpart works and how you, as a human, would interact with it. This is long-winded, but I think it gives good insight into the type of thinking required to do good modeling.

There are two ways to control the power state of the computer on my desk:

  • Power Switch: Immediately cuts the flow of electricity to the power supply, bringing the entire computer to a sudden, disorderly halt.
  • On/Off Button: Tells the hardware to notify the software that something on the outside wants everything shut down. The software does an orderly shutdown, notifies the hardware that it's done and the hardware signals the power supply that it can go into its standby state. If the power switch is on, the machine is running and the software is in a state where it can't respond to the shutdown signal, the system won't shut down unless I turn off the power switch. (A VM will behave in exactly the same way; if the shutdown signal is ignored by the software, the machine will continue running I have to force it to power off.) If I want to be able to restart the machine, I have to turn the power switch back on and then press the on/off button. (Many computers have the option of using a long press of the power button to go directly to the standby state, but this model doesn't really need that.) This button can be treated like a toggle switch because pressing it results in different behavior depending on the state when it's pressed. If the power switch is off, pressing this button does absolutely nothing.

For a VM, both of these can be modeled as read/write Boolean values:

  • power - When changed to true, nothing happens other than a note being made that the switch has been placed into this state. When changed to false, the VM is commanded into an immediate power-off state. For the sake of completeness, if the value is unchanged after a write, nothing happens.

  • onoff - When changed to true, nothing happens if power is false, otherwise the VM is commanded to start. When changed to false, nothing happens if power is false, otherwise, the VM is commanded to notify the software to do an orderly shutdown, which it will do and then notify the VM that it can go into the power-off state. Again, for completeness, a no-change write does nothing.

With all of this comes the realization that there's one situation when the state of the machine doesn't reflect the state of the switches, and that's during shutdown. power will still be true and onoff will be false, but the processor is still running its shutdown, and for that we need to add another resource so we can tell what the machine is actually doing:

  • running - A read-only value that's true when the VM is running and false when it isn't, determined by asking the hypervisor for its state.

The upshot of this is that if you want a VM to start up, you have to make sure the power and onoff resources have been set true. (You could allow the power step to be skipped by making it self-resetting, so that if set to false, it becomes true after the VM has been verifiably hard-stopped. Whether that's a RESTfully-pure thing to do is fodder for another discussion.) If you want it to do an orderly shutdown, you set onoff to false and come back later to see if the machine actually stopped, setting power to false if it didn't.

Like the real world, you still have the problem of being directed to start the VM after it's had onoff changed to false but is still running because it's in the middle of shutdown. How you deal with that is a policy decision.

Blrfl
  • 20,235
  • 2
  • 49
  • 75
2

You could leverage 5 levels of media type to specify the command in the content-type header field of the request.

In the VM example, it would be something along these lines

PUT /api/virtualmachines/42
Content-Type:application/json;domain-model=PowerOnVm

> HTTP/1.1 201 Created
Location: /api/virtualmachines/42/instance

Then

DELETE /api/virtualmachines/42/instance
Content-Type:application/json;domain-model=ShutDownVm

Or

DELETE /api/virtualmachines/42/instance
Content-Type:application/json;domain-model=PowerOffVm

See https://www.infoq.com/articles/rest-api-on-cqrs

guillaume31
  • 8,358
  • 22
  • 33
  • Be advised, 5LMT was a proposed solution and is not supported by [standards](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type). I came across [the CQRS](https://www.infoq.com/articles/rest-api-on-cqrs) article before and learned much from it. – Peter L Jul 14 '19 at 16:07
2

Are both designs RESTful?

So if you want to think restfully then forget about commands. The client doesn't tell the server to shut down the VM. The client "shuts dow" (metaphorically speaking) their copy of the resource representation by updating its state and then PUTs that representation back on the server. The server accepts that new state representation and as a side-effect of this, actually shuts down the VM. The side-effect aspect is left up to the server.

It is less of

Hey server, client here, would you mind shutting down the VM

and more of

Hey server, client here, I updated the state of resource VM 42 into the shutdown state, update your copy of this resource and then do what ever you think is appropriate

As a side effect of the server accepting this new state it can check what actions it has to actually perform (such as physically shutting down VM 42), but this is transparent to the client. The client is unconcerned with any actions the server has to take to become consistent with this new state

So forget about commands. The only commands are the verbs in HTTP for state transfer. The client doesn't know, nor does it care, how the server is going to get the physical VM into the state of shut down. The client isn't issuing commands to the server to achieve this, it is just saying This is the new state, figure it out.

The power of this is that it decouples the client from the server in terms of flow control. If later the server changes how it works with VMs, the client doesn't care. There are no command endpoints to update. In RPC if you change the API end point from shutdown to shut-down you have broken all your clients as they now don't know the command to call on the server.

REST is similar to declarative programming, where instead of listing a set of instructions to change something you instead just state how you want it to be and let the programming environment figure it.

Cormac Mulhall
  • 5,032
  • 2
  • 19
  • 19
  • Thx for your answer. The second part about decoupling client and server very much aligns with my own understanding. Do you have a resource/link that backs up the first part of your answer? Exactly what REST constraint is broken if I use resources, HTTP methods, hypermedia, self-descriptive messages, etc.? – leifbattermann Jan 05 '17 at 08:54
  • There is no issue with using resources, HTTP methods etc. HTTP is a RESTful protocol after all. Where there becomes an issue is using what you term "action endpoints". In REST there are resources, which represent concepts or things (such as virtual machine 42, or my bank account) and the HTTP verbs uses to transfer the state of these resources between clients and servers. That is it. What you shouldn't do is try and create new commands by combining non-resource endpoints with HTTP verbs. So 'virtualmachines/42/actions' isn't a resource and shouldn't exist in a RESTful system. – Cormac Mulhall Jan 05 '17 at 09:31
  • Or to put it another way, the client shouldn't be trying to run commands on the server (beyond the limited HTTP verbs concerned solely with state transfer of resources). The client should be updating its copy of the resource and then simply asking the server to accept this new state. The acceptance of this new state can have side effects (the VM 42 is physically shut down) but that is beyond the concern of the client. If the client isn't trying to run commands on the server then there is no coupling via those commands between the client and the server. – Cormac Mulhall Jan 05 '17 at 09:41
  • You can run the command on the resource... How would you do let's say "deposit" and "withdraw" on a bank account? It would be using CRUD for something that's not CRUD. – Konrad Aug 28 '18 at 07:13
  • 1
    It's better to use `POST /api/virtualmachines/42/shutdown` instead of having any "side effect". The API must be understandable to the user, how will I know that for example `DELETE /api/virtualmachines/42` will shut the VM down? A side effect to me is a bug, we should design our APIs to be understandable and self-descriptive – Konrad Aug 28 '18 at 07:19
  • REST is an architectural style that many people get wrong and it became more like a buzzword. Take a look at [Richardson Maturity Level](https://martinfowler.com/articles/richardsonMaturityModel.html) – Konrad Aug 28 '18 at 07:25
  • 1
    That is just remote procedure masquerading as REST/HTTP. If you are dead set on RPC you are better off just using a RPC protocol. The URL scheme is not "the API". The URL scheme says where the resources are. `/api/virtualmachine/42/shutdown` is not a resource. The state transfer way of doing this is to have a resource representation of Virtual Machine 42 that the client updates the state to "shutdown" and sends that state via a PUT to the server. The server then says "oh the state of the virtual machine should now be shutdown, let me do that". The client doesn't worry about *how* it does this – Cormac Mulhall Aug 29 '18 at 08:08
  • The only thing the client and the server need to share is a common knowledge of the data format of the state representation (ie what is the format of the document representing the state of Virtual Machine 42). It could be just a simple JSON format but the client and the server need to understand it. After that they don't need to know anything else, the client certainly doesn't need to know that the command to shut down the server is at this particular URL or how the server gets the virtual machine into the correct state based on an updated state representation. – Cormac Mulhall Aug 29 '18 at 08:11
  • REST is not for every problem, but if you really don't want to use REST as it is designed a better solution is to just not use REST/HTTP. Use something else that is actually designed for Remote Procedure Calls. Making HTTP RPC-like is far more confusing than any confusion over state representations. – Cormac Mulhall Aug 29 '18 at 08:12
  • 1
    Taking the bank account example, the client doesn't tell the server to "deposit" or "withdraw". The client updates the balance of the account (essentially doing a withdraw or a deposit itself) and then sends the new state to the server. The server either accepts this new state or rejects it. This is actually a good example of the advantages of REST. The client does not need to know that "deposit" is the command to add money and "withdraw" is the command to delete money. It just changes the amount of the bank account to what it wants and sends that new state to the server. – Cormac Mulhall Aug 29 '18 at 09:50
  • ‘So if you want to think restfully then forget about commands.’ You seem to advocate PUTting an *output* state (intended state) over POSTing an *input* value. However in his thesis, Fielding states that both are RESTful, [§ 5.2.1.2](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2_1_2): – Géry Ogam Jun 11 '21 at 09:36
  • ‘Depending on the message control data, a given representation may indicate the current state of the requested resource, the desired state for the requested resource, *or the value of some other resource, such as a representation of the input data within a client's query form, or a representation of some error condition for a response.*’ – Géry Ogam Jun 11 '21 at 09:36
  • Sometimes you do not know the output state of a resource, so you cannot transfer it to the resource. E.g. for a registration resource storing your email and a hash of your password given in input (a password should never be stored in clear), you cannot PUT your email and the hash of your password (output state) because it is not your responsibility to hash the password; instead you POST the email and the password (input value) and the server hashes the password. So as Roy Fielding said, [it is okay to use POST](https://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post): – Géry Ogam Jun 11 '21 at 09:36
  • ‘I think the anti-POST meme got started because of all the arguments against tunneling other protocols via HTTP’s POST (e.g., SOAP, RSS, IPP, etc.). Somewhere along the line people started equating the REST arguments of “don’t violate HTTP’s method definitions” and “always use GET for retrieval because that forces the resource to have a URI” with the paper tiger of “POST is bad.” Please, let’s move on. We don’t need to use PUT for every state change in HTTP. REST has never said that we should.’ – Géry Ogam Jun 11 '21 at 09:37
  • In other words, REST is not about using CRUD operations, which is still RPC. [REST is about using hypertext](https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven), as explained in [Mark Seemann’s answer](https://softwareengineering.stackexchange.com/a/338669/184279). – Géry Ogam Jun 11 '21 at 09:37
  • Yes REST is not about crud, that is the point. REST is about state transfer, it is in the name. Having an "actions" resource that you POST commands to in order to update the state of a different resource is not REST. Sure you can POST the state change to the actual resource you are changing but why would you bother, just use PUT. A Fielding says "POST only becomes an issue when it is used in a situation for which some other method is ideally suited" – Cormac Mulhall Jun 13 '21 at 23:00
  • 1
    @CormacMulhall ‘Sure you can POST the state change to the actual resource you are changing but why would you bother, just use PUT.’ As I said, you should use PUT for replacing the current state of a *target resource* with a *new state*, because the request can be repeated in case of network failure since PUT is an *idempotent* method. But you should use POST if you don’t know the target resource or the new state. This is what Fielding means when he says: ‘POST only becomes an issue when it is used in a situation for which some other method is ideally suited’. – Géry Ogam Jun 22 '21 at 18:20
  • @CormacMulhall From RFC 7231, [§ 3.3](https://datatracker.ietf.org/doc/html/rfc7231#section-3.3): ‘The purpose of a payload in a request is defined by the method semantics. For example, a representation in the payload of a PUT request (Section 4.3.4) represents the desired state of the target resource if the request is successfully applied, whereas a representation in the payload of a POST request (Section 4.3.3) represents information to be processed by the target resource. In a response, the payload's purpose is defined by both the request method and the response status code. – Géry Ogam Jun 22 '21 at 18:20
  • 1
    @CormacMulhall … For example, the payload of a 200 (OK) response to GET (Section 4.3.1) represents the current state of the target resource, as observed at the time of the message origination date (Section 7.1.1.2), whereas the payload of the same status code in a response to POST might represent either the processing result or the new state of the target resource after applying the processing. Response messages with an error status code usually contain a payload that represents the error condition, such that it describes the error state and what next steps are suggested for resolving it.’ – Géry Ogam Jun 22 '21 at 18:20
  • @Maggyero But you do know the resource, and you know the state. The resource is "virtual machine 42" and the state is "shut down". You don't POST the shutdown command to vm 42 via some janky fake resource `actions` or `shutdown` (see Konrad comment) You PUT the actual resource into a new state (`{state: shutdown}`). – Cormac Mulhall Jul 05 '21 at 10:31
  • If you don't want to send the entire state of the VM on each PUT to the main resource `vm/42` then you can have a child `vm/42/state` resource that you can `PUT` a very simple resource to eg `PUT vm/42/state {state: shutdown}` – Cormac Mulhall Jul 05 '21 at 10:34
  • ‘But you do know the resource, and you know the state.’ Yes in the case of a machine reboot you know the intended state so you could use PUT. But not in general, so you should remove your wrong statement: ‘So if you want to think restfully then forget about commands.’ And even in the case of a machine reboot you should [use POST anyway](https://softwareengineering.stackexchange.com/a/429778/184279) because with PUT the machine reboot will not be the method’s *intended* effect (which is already defined as replacing the target resource’s state) like with POST but the method’s *side* effect. – Géry Ogam Jul 05 '21 at 11:12
  • The methods intended effect is to sync the state of the resource the client has with the state of the resource the server has. That new state is 'shutdown' (or 'rebooted'). The side-effects of that are nothing to do with the client, they are up to the server. The client cares anout what state the resource should be in. How the server gets it into that state is up to the server. That is the power of REST, it decouples the `what` from the `how`. This is why you should forget about commands. – Cormac Mulhall Jul 06 '21 at 14:07
  • The client doesn't care how the server satisfies the transfer of state. The client says "This VM should be in the shutdown state, figure it out" and the server figures it out. The client doesn't issue commands to the server as to how to shutdown the VM. Again forget about commands, think about states. Yes POST is a catch all for basically anything that doesn't fit into state transfer but the idea that you have to use a POST if there are server side effects is completely wrong. The client doesn't care about server side effects if the state transfer is fufilled. – Cormac Mulhall Jul 06 '21 at 14:23
  • Reading the comments in that other question I think the confusion is that you are thinking of the`resource` and the `physical vm` as to different things. The actual VM shutting down because you updated the state of the `resource` representing that VM is not a 'side effect' of the state transfer. Resources represent things (REpresentational State Transfer). If you update the state of the `resource` representing the VM it is totally fine (and expected) that the actual VM shuts down. They are not different actions. – Cormac Mulhall Jul 06 '21 at 14:31
  • Or to put it another way, it doesn't make any sense to say `I intended to update the resouce respresenting VM 42 to the 'shutdown' state but I'm really surprised that this caused VM 42 to shutdown, that was not my intent`. The resource represents the thing, if you change the state of the thing you can expect the resource to change and if you can change the state of the resource you can expect the real thing to update. A `side-effect` is different, it is a change on a *different* resource caused by the change on the original resource. – Cormac Mulhall Jul 06 '21 at 14:40