Page MenuHomePhabricator

Require POST for all changes; Never change content on HEAD-request
Open, LowPublic

Description

Currently, some changes like patrolling or reverting can be achieved by GET requests. This is unfortunate because usually you don't expect a link changing content.

Some browsers offer automated link-checker-plugIns/addOns. They iterate over all links they find on one page to see whether the contents are available or whatever. Unfortunately the requests are sent with the session cookies.

The issue are the revert links in the watch list and other lists.

Recently a user unintentionally reverted all edits (where possible) included in their watch list.

I can't imagine how to effectively solve this issue. A <form> or JavaScript is always required to POST, I guess...


Version: 1.21.x
Severity: normal

Details

Reference
bz44602

Event Timeline

bzimport raised the priority of this task from to Low.Nov 22 2014, 1:29 AM
bzimport set Reference to bz44602.
bzimport added a subscriber: Unknown Object (MLST).

*scares*

And what about opening revert links on another tab/window? Imagine you need to revert a lot of edits in contributions or recentchanges. I do not want to go link by link, clicking on it, wait for the page to load, going back, locate what was the last revert link I have to hit and do it again for all edits. I want to click them and be able to open them on a new tab/window. This is not possible with a POST form nor JavaScript doing a POST.

It's user responsability to not run such a link-checker plugin on pages like recentchanges or contributions, specially if the user has rollback rights.

Also, the plugin is bad designed, since it should send HEAD requests, not GET ones. HEAD requests shouldn't trigger rollback (and if they do, that's a bug).

(In reply to comment #1)

HEAD requests shouldn't trigger rollback (and if they do, that's a bug)

Just tested and they did:

var xmlhttp = window.XMLHttpRequest ? 
   new XMLHttpRequest() : 
   new window.ActiveXObject("Microsoft.XMLHTTP"); 

 xmlhttp.open(
  "HEAD", 
  "URL",
  true
 );
 xmlhttp.onreadystatechange = function() {
  if (4 === xmlhttp.readyState) alert(xmlhttp.getAllResponseHeaders())
 }
 xmlhttp.send(null);

resulted in https://commons.wikimedia.org/w/index.php?title=User_talk:Rillke/LicenseReview.js&diff=prev&oldid=89617364 this edit.

what about opening revert links on another tab/window

This is indeed an issue. Perhaps there is a way to proper visualize the result using JavaScript or there is something we're just not seeing...

Would it be possible to make revert button targets to a temporary JavaScript-redirecting page that automatically redirects to the actual rollback page after like 2 seconds? Only good-coded link-checkers would follow scripts. I've found google using this kind of technology, and it doesn't only have the redirect, but also displays a link for browsers which doesn't support scripts.

(In reply to comment #3)
In this case it would be a more convenient solution to just make the rollback-link using AJAX and displaying the resulting diff in a jQuery dialog or something "speech-bubble-like" below the rollback link.

(In reply to comment #4)
AJAX doesn't allow CTRL+Click to open on a new tab/window. Imagine if you need to rollback a lot of edits from Special:Contributions.

This would impose annoying limitations just because someone with little or no knowledge of what was doing screwed things up. I wonder why that tool didn't hit the Special:Logout link before hitting the rollback buttons, and if the solution would be to simply move the logout link before any other link on the page.

(In reply to comment #5)
The old link should not be destroyed. Just binding an observer for the click-event. Then the user can decide which way go.
If you have to rollback lots of edits, you will be happy having AJAX because you'll be able to go quickly through the whole contribs page without having to open a lot of tabs that you would have to close after finishing and there is still http://meta.wikimedia.org/wiki/User:Hoo_man/Scripts/Smart_rollback

(In reply to Jesús Martínez Novo (Ciencia Al Poder) from comment #1)

Also, the plugin is bad designed, since it should send HEAD requests, not
GET ones. HEAD requests shouldn't trigger rollback (and if they do, that's a
bug).

Actually, it's MediaWiki with the issue. As reported, GET and HEAD requests should never change state.

Per http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 :

"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"."

I don't know whether we want to fix this for existing features (however, it *can* be done in such a way as users with JS see exactly the same user experience and it still works with no-JS, albeit with an extra step).

However, no new GET or HEAD methods that take actions should be introduced. Recently developed features, such as Thanks, show how to follow this guideline in practice (uses AJAX with the API requiring POST and a token, with a no-JS fallback that has a nice interface and uses POST, i.e. https://en.wikipedia.org/wiki/Special:Thanks/123)

Not able to open rollback links on a new page means there's no way to rollback a lot of edits and also see what has been reverted.

"Fixing" this will mean fixing a very rarely case of script fuck-up while breaking user experience and making things difficult for sysops when dealing with vandalism and SPAM. The question here is: It's really worth it?

Krinkle closed this task as Resolved.EditedMay 23 2016, 9:33 PM
Krinkle claimed this task.
Krinkle subscribed.

The examples mentioned (patrolling, rollback, watchlist) are fixed. The overall tracking task is T92357. See also T33270.

Ciencia_Al_Poder removed Krinkle as the assignee of this task.

Here to say that as W3C specification every GET request should be idempotent.

From: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
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". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.