X-Requested-With, AJAX Requests, and Android WebViews

Why you shouldn't rely on X-Requested-With to determine if an HTTP request is an AJAX call or not.

Posted by Justin Carmony on March 11th, 2015

Today we ran into an interesting problem with certain pages of our website not loading for Android users inside their Facebook Apps. We dug down and ran into several red herrings, but ultimately found the problem.

The Problem

If you Google for “X-Requested-With”, or the $_SERVER variable name in PHP HTTP_X_REQUESTED_WITH you will likely find a great deal of posts stating that it is a method for detecting AJAX requests. Most major JavaScript libraries and/or frameworks like jQuery will set the X-Requested-With HTTP header for any AJAX requests. So if you Google X-Requested-With or HTTP_X_REQUESTED_WITH you will see blog posts & StackOverflow answers about detecting AJAX requests.

One major problem is while this a common practice, it isn’t an HTTP standard, and is used in other contexts as well. The example that bit us is the Android Facebook App and it’s WebViews. When using a WebView in Android, it will send the name of the app (i.e. com.example.app).

So if you’re logic looks like this:

$data = [
    'fruit' = ['apple','banana','watermelon']
];

// If this is an AJAX call, return json data
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']))
{
    echo json_encode($data);    
    exit;
}
// This is a normal browser request
else
{
    echo RenderTemplate('ListFruit.tpl', $data);
    exit;
}

AJAX requests made by jQuery will retreive JSON data of $data. Normal browser requests will receive the HTML template of ListFruit.tpl.

However, because Android App’s WebViews will set X-Requested-With, the code above will return JSON data, not the HTML, regardless if it is an AJAX request or not!

The Solution

Don’t rely on X-Requested-With to determine if a Request is an AJAX request or not. Instead have your app check the Accept header for application/json and make sure your AJAX requests JSON. Another option is to create URL endpoints that are only used by your application for AJAX calls (like a REST API).

I hope this helps someone, we spent a few hours finding and fixing this one.

About Justin Carmony

Justin is the Sr. Director of Engineering for the Deseret News and Deseret Digital Media, Previous President of the Utah PHP Usergroup, and frequently works with the Utah Open Source Foundation which organizes the OpenWest Conference. Justin loves just about anything with web technologies from PHP, JavaScript, Node.js, Salt, and managing engineering teams.

Learn More