First of all “/toggle” is not a proper REST endpoint. In fact, that is exactly what an RPC endpoint might look like. I can’t believe so many “developers” miss this.
With JSON RPC, he would POST a JSON object to a /toggle endpoint which runs a procedure to open or close his garage door.
If you want to be cute and conform to REST as much as possible, you would have to treat your garage door like a resource, and then use PUT to send the entire new state of the garage door to your API or PATCH to send the instructions for how to change the existing state (or use the +json media type for patch if you want to be lazy and just send a JSON object with updated key values). Your URL would probably be in the form of “/garage-doors/garage-door-id”.
Except, his garage door is probably NOT a resource and has no ID or even a serialized representation of it’s physical state. It’s just a physical door. And it should be driven remote procedures.
Maybe you don’t need any of this. Maybe you are happy with just using GET and pushing everything into REST and basically doing the wrong things. But that’s how you end up with the problems in the article, by not respecting standards, by choosing to be close enough to correct instead of technically correct. And frankly, if there’s any people who should strive for technical precision it should be engineers.
I personally would not hire a single software engineer who chose to approach this problem in the RESTful way without clear and deliberate reasoning for doing so.
Yeah obviously he is doing it wrong, that is the point of the story. GET methods should not have side effects. But wouldn't you have the same problem if you sent a JSON RPC request using GET?
Clearly this is not a REST architecture, they are just using raw HTTP requests as RPC's. I just don't see how the JSON RPC standard would help anything, it just seem like an additional wrapper.
You wouldn't send a JSON RPC request with GET. JSON RPC requires you to send a JSON object in the body describing the method you are calling and the parameters, and the version of JSON RPC you are using. That requires a POST.
You could just have a single /rpc endpoint that takes POST and use that to serve multiple procedures for all sorts of things.
Yeah OK, so JSON RPC avoids this particular problem by simply not supporting GET. But that is kind of throwing the baby out with the bathwater, since GET is quite conventient when used appropriately.
Consider what would happen if he didn't want to merely "toggle" his door, but rather have it closed, definitively and once and for all.
Could he do that with /toggle? Does he know the state of the door well enough to know if toggle is the right command? Can he even trust the state of the door being told to him? What if it's already closed and it opens instead?
No. The only way is to send a message that directly says "Close the Door", with no room for ambiguity on his intent.
JSON RPC excels at this, and in putting the door in whatever state he wants, maybe half way, or 3/4. How would you do this with "convenient" GETs? Use query params? Multiple endpoints? By this point, idempotency is in the rear view mirror and you're well on your way to having a clunky garage door system fraught with bugs and strange edge cases.
I don't really have anything against JSON RPC but it is just a standard for encoding a method name with dynamically typed parameters. You can say "close the door" in JSON RPC, or you can just post the string "close the door" to an URL. It doesn't make the service more robust or reliable to use an extra layer of wrappers.
With JSON RPC, he would POST a JSON object to a /toggle endpoint which runs a procedure to open or close his garage door.
If you want to be cute and conform to REST as much as possible, you would have to treat your garage door like a resource, and then use PUT to send the entire new state of the garage door to your API or PATCH to send the instructions for how to change the existing state (or use the +json media type for patch if you want to be lazy and just send a JSON object with updated key values). Your URL would probably be in the form of “/garage-doors/garage-door-id”.
Except, his garage door is probably NOT a resource and has no ID or even a serialized representation of it’s physical state. It’s just a physical door. And it should be driven remote procedures.
Maybe you don’t need any of this. Maybe you are happy with just using GET and pushing everything into REST and basically doing the wrong things. But that’s how you end up with the problems in the article, by not respecting standards, by choosing to be close enough to correct instead of technically correct. And frankly, if there’s any people who should strive for technical precision it should be engineers.
I personally would not hire a single software engineer who chose to approach this problem in the RESTful way without clear and deliberate reasoning for doing so.