Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is $request->isXmlHttpRequest() reliable in symfony2?

Tags:

ajax

symfony

Let's consider a scenario like below:

  1. User selects filter button which create a AJAX call to a symfony2 controller and return the result in JSON format.
  2. User select some other links and system will redirect him to the page
  3. User select browser Back button.
  4. User will see JSON response, but he should see the original page.

My controller look like below :

/**
 * 
 *
 * @Route("/ajax", name="ajax_route" , options={"expose"=true})
 * @Template()
 */
public function someAction()
{
    $request = $this->getRequest();

    $json = array( );

    if($request->isXmlHttpRequest())
    {

        $res = json_encode($json);

        return new Response($res , 200 , array( 'Content-Type' => 'application/json' ));
    }

    return array( );
}  

In other words, if user press back button the if($request->isXmlHttpRequest()) returns true which is not the result I am looking for. Is it a normal behavior or what ?

like image 331
pmoubed Avatar asked Aug 13 '12 20:08

pmoubed


2 Answers

Symfony\Component\HttpFoundation\Request::isXmlHttpRequest() is a simply utility-method that checks whether HTTP request came up with X-Requested-With header with value XMLHttpRequest. So it's as reliable as X-Requested-With header is.

However, this is not really important. The important thing to notice is the fact that when the user clicks on the back button the browser does not send a new HTTP request to the server. It just restores the page from its internal memory/cache.

like image 152
Crozin Avatar answered Sep 28 '22 07:09

Crozin


I understand that this is an old question, but the same issue just caught me so I figured I'd write up an answer anyway.

In most scenarios, you can invalidate the back button cache by attaching an onUnload handler to the window, like so:

window.addEventListener('unload',function(){});

or, if you prefer jQuery:

$(window).unload(function(){});

but, since your AJAX response is in JSON, that's obviously not possible since you can't include script fragments. In this case, I think the best idea is to set the cache-control: no-store header so the browser wont attempt to cache the result.

You can do that in the OP's case with Symfony2 using:

return new Response($res , 200 , array(
    'Content-Type' => 'application/json',
    'Cache-Control' => 'no-store',
));

or for more general PHP:

header('Cache-Control: no-store');

There's a caveat here in that it may degrade your performance quite a bit, depending on your app's structure, in which case your best bet would probably be to just use a different URL for your AJAX call. Sucks, I know.

You can find some documentation on the bfcache here, which may be more helpful in different cases.

like image 35
Jon G Avatar answered Sep 28 '22 05:09

Jon G