Opened 12 years ago
Last modified 10 years ago
#10393 new defect
POST data is lost after redirect
Reported by: | ejucovy | Owned by: | ejucovy |
---|---|---|---|
Priority: | normal | Component: | PermRedirectPlugin |
Severity: | normal | Keywords: | |
Cc: | Trac Release: | 1.0 |
Description
The situation is described in comment:ticket:2210:14 and comment:ticket:2210:16 -- if a user has a browser window to a Trac edit screen open for a long enough time before submitting the edit form, their session can expire and they'll be redirected to the login screen. After successful login, they'll be redirected back to the edit screen, but their edits will be lost, which can be very annoying.
Simple way to reproduce in a browser:
- Log in to your trac site
- Open a browser tab to http://trac-site.com/newticket
- Fill in some text to create the new ticket
- Don't submit the form yet!
- Open a second browser tab to http://trac-site.com/logout and then close it
- Back in the first tab, submit the form
If PermRedirectPlugin is installed, you'll be redirected to the login screen; log in, and you'll land back on the "newticket" form. But all your hard work is completely lost.
I think that it's fair to consider this a bug in PermRedirectPlugin. The reason is that, without PermRedirectPlugin installed, Trac's behavior is "safer." If you follow the exact same reproduction steps without the plugin installed, you'll be given an "Error: Forbidden" screen that prompts you to log in.
This screen is actually rendering an HTTP response to the POST request, rather than instructing the browser to issue an immediate GET request like the plugin does. So this actually gives you an opportunity to log back in using a separate tab, and then simply hit "reload" on the first tab. Your browser will warn you that you're resubmitting a form via POST and ask if you really want to resubmit the data. You say yes, and the exact same POST request will be replayed, with your original intent fulfilled and no loss of data.
Attachments (0)
Change History (5)
comment:1 Changed 12 years ago by
comment:2 Changed 12 years ago by
The session-based approach is problematic because as soon as the user logs in, he's likely to have a different session than the one he had as an anonymous user.
comment:3 Changed 12 years ago by
(4c) is problematic because there isn't necessarily a login form (in the case of Trac core HTTP auth)
comment:4 Changed 12 years ago by
Hybrid idea:
- In post_process_request, if method==POST, set a (path-scoped?) "saved_post" cookie containing the POST body
- Add javascript to all pages such that on window.load
- Check if "saved_post" cookie is present; if it is, save its value to a Javascript variable and delete the cookie
- Then pop up a modal dialog: "You have unsaved data that you tried to submit earlier. Do you want to resubmit it?"
- If user clicks "Yes", use Javascript to fire a synchronous POST request using the exact request body from the cookie
(This is, obviously, getting pretty convoluted, but it's a fun problem to think about.)
comment:5 Changed 10 years ago by
I remember dealing with proper re-direct in AccountManagerPlugin. IMHO salvaging POST date after redirect could (should?) be done inside AccountManager, since it already messes with Trac's LoginModule.
Regarding propagating session attributes two pre-existing methods come to my mind to possibly start from:
- trac.web.session.Session.promote_session()
- it promotes all anonymous session attributes to an authenticated session, if there is no preexisting session data for that user name, meaning on first successful login only - one could aim at still copying, but only non-existant session attributes
- functions in datasaverplugin/trunk/datasaver/htdocs/datasaver.js
- with the issue of session-based approach, at least of no
localStorage
is available in user's browser - form restore fromlocalStorage
might even solve the issue right-away (untested)
UnwashedMeme outlined a few possible solutions:
Another class of solutions that occurs to me:
I think (1), (2), (4a) and (4c) are worth investigating, but all of these approaches are pretty ugly in one way or another.