Live data from Hacker News

You know how HTTP GET requests are meant to be idempotent?

twitter.com

231–240 of 313 posts

Re: You know how HTTP GET requests are meant to be idempotent?

#231
post #150

The real problem here, as usual, is web browsers, the worst class of software ever written. We constantly come across these CSRF-style bugs that are only made possible by how stupid the browser and HTTP are, but instead of blaming the culprit and trying to deal with the source, we blame ourselves for not being accommodating enough. Fool me once, shame on me, fool me 5,000 times, shame on me. Oh, and occasionally inve…

Craftsmen should understand the tools they use.

We expect it in every other industry.

Why do people like you always want to suggest that web developers shouldn't have to learn the basics of the tools they use every day? This is page one HTTP stuff.

This is the anti-intellectualism in our field. Where people are so used to finding a YouTube video tutorial for the exact thing they want to do that anything that's inherently hard (like client development) or requires some extra knowledge to do correctly is somehow shitty and needs to be reworked. More and more often it's somehow everything's fault but the craftman's.

It's that mentality that's coasting parts of our field into code monkey cost center positions. Go somewhere like /r/webdev and watch how unresourceful the beginners are and how bad the advice is.

Re: You know how HTTP GET requests are meant to be idempotent?

#232
post #213

Earlier quoted context omitted.

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.

Re: You know how HTTP GET requests are meant to be idempotent?

#233
post #78

Earlier quoted context omitted.

I dispute your example. If you call f(2) and it always returns 4, it's idempotent and side-effect-free. If you call f() and it returns 4, then 8, etc, it is neither.

From wikipedia: "A unary operation f, that is, a map from some set S into itself, is called idempotent if, for all x in S, f(f(x)) = f(x)."

"Idempotent" is one of those overloaded terms...

Re: You know how HTTP GET requests are meant to be idempotent?

#234
post #232

Earlier quoted context omitted.

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.

Re: You know how HTTP GET requests are meant to be idempotent?

#235
post #15

When I recently added 'click to unsubscribe' functionality to my emails, the URL got wrote out into some logs. Those logs got written to a Slack channel and Slack loves to click any link it sees. Oh, and it doesn't respect robots.txt. But all I saw was every member of my list clicking 'unsubscribe'. It took a good hour to figure out exactly what was going on. Idempotence is not the problem here, by the way. That just…

Consider link shortener services...

It's perfectly fine to have certain side-effects, provided the GET is idempotent, but not others/most. Specifically, it's fine to idempotently have side-effects where it doesn't matter who is causing the effect, the side-effects are desirable, and the side-effect load won't be overwhelming.

In the case of a link shortener one can pretend that the side effect did not happen the first time the service sees some particular link, that the shortening has already occurred (at the beginning of time!). There is definitely a side-effect, since it involves updating a persistent hash table, and it is idempotent (though one could construct a shortener where it's possible to get more than one shortened form for a given URI when racing to shorten it, but this is not a problem for this particular sort of service).

Re: You know how HTTP GET requests are meant to be idempotent?

#236

Earlier quoted context omitted.

It's possible to be idempotent without being side-effect free. If you PUT some record, for example, then that operation _will_ have side effects (modifying the record). If you then PUT that same data again, the result will be the same (it's idempotent).

that’s not a side effect. in common usage, a side effect is an extra action, not the desired action itself. if you PUT some record, and some other record or state changes, that’s a side effect.

I suppose logging is a side effect and that makes practically everything technically non-idempotent (though on purpose).

Re: You know how HTTP GET requests are meant to be idempotent?

#237

Earlier quoted context omitted.

Don't make your users jump through hoops to unsubscribe. That seems like a typical dark pattern to me.

Github also does it for their logout button for good reason. Is that a dark evil pattern to keep you logged in to their ecosystem? Or just something someone would say who doesn't understand it?

I trust Github. If it were up to me, I'd remove the logout confirmation from Github but having it there doesn't particularly bother me.

When Facebook does it, I do have a problem with it because I don't think their motives are as pure.

Re: You know how HTTP GET requests are meant to be idempotent?

#238

Earlier quoted context omitted.

The server tells the client about the state through the hypertext documents it sends it. The client then transitions to a new state by performing an action described in that document. Hence: Hypertext/Hypermedia as the engine of application state (HATEOAS). I'm still not grasping why you think the API above needs some kind of universal client though. You can implement a very simple client for that extremely quickly.…

I'm not saying it needs a universal client, just that it's the only real reason I can think of for including all of that. For example, say we are writing a client to do something with Fitbit data. Step one wouldn't be to send a GET to the root to find out what actions are possible, would it? We might find out they have APIs for tracking vehicle mileage but I don't want that in my client - I just want to graph the hou…

> I'm not saying it needs a universal client, just that it's the only real reason I can think of for including all of that.

I already gave several examples of reasons why you would do it this way in my earlier comment.

Why have we leapt from the garage remote example to a FitBit that tracks vehicle mileage? I don't see why you keep leaping to "it must handle everything everywhere". Stop thinking about handling everything under the sun – we're talking about a garage remote.

> If you were going to craft a client UI based entirely off the server responses, you are going to recreate the Gopher experience, and nobody wants that.

REST is a distillation of the principles that make the web work. Can you see the parallels with how HTML forms work? Browsers don't need to know that contact forms need to be POSTed to /contact, the server sends the client a document describing the action to take.

Re: You know how HTTP GET requests are meant to be idempotent?

#239

Earlier quoted context omitted.

A reboot of the machine isn't the end of the world and far less risky than a garage door randomly opening. It probably needed it anyway as they tend to degrade over time. This is a very specific usecase. If it becomes an issue, I can always push out an update of the software that switches things to POST (thanks to using the golang library, overseer).

It still seems a bit odd to do it this way when it's so easy to do it right. I hope the hostnames / IP addresses aren't predictable, because all it would take to cause trouble is to send an HTML email containing something like " rel="nofollow">http://192.168.0.1/reboot"> to your staff and then you'd trigger a bunch of reboots whenever anybody opened their email. Or just send a link to a page that does the same thing.…

I feel like the 'do it right' comment is a bit speculative or entitled. It does create a usability barrier that I was trying to avoid. Even the extra button click is a pain in the ass when you're rebooting dozens of machines (sometimes daily).

Your second paragraph is spot on. Very good point and kind of why I posted here in the first place. Two minds are always better than one. I forgot about the image attack. I've seen this used in the past to 'win' contests by sending in votes over GET.

Luckily my IP's are pretty hard to guess, not a standard range, but you're right... that is a totally valid 'attack' vector. I'll make the change asap.

Re: You know how HTTP GET requests are meant to be idempotent?

#240
post #90

To me this sounds like a CSRF problem. There's no token or session associated with these calls, so a browser was able to inadvertently CSRF the calls. Changing this call to POST or PUT would still leave this API vulnerable.

It's not about access control, it's about the fact that browsers are free to make speculative GET requests whenever they like, and they actively do to pre-fetch pages. His GET end-point was pre-fetched by his browser, activating the door. This would still happen even if there was a token or session associated.

> This would still happen even if there was a token or session associated.

This is exactly the scenario a CSRF token is support to prevent. But I understand your point.

Post reply on HN