Hacker News new | comments | ask | show | jobs | submit login

> Just make sure you apply the data-no-instant tag to your logout link, otherwise it'll logout on mouseover.

Logout links should never be GETs in the first place - they change states and should be POSTs.

POSTs are not Links. And Logout service is indempotent even if you can consider it changes the state of the system

Lots of people in this thread confusing “idempotent” with “safe” as specified in the HTTP RFC: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

FWIW RFC 2616 was obsoleted by the newer HTTP/1.1 RFCs: https://tools.ietf.org/html/rfc7231#section-4.2

Which still doesn't change GP's point though:

> In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe".

(there's an exception listed too, but doesn't apply to logout)

EDIT: I know of someone who made a backup of their wiki by simply doing a crawl - only to find out later that "delete this page" was implemented as links, and that the confirmation dialog only triggered if you had JS enabled. It was fun restoring the system.

I don't know why you think I'm contradicting them. I was just pointing out that there are newer RFCs. They also happen to have a stronger and more complete definition of safe methods.

Ok, so make it a form/button styled to look like a link.

Idempotency is not the issue, the issue is that a user might hover over the logout link, not click it, then move on to the rest of the site and find they are logged out for no reason.

Right, which is why the included library includes an HTML attribute to disable prefetch on a given link.

OP’s point was that logout should not be implemented with a link/GET but instead with a button/POST for exactly this reason.

A logout action is idempotent, though. You can't get logged out twice. In my opinion, that's the use case for a GET request.

I just checked NewRelic, Twilio, Stripe and GitHub. The first 3 logged out with a GET request and GitHub used a POST.

Idempotency has nothing to do with it. Deleting a resource is idempotent as well. You wouldn't do that via GET /delete

A GET request should never, ever change state. No buts.

Just because a bunch of well known sites use GET /logout to logout does not make it correct.

Doing anything else as demonstrated in this and other cases breaks web protocols, the right thing to do is:

GET /logout returns a page with a form button to logout POST /logout logs you out

Depends on your definition of “state.” A GET to a dynamic resource can build that resource (by e.g. scraping some website or something—you can think of this as effectively what a reverse-proxy like Varnish is doing), and then cache that built resource. That cache is “state” that you’re mutating. You might also mutate, say, request metrics tables, or server logs. So it’s fine for a GET to cause things to happen—to change internal state.

The requirement on GETs is that it must result in no changes to the observed representational state transferred to any user: for any pair of GET requests a user might make, there must be no change to the representation transferred by one GET as a side-effect of submitting the other GET first.

If you are building dynamic pages, for example, then you must maintain the illusion that the resource representation “always was” what the GET that built the resource retrieved. A GET to a resource shouldn’t leak, in the transferred representation, any of the internal state mutated by the GET (e.g. access metrics.)

So, by this measure, the old-school “hit counter” images that incremented on every GET were incorrect: the GET causes a side-effect observable upon another GET (of the same resource), such that the ordering of your GETs matters.

But it wouldn’t be wrong to have a hit-counter-image resource at /hits?asof=[timestamp] (where [timestamp] is e.g. provided by client-side JS) that builds a dynamic representation based upon the historical value of a hit counter at quantized time N, and also increments the “current” bucket’s value upon access.

The difference between the two, is that the resource /hits?asof=N would never be retrieved until N, so it’s transferred representation can be defined to have “always been” the current value of the hit counter at time N, and then cached. Ordering of such requests doesn’t matter a bit; each one has a “natural value” for it’s transferred representation, such that out-of-order gets are fine (as long as you’re building the response from historical metrics,

Don't be a wise ass, with that definition state changes all the time in memory registers even when no requests are made.

> So, by this measure, the old-school “hit counter” images that incremented on every GET were incorrect

Yes they are incorrect. No Buts.

Two requests hitting that resource at the same exact timestamp would increase the counter once if a cache was in front of it.

That brings me back to the year 2001, when my boss's browser history introduced Alexa to our admin page and they spidered a bunch of [delete] links. cough cough good thing it was only links from the main page to data, and not the actual data. I spent the next few days fixing several of problems that conspired to make that happen...

As in, anybody with a link to /delete could delete things? No identification/authentication/authorization needed?

> I spent the next few days fixing several of problems that conspired to make that happen...

Yes, I was a total n00b in 2001. But then, so was e-commerce.

and fwiw, I knew exactly how bad our security was... I kept my boss informed, but he had different priorities until Alexa "hacked" our mainpage :p

If you're not allowed to change state on GET requests, how do you implement timed session expiration in your api? You can't track user activity, in any way, on get requests, but still have to remember when he was last active.

Idempotence is for PUT requests. GET requests must not have side effects.

I've heard this "get requests shouldn't have side effects" argument before, but I don't think it works. At least, not for me, or I'm doing something wrong.

For example: Let's implement authentication, where a user logs in to your api and receives a session id to send along with every api call for authentication. The session should automatically be invalidated after x hours of inactivity.

How would you track that inactivity time, if you're not allowed to change state on get requests?

I think this is the argument for PUT instead of POST, not GET instead of POST.

You're confusing idempotency and side effects. A GET should not have any side effects, even if they are idempotent.

It's not about idempotency, but about side effects. The standards mention if it will cause side effects use POST. Logging out does cause side effect (you lose your login) and hence should be a POST.

In the old days it might have been acceptable to get away with a GET request but these days thanks to prefetching (like this very topic) it's frowned upon.


GET is also supposed to be “safe” in that it doesn’t change the resource which a logout would seem to violate.

The whole reason this is supposed to be the case is in order to enable such functionality as this instant thing.

Also: sometimes a site is misbehaving (for myself, or maybe for a user we're helping) and it's helpful to directly navigate to /logout just to know everyone is rowing in the same direction.

Using a POST, especially if you're building through a framework that automatically applies CSRF to your forms, forecloses this possibility (unless you maintain a separate secret GET-supporting logout endpoint, I guess).

When I originally started my community site I used GET for logout. However, users started trolling each other by posting links to log people out. It wasn't easy to control, because a user could post a link to a completely different site, which would then redirect to the logout link. So, I switched to POST with CSRF and never had another issue.

That's exactly the problem with idempotency.

actually, no. Idempotency means that you can safely do the same operation multiple times with the same effect as doing it once. That's a different issue than the no-side-effects rule which GET is supposed to follow.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact