ColdFusion UDF for detecting jQuery AJAX operations…

Posted by Dan on Apr 9, 2009 @ 6:43 PM

Raymond Camden justed posted an article on detecting jQuery AJAX operation using ColdFusion. I honor of that post, I thought I'd share the UDF I've been using in my application for quite some time:

<cffunction name="isAjaxRequest" output="false" returntype="boolean" access="public">
    <cfset var headers = getHttpRequestData().headers />
    <cfreturn structKeyExists(headers, "X-Requested-With") and (headers["X-Requested-With"] eq "XMLHttpRequest") />
</cffunction>

The code uses the exact same logic the technique in Raymond's post, but having the code in a function makes your detection code a lot easier to read.

Now when you want to detect if a request came from an AJAX operation, you can just do:

<cfif isAjaxRequest()>
    Came from jQuery! :)
<cfelse>
    Didn't come from jQuery. :(
</cfif>

Doesn't get any easier than that!

Categories: HTML/ColdFusion, jQuery

14 Comments

  • Great tip, I could have used it several projects ago!

    But this is somewhat misleading. It tells you an "X-Requested-With" header is present with a value of "XMLHttpRequest". Not necessarily that jQuery made it though. Scriptaculous adds that header, too. Most likely others as well.
  • @Jules:

    While other libraries do send it, jQuery always sends with any XHR requests. So it's not going to tell you it's jQuery specifically, hopefully you know what library you're using on your website. :)
  • I know I could test this myself but I thought I'd highlight/ask anyway...

    What about a .get() or .post() request in jQuery I wonder?
  • @Adrian:

    The $.get() and $.post() methods in jQuery are just shortcuts to the $.ajax() method--they are all still AJAX operations. Any XHR call in jQuery will be invoked with the extra header.

    Some other libraries do the same thing. It's not part of the formal XMLHttpRequest() spec, but it's a nice way to easily determine an AJAX request.

    You could also use the same technique in your own code, you'd just have to build in the header addition into your XHR library.
  • When you say <cfif isAjaxRequest()> in a component, does that mean that isAjaxRequest must also be defined in that component, or do you extend the component, or do you mean <cfset obj = ...> <cfif obj.isAjaxRequest()> ?
  • @Phillip:

    How you handle it up to you. I essentially keep a class library of UDFs that I import into any template I need that class of library files.

    However, if I'm invoking a CFC AJAX, then I really don't have a need for the function in the first place--since I'm generally going to be return a structured data type (such as a struct.) So, how I called the function remotely is irrelevant.
  • I'm just making sure I have the syntax correct.
    If you are <cfif isAjaxRequest()> in a template, then you must first do a <cfinclude > of a .cfm file that contains all your commonly used UDFs, right?
  • @Phillip:

    Yes, or some people like to store their UDF libraries in a persistent cope (like the application scope) so they're always available and they don't have to reload on each page.

    Whatever fits your model the best.
  • Oh, ok. And I'm not asking you to speak for everyone. I'm just trying to understand your blog post.
    So do you say Application.isAjaxRequest() or do you do a cfinclude?
    I know the answer can be "You can do anything you want!", but I'm just trying to understand what Dan Switzer does.
    And I'm really hoping the answer to that isn't "It depends".
  • @Phillip:

    Unfortunately, it is "it depends." There's no "one ring to rule them all," it really depends on the application and what type of framework you're using to what makes sense.

    I've both cached UDFs in a persistent scope and used <cfinclude /> to import libraries into code. I just make my decision based upon what makes more sense to the current codebase.

    When working on code that's essentially procedural based, I tend to use <cfinclude /> more as "import" statement for loading the library--especially since I have some pretty large UDF libraries (which are organized by functionality.)
  • I just add a ajax=1 variable on the end of ajax requests. Or add a timestamp variable to also avoid caching. Then check for that.
  • Charles Robertson's Gravatar
    Charles Robertson
    Ziggy. Your approach is not secure. An attacker could firebug the ajax URL variable, and access the page directly. Using IsAjaxRequest() is a better approach. I'm just hoping it works with prototype.js. I use both jQuery & prototype.js...
  • @Charles,

    Nothing about HTTP is secure. A user can still modify the headers sent to the server, so even the approach here isn't hacker proof. You still need to take whatever precautions you need to make your code secure.
  • Charles Robertson's Gravatar
    Charles Robertson
    @Dan

    Generally the process of enacting a request header XSS attack requires a more elaborate approach, especially on websites that use SSL.
    I have just watched a video, where the attacker, uses Wireshark to steal a user's Facebook login cookies. Admittedly, the only reason the attacker was able to demonstrate this, so easily, was because the connection to Facebook was unsecured. His victim, had turned off the Facebook 'secure browsing setting'. But, even secure data can be obtained, using SSL stripping.
    I think this video must be quite old, because I am sure Facebook enforce secure browsing, now?
    I agree that almost any XSS or CSRF security measure can be circumvented, but it is a question of how hard an attacker is willing to try. Adding 'ajax=1' to a URL, is about as easy as it gets.

Comments for this entry have been disabled.