views:

684

answers:

4

All over the Internet, included even here at StackOverlow, people state that a good way to check if a request is AJAX or not is to do the following:

if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ) {...}

However, I don't see $_SERVER['HTTP_X_REQUESTED_WITH'] in the official PHP documentation

And when I try to do the following:

echo $_SERVER['HTTP_X_REQUESTED_WITH'];

Nothing is outputted.

Am I doing something wrong? Because I'd really like to be able to use $_SERVER['HTTP_X_REQUESTED_WITH'] if it's available.

+6  A: 

$_SERVER keys that start with HTTP_ are generated from HTTP request headers. In this case, the X-Requested-With header.

Ignacio Vazquez-Abrams
So do all browsers set this header? Also, how is this header set if it's a AJAX call?
Hank
XHR can send arbitrary headers in a request.
Ignacio Vazquez-Abrams
@Hank What's wrong with AJAX call? You think it uses not HTTP request? Which one then?
Col. Shrapnel
I'm trying to prevent people from directly access my web service but allow XHR
Hank
@Hank ahahahaha what a silly :) What's wrong with this "direct access" then?
Col. Shrapnel
@Hank telling apart XHR from "normal" requests is absolutely, fundamentally useless as a security measure, as everyone can simulate a XHRequest without problems. You need to protect your Ajax scripts using solid authentication measures (or whatever else you already have in place for your main application).
Pekka
+5  A: 

The variables in $_SERVER are not really part of PHP, which is why you won't find them in the PHP documentation. They are prepared by the Web server which passes them on to the scripting language.

As far as I know, the X-Requested-With is sent by the Ajax functions of most major Frameworks but not all (Dojo, for example, added it only two years ago: #5801). As such, and taking into considerations @bobince' comments, it's safe to say it's not generally a 100% reliable method to determine whether a request is an AJAX request or not.

The only 100% secure way is to send a pre-defined flag (e.g. a GET variable) along with the request and for the receiving page to check for the presence of that flag.

Pekka
I don't think it's a reliable method either. Firewall/proxy tools may futz with it, and you could be returning the wrong response to proxied users if you don't combine use of this header with `Vary: X-Requested-With` in the response... which in turn screws up cacheing in IE. Lots of people do use `X-Requested-With`, but I think it's a terrible idea. Better to pass a flag in the query parameters to signal you want an XMLHttp-style (or JSON) response.
bobince
+1  A: 

This header is a standardization-in-progress from all of the ajax libraries out there.

It won't be documented in the php documentation per-se, but rather in the different ajax libraries that set this header. Common libraries do sent this header (jQuery, Mojo, Prototype,..)

Usually these library will set the header using

xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");

I Hope this will help you, Jerome Wagner

Jerome WAGNER
A: 
echo $_SERVER['HTTP_X_REQUESTED_WITH'];

What'd you expect from such a code? Assume you're running it directly from the browser, not using AJAX request. So, how come this header could be set?

Well the Answer to the Ultimate Question of Life, the Universe, and Everything - an HTTP sniffer! Get yourself one and forget of printing $_SERVER variable.

Firebug has one, or you may want to use Fiddler HTTP proxy or LiveHTTPHeaders Mozilla plugin. I'm bored to make links but it easily googled.

So, with HTTP sniffer you can be sure of any HTTP header ever.

Note that you can't prevent any "direct access" by using XHR, as every HTTP request to your server is already "direct".

Col. Shrapnel
From both browser and XHR, nothing it outputted
Hank
how do you know with XHR? Did ou properle encoded an answer?
Col. Shrapnel