Is it possible to restrict a route for AJAX only?

PhpAjaxSymfony

Php Problem Overview


Is it possible to restrict a Symfony 2 route for XHR requests only? I want to declare routes, which are only accessible via AJAX.

I do not want to put some extra lines into each AJAX-specific-actions like that:

if ($request->isXmlHttpRequest()) {
    // do something
} else {
    // do something else
}

I want to define:

  • one rule for AJAX requests
  • one rule for GET/POST requests to the same URL

in order to get around having conditions like above.

Php Solutions


Solution 1 - Php

I know this question is a bit older but meanwhile a new way to achieve this was introduced in Symfony 2.4.

Matching Expressions

For an ajax restriction it would look like this:

contact:
    path:     /contact
    defaults: { _controller: AcmeDemoBundle:Main:contact }
    condition: "request.isXmlHttpRequest()"

Also possible in Annotation:

/**
 * ContactAction
 *
 * @Route("/contact", name="contact", condition="request.isXmlHttpRequest()")
 */

Solution 2 - Php

My advice would be to define your own router service instead of default, which would extend from Symfony\Bundle\FrameworkBundle\Routing\Router, and redefine method resolveParameters() with implementing your own logic for handling additional requirements.

And then, you could do something like this in your routing:

your_route:
    pattern:  /somepattern
    defaults: { somedefaults }
    requirements:
        _request_type:  some_requirement

Solution 3 - Php

I'm not sure that you can prevent the request taking place, however you can check for an XHR request in the Controller by checking the current Request

The code would look like this:

if ($request->isXmlHttpRequest()) {
    // ...
}

This is not 100% reliable, due to among other things, browser inconsistencies and the possibility of proxy interference. However it is the predominant method of checking for an asynchronous request and is recommended by many. If you are cr

URL Parameter

An alternative would be to add a parameter in your URL to identify the request as asynchronous. This is achieved by adding ?ajax=1 to your URL. Then, check for the parameter with:

$AjaxRequest = $request->getParameter('ajax');
If($AjaxRequest == 1) {
    //...
}

Of course, at this point you could also create a specific Route e.g. /ajax/index/.

Solution 4 - Php

No, you cannot. It is not depend on which framework you are using, AJAX requests basically are just requests to a server. There is no 100% reliable solution, just "hacks".

Solution 5 - Php

What you're looking for does not exist in Symfony routing configuration.

Request::isXmlHttpRequest is even not 100% reliable, and checks HTTP headers put by your JavaScript library :

> It works if your JavaScript library set an X-Requested-With HTTP header. It is known to work with Prototype, Mootools, jQuery.

Solution 6 - Php

You can use the requirements for reach the described result.
So, suppose that you're defining routes onto yml format, you have to do something like this

my_route:
  pattern:  /path/to/route
  defaults: { _controller: CompanyBundle:Controller:Action, _format: html }
  requirements:
      _format:  xmlhttp /* not sure about the correct format because
                           i've never checked about */

And you can, of course, use _method: POST or _method: GET

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChrisView Question on Stackoverflow
Solution 1 - PhpMarkus KottländerView Answer on Stackoverflow
Solution 2 - PhpVitalii ZurianView Answer on Stackoverflow
Solution 3 - PhpRichView Answer on Stackoverflow
Solution 4 - PhpdmirkitanovView Answer on Stackoverflow
Solution 5 - PhpAlterPHPView Answer on Stackoverflow
Solution 6 - PhpDonCallistoView Answer on Stackoverflow