HTTP Referer overwritten when used in FormAPI.
dobson - May 15, 2006 - 18:41
| Project: | Drupal |
| Version: | 5.7 |
| Component: | forms system |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | by design |
Jump to:
Description
Here is my test code:
function mymodule_testform(){
$form = array();
//$form['#redirect'] = $_SERVER['HTTP_REFERER'];
$form['then_go_to'] = array('#type'=>'hidden', '#value'=>$_SERVER['HTTP_REFERER']);
$form['submit'] = array('#type'=>'submit', '#value'=>'Submit Form');
drupal_set_message('set: '.$form['then_go_to']['#value']);
return drupal_get_form('testform', $form);
}
function testform_submit($form_id, &$form_values){
drupal_set_message('get '.print_r($form_values['then_go_to'],true));
// return $form_values['then_go_to'];
drupal_goto($form_values['then_go_to']);
}When the form is rendered for the first time, the message printed is:
set: <MY REFERER>When I submit, however, the message is:
* set: <FORM URL>
* get <FORM URL>
* set: <FORM URL>It seems that the form render function is being called once again before the submit code, and resetting the referer to the form URL. I have tried to set $form['#redirect'], and I have tried to return the URL from the submit function, with the same results.

#1
Just commenting to ping me.
#2
Pardon me, but how this is a Drupal issue? HTTP_REFERER is the previous page. In this case, the previous before the POST request.
#3
Chx: please take two deep breaths and actually try to understand, mmkay?
The only way it could become set to the URL of the form is if the form generating code (where $form['whee'] was set to disobey.com) was re-run at a later step in the process (somewhere between _alter and _submit), when the referer has, in fact, changed. This has nothing to do with "OHMYGOD, LEARN2HTTP" - the same problem would appearently occur with epoch timestamps: they'd be set once on the GET, and then again on the POST which can be a huUuGe difference. Same with a zillion other dynamic form fields that should not change.
As you've mentioned in IRC, if your *only* soluton, that you know ACTUALLY works because you tested it before responding, is to change the #action of the form to something else, then by all means say as much and close.
#4
I have not tested anything and if that's the case, then I am re-closing because there is no way we can avoid (in 4.7, at least) to rebuild the form tree as form API needs it. For 4.8 we might save it to session.
#5
Followup for those who may come after in search of a solution: there appear to be several clues for finding ways around this particular design.
1) $form['#action'],
2) checking for POST vs GET,
3) $_SESSION variables,
4) wait for 4.8 :),
And probably a few more ( certainly not $form['#redirect'] as of 4.7.0 ).
Good luck.
Oh, and while I'm here already, I might as well mention that the comment preview button below this post isn't previewing (I'd report it properly but I'm nervous to start a new thread on drupal.org unless A: I have a bloody good reason to, and B: It's important enough for me to have taken the time to ask for help in phrasing my post in a manner which will not result in my being ignored while still being acceptable to the drupal community).
Oh, and seeing as I'm already here, I may as well mention that the breadcrumb above this 'New Comment' page reads: 'Home » Downloads » HTTP Referer overwritten when used in FormAPI'. I am of course not sure, but I might have posted to 'Home » Downloads » Drupal project » Drupal » issues'. See above.
I totally love Drupal, btw! Drupal and #drupal-support with its cargo of friendly, helpful people are the best in the west.
#6
*BUMP*
This is still the case? I'm using Drupal 5.7 and finding the EXACT same behaviour. And strangely, I can find no other discussion of it. Whatever happened to this issue? The implication was it would be revisited, but it seems that never happened and it's still not clear how you get around it. Any takers?
#7
Greg: the way to move this forward would be to test it under Drupal 6 and, if it still exists, state as much here and set the version to 7.x-dev. No more work is being done, save for security fixes, on Drupal 5 OR 6.
#8
this is still by design. Drupal 6 has a #cache and Drupal 5 has #multistep that stores the form tree though.
#9
Thanks guys. Achieved what I wanted with nodeapi in the end. Look forward to getting in to Drupal 6, but no can do until a few more modules I need are in a more stable state. =(
Won't be long now!
#10
In case anyone has a similar solution and chances on this thread, I wrote up my solution here as a comment: http://drupal.org/node/134000#comment-799369
(Which was deleted ... wtf? Sometimes I wonder why I bother...)
#11
Word on the street is that this idea - redirecting back to referer - is an unreliable one because of the referer_uri() call; you may not get one at all, and it could be faked or insecure. If you're linking internally, it's probably better to pass a variable on to the form function with the redirect path in it. However, if none of that is sufficient to dissuade you from this path, you may benefit from the ideas below. I decided to save a variable to $_SESSION with the referer - and since I had several different forms, I broke it out into a separate function:
function _form_redirect() {if (!$_SESSION['formredirect'] || $_SESSION['formredirect']['time'] < (time() - 600)) {
$redirect = check_url(referer_uri());
$_SESSION['formredirect'] = array('url' => $redirect, 'time' => time());
}
return $_SESSION['formredirect']['url'];
}
That way I could call that function in form creation:
function foo_form() {...
$form['#redirect'] = _form_redirect();
}
And I unset the $_SESSION variable before returning the redirect in the submit function:
function foo_form_submit($form_id, $form_values) {unset($_SESSION['formredirect']);
...
return $form_values['#redirect'];
}
As it turns out, since I think all my links are going to be internal, I'm probably going to put another parameter into the function that calls confirm_form instead of doing the above; however, since I spent some time on this, I figured it might possibly help someone else out if you need to redirect back to an external page.