Click here to Skip to main content
15,889,838 members
Articles / Programming Languages / Javascript

SecureXHR - an XMLHttpRequest wrapper library written in JavaScript

Rate me:
Please Sign up or sign in to vote.
4.89/5 (7 votes)
9 Jun 2013CPOL36 min read 25K   562   18   3
SecureXHR aims at providing a simple but sufficient interface for the XMLHttpRequest object and increase its safety
<!-- Start Article -->

Download note

The complete package which includes test files takes up about 110Mb of disk space (when unpacked), as there are two large files needed to test the XMLHttpRequest progress functionality.

Introduction

The XMLHttpRequest object is implemented in all major web browsers to allow developers benefit from the AJAX technology. The advantages of AJAX are indisputable, however XMLHttpRequest is often awkward to use, especially due to its asynchronous nature: not only is the onreadystatechange event triggered asynchronously, but the same is true for all other important events, such as onloadstart, onloadend or onerror, to name a few. Vital information is not to be found in one place, there is no easy way to learn what is going on with an AJAX request at a given time and debugging may be a real nightmare.

Secondly, there are a number of configuration options which may and/or have to be defined for each XMLHttpRequest connection. If a given site relies on AJAX heavily redefining all the necessary settings in various parts of our code may make it less legible and more problematic to modify. Moreover, any configuration related problems can usually be detected only after an attempt to open a connection, send data or retrieve a server response has been made.

Finally, there are serious security concerns related to spying and phishing attacks which may be conducted by exploiting some weaknesses of the XMLHttpRequest object and JavaScript. The risks include:

  • overwriting and wrapping an instance of the XMLHttpRequest object (dangerous if a singleton instance is used),
  • overwriting and wrapping an XMLHttpRequest.prototype.open method (dangerous if there is a chance of some malicious script having been executed before most "AJAXian" communication takes place, i.e. if new XMLHttpRequest instances are created after a page and a malicious script have been loaded),
  • using an unmodified XMLHttpRequest instance to send some private information displayed on a web page to a remote site controlled by an attacker.

SecureXHR addresses all the issues presented above as it provides the developer with a solution which offers:

  1. a user friendly interface that lets one identify, control, handle and debug AJAX connections and gather all the necessary information related to each XMLHttpRequest instance in a much more convenient way;
  2. a method to validate and reuse XMLHttpRequest configuration options;
  3. a fix to effectively prevent all three types of phishing attacks which have been previously described.

SecureXHR does not prevent cross-site scripting attacks but protects the XMLHttpRequest object in case of a successful XSS attack.

Background

SecureXHR is a self executing anonymous function which is invisible and inaccessible from the global scope. Its interface is exposed to the global scope in the form of a getter function so there is no way to overwrite private methods or properties used by SecureXHR.

However, there is a risk of its interface being overwritten either if it is not deleted after no longer needed (the developer should delete the SecureXHR interface after all scripts which use AJAX technology have been loaded) or if other scripts which employ SecureXHR do not properly hide their code from the global scope (i.e. if a second party variable or property storing the SecureXHR interface getter function is somehow exposed to the global scope). Even if a SecureXHR interface copy gets modified by a malicious script there still remains a tool to effectively prevent phishing attacks: the developer can turn on the SecureXHR's sites filter and either allow AJAX connections only to the current browser window site or block XMLHttpRequest requests to sites which are not on the filter list. The sites filter can be used either internally by SecureXHR or globally by the means of SecureXHR modifying (overwriting and wrapping) the original XMLHttpRequest.prototype.open method.

Similarly, SecureXHR may optionally attempt to remove the window.XMLHttpRequest from the global scope to prevent any malicious scripts from having access to the XMLHttpRequest object. With some browsers there might be no way to effectively hide the host object from the global scope, but SecureXHR can optionally attempt to modify (overwrite and wrap) the original XMLHttpRequest.prototype.open method so that it will expect a secret token as its additional (6th) parameter. In this way, SecureXHR will be the only script which is able to directly access and run AJAX requests. Other scripts will have to rely on the SecureXHR interface.

Letting SecureXHR modify and wrap the original XMLHttpRequest.prototype.open function is strongly advised as a way to provide an ultimate safety to an AJAX dependent web page, but not all browsers allow native object prototype modifications (e.g. at least some versions of Internet Explorer) and one must bear in mind that any prototype modifications are impossible to revert.

A quick look

A short example might be useful to show the flexibility and user-friendliness of SecureXHR in terms of running AJAX requests:

JavaScript
//first retrieve the SecureXHR interface:
var xhr = getSecureXHRInterface();

//then create at least one reusable configuration for XHR requests:
var xhrConfig = xhr.conf({
	"getType" : "json" ,
	"path"    : "/ajax/index.php" ,
	"onDone"  : xhrComplete
});

//run as many AJAX requests as you like using the configuration created above:
//(you can optionally modify any of the configuration values when opening a connection):
var ok = xhr.exec( {"id":453, "action":"getUserDataById"} , xhrConfig.inf.cfgId );

//check for any basic problems with initiating the request:
if( ok.err.fatal )
	alert( "The request could not be initiated due to a fatal error at " + ok.err.at );

//the method to be triggered when a request has been terminated or completed:
function xhrComplete( requestInfo )
{
	if( requestInfo.err.fatal )
	{
		//analyse and deal with an error which has occurred during a request
		return;
	}
	//else:
	//deal with the server response which is to be found in "requestInfo.xhr.response" property
}

With minimalistic approach the following will also work:

JavaScript
getSecureXHRInterface().exec( {"id":453, "action":"getUserDataById"} , 0 , {
	"getType" : "json" ,
	"path"    : "/ajax/index.php" ,
	"onDone"  : function( result ) {
		displayUserData( result.xhr.response );
	}
} );

Using the code

Loading subsequent scripts

In order to properly use SecureXHR, the developer has to load at least 4 scripts in the following way:

  1. the SecureXHR configuration script containing an object with setup options, some of them to be used by all XMLHttpRequest instances. This script is automatically removed from the global scope by SecureXHR as soon as it has been parsed. This step can be skipped if the developer decides to use default values of SecureXHR setup options;
  2. the SecureXHR script containing the main code of the library;
  3. one or more scripts which will make use of the XMLHttpRequest object via the SecureXHR interface;
  4. a clean up script which will delete the SecureXHR interface so as to remove it from the global scope. This step is optional if the developer wants to make the SecureXHR interface available to other scripts which may be executed later on, but leaving this interface in the global scope involves security risks.

For instance:

HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" charset="utf-8">

<!-- initial setup and possibly configuration for the SecureXHR object -->
<!-- this script is optional if the developer decides to rely on the default configuration used by SecureXHR -->
<script type="text/javascript" src="securexhr_ini.js"></script>

<!-- the SecureXHR object (should be loaded before all other scripts which are going to use it) -->
<script type="text/javascript" src="securexhr.js"></script>

<!-- all other scripts which are supposed to employ the AJAX technology -->
<script type="text/javascript" src="your_script_using_ajax_1.js"></script>
<script type="text/javascript" src="your_script_using_ajax_2.js"></script>

<!-- a clean up script removing the SecureXHR setup interface from the global scope -->
<!-- the name of a getter function which returns the interface is set via the _SecureXHRIni.interfaceExposeFuncName property -->
<!-- this script can be skipped, but leaving the interface in the global scope would pose a security threat -->
<script type="text/javascript">
	getSecureXHRInterface = undefined;
</script>

<!-- other scripts, meta tags and page content... -->

Preparing the SecureXHR setup script

An object with default setup options used to initialise SecureXHR looks like the following:

JavaScript
var _SecureXHRIni = {
	"interfaceExposeFuncName" :	"getSecureXHRInterface" , // see point 1. below
	"deleteWindowXHR" :		true	,		// see point 2. below
	"allowXHRViaActiveX" :		false ,			// see point 3. below
	"onXHRPrototypeForged" :	null ,			// see point 4. below
	"allowOtherSites" :		false , 		// see point 5. below
	"modifyXHRToFilterSites" :	true , 			// see point 6. below
	"modifyXHRToRequireToken" :	true ,			// see point 7. below
	"maxOpen" :			4 ,			// see point 8. below
	"rerunPendingMs" :		25 ,			// see point 9. below
	"testing" :			false			// see point 10. below
};

By default, SecureXHR will look for a variable named _SecureXHRIni which should contain its setup configuration options. If the object is not found or if it doesn't have some of the fields presented above SecureXHR will use default values for each setup property which has not been defined. If the developer wants to store SecureXHR setup options in a variable of a different name (other than _SecureXHRIni) he has to modify the last part of the script containing the main SecureXHR code. For example, instead of the original ...})("_SecureXHRIni") code the developer can change it to something like ...})("SecureXhrSetupOptions").

SecureXHR setup options explained in more detail:

  1. interfaceExposeFuncName (string, tested against the /^[a-zA-Z_\$]{1}[a-zA-Z0-9_\$]*$/ regular expression) - the name a getter function which will be created by SecureXHR in the global scope so as to make its interface available to other scripts. Default value: "getSecureXHRInterface".
  2. deleteWindowXHR (boolean) - a flag telling SecureXHR whether or not it should attempt to remove the window.XMLHttpRequest property so as to hide the XMLHttpRequest object from the global scope in order to increase its security. Such attempt will most likely be successful with Firefox and/or Chrome browsers and fail with Internet Explorer. Default value: true.
  3. allowXHRViaActiveX (boolean) - a flag telling SecureXHR whether or not it should allow creating XMLHttpRequest instances via the ActiveX object. Setting this option to true will make SecureXHR work with older Internet Explorer versions, but at the same time, it will be a breach of security, because other safety related options, such as deleteWindowXHR, onXHRPrototypeForged, modifyXHRToFilterSites and modifyXHRToRequireToken, will become ineffective with older Internet Explorer browsers. Default value: false.
  4. onXHRPrototypeForged (function) - an optional delegate function which is to be triggered in case SecureXHR detects any unauthorised modification of the XMLHttpRequest.prototype methods and/or properties (apart from modifications made by SecureXHR itself). SecureXHR will check for XMLHttpRequest.prototype modifications only in case the XMLHttpRequest object remains available to the global scope. For more details see SecureXHR delegate functions below. Default value: null.
  5. allowOtherSites (boolean / array) - an option used to apply a site filter. If the value is set to true no filter will be used. If the value is false SecureXHR will allow XMLHttpRequest connections to be made only with the current browser window site. If the value is an array containing site names SecureXHR will block outgoing XMLHttpRequest requests to any site which is not on the list (the current browser window site is always allowed by default). If such an array contains at least one badly formed site name SecureXHR will throw an error and the script will be terminated. Default value: false.
  6. modifyXHRToFilterSites (boolean) - a flag telling SecureXHR whether or not it should modify the XMLHttpRequest.prototype.open method so that each new XMLHttpRequest instance will internally implement the site filter defined via the allowOtherSites SecureXHR setup option. Default value: true.
  7. modifyXHRToRequireToken (boolean) - a flag telling SecureXHR whether or not it should modify the XMLHttpRequest.prototype.open method so that it will expect a secret token (generated and accessed only by SecureXHR) as its additional (6th) argument. Default value: true.
  8. maxOpen (unsigned integer) - the maximum number of simultaneous (open) XMLHttpRequest connections. Normally, browsers limit the number of concurrent connections per server, but SecureXHR can only limit the number of all AJAX connection per browser tab (other requests are placed on the pending requests list). The developer might want to set this value just below the limit adopted by the browser to avoid browser hanging (in case the connection limit to a server has been reached and requests cannot be completed any time soon) and prevent potential DoS attacks via XMLHttpRequest connections. Default value: 4.
  9. rerunPendingMs (unsigned integer) - the time interval (in milliseconds) in which SecureXHR checks whether the number of concurrent connections has fallen below the maxOpen value (see the point above) so that subsequent requests waiting on the pending list can be run (open). Default value: 25.
  10. testing (boolean) - a flag telling SecureXHR whether or not to add an extra function to its interface getter method (see information on the interfaceExposeFuncName setup option above). When this value is set to true an object returned by getSecureXHRInterface will contain the priv function which exposes some private SecureXHR properties which should never be disclosed in the production mode (for more details see getSecureXHRInterface().priv() function description below). Default value: false.

A script (securexhr_ini.js in the example above) containing the SecureXHR setup configuration object (_SecureXHRIni) does not have to be loaded if the developer decides to adopt default values in case of each setup option. Otherwise, the developer has to define only those setup options whose values should be different. For instance:

JavaScript
var _SecureXHRIni = {
	"allowOtherSites" :	[
		"http://www.yoursite.com" ,
		"https://www.yoursite.com" ,
		"http://yoursite.com" ,
		"https://yoursite.com"
	] ,
	"maxOpen" :		6
};

In this example, the number of all concurrent connections per browser tab has been limited to 6 and any AJAX connections to sites other than "yoursite.com" will be blocked (http/https and www/no-www variants have to taken into account as the current window address migh be "www.yoursite.com" while a script attempts to access "yoursite.com" - or vice versa - which would not work if only one of these site names were included in the allowOtherSites filter).

An error will be thrown and SecureXHR will not start if the following setup option problems are encountered:

  • the value of the interfaceExposeFuncName option is not a valid JavaScript function name
  • the value of the interfaceExposeFuncName option is the same as the name of an existing variable / function
  • at least one site name listed in the allowOtherSites array is malformed

Even if the developer supplies correct values for setup options SecureXHR may still fail to set some of them. This might be especially the case if:

  • the developer sets both/either the modifyXHRToFilterSites option and/or the modifyXHRToRequireToken to true but the browser does not allow SecureXHR to overwrite the XMLHttpRequest.prototype.open method - the value is set to false
  • the developer sets the deleteWindowXHR option to true but the browser does not allow SecureXHR to successfully remove the XMLHttpRequest object from the global scope - the value is set to false

In order to check what values have been actually adopted by SecureXHR and which user-defined values could not be set the developer has to use the getSecureXHRInterface().info("setup") method (see SecureXHR interface description below for more details).

Request configuration settings

SecureXHR offers a number of options related to AJAX requests:

  • onDone (function) - a mandatory delegate function to be triggered when a request has been completed or terminated for whatever reason. This is the only obligatory parameter which will not accept its default value and has to be defined by the developer - otherwise the getSecureXHRInterface().conf() or the getSecureXHRInterface().exec() methods will return an error. For more details see SecureXHR delegate functions below. Default value: null.
  • onProg (function) - an optional delegate function to be triggered whenever a computable amount of data has been uploaded and/or downloaded during an asynchronous request. It is useful for measuring and reporting on data upload and/or download progress. For more details see SecureXHR delegate functions below. Default value: null.
  • onStat (function) - an optional delegate function to be triggered whenever a request readyState property changes (4 states) or when a request passes into one of its subsequent stages:
    1. "pending" - placed on the pending requests list
    2. "setting" - setting up request parameters
    3. "sending" - attempting to send a request
    4. "loading" - XMLHttpRequest.onloadstart event triggered (or the point just after the XMLHttpRequest.send() method execution reached if the onloadstart event is not supported by the browser)
    5. "closing" - the request has been completed or terminated and a response information object is being prepared
    It gives the developer a better idea of what is going on with a running request. For more details see SecureXHR delegate functions below. Default value: null.
  • onTime (function) - an optional delegate function to be triggered when an open asynchronous request has not been completed within the number of milliseconds set in the wait request configuration option (see below). For more details see SecureXHR delegate functions below. Default value: null.
  • wait (integer) - the number of milliseconds (counting from the time of the XMLHttpRequest.send method execution) after which the onTime delegate method (see above) is to be triggered. The value must be greater than 0. If no onTime callback is defined SecureXHR will attempt to abort an asynchronous request. Default value: 60000 (i.e. 60 seconds).
  • sameSite (boolean) - a flag which tells SecureXHR whether or not to force the same protocol, host and port for AJAX connections as the window.location object points to. It is advised to leave the parameter with its default value (true), as sometimes users may encounter problems when trying to open an XMLHttpRequest connection to an address like "http://examplesite.com" (no "www" prefix) from something like "http://www.examplesite.com" ("www" prefix used) or vice versa (both attempts would be blocked by the browser for security reasons). Setting this parameter to true will take care of the problem without the developer having to worry about it. When attempting cross-site requests this option should be set to false. Default value: true.
  • site (string) - the full name of a site (protocol, host name and port, if any) to which an AJAX connection is to be made. If sameSite parameter is set to true the site option will always be assigned the same protocol, host name and port as the current browser window. Default value: "http://localhost".
  • path (string) - the full name of a path which forms the second part of a URL address to which an AJAX connection is to be made. Default value: "/index.php".
  • noCache (boolean) - a flag which tells SecureXHR whether or not to take some extra measures to prevent request results from being cached by a web browser. If the option is set to true, a Unix timestamp (in milliseconds) and a request counter will be appended to the full URL address of a target site. Default value: true.
  • reqIdChar (string) - the name of a variable (appended to the full URL address of a target site) which stores a unique request ID if the noCache option (see above) is set to true. Default value: _ (an underscore).
  • method (string) - the name of a method which is to be employed by a request ("HEAD","GET","POST" and other methods accepted in XMLHttpRequest connections). Default value: "GET".
  • ifBadMet (integer) - the code of an action to be taken on discovering a connection method and connection data inconsistency, i.e. there is either no data to send and the "POST" (precisely: not "GET" or "HEAD") method is used or there is some data to be sent and the "GET" (or "HEAD") method is used. The options are:
    1. (getSecureXHRInterface().BAD_METHOD_IGNORE) no action will be taken on discovering such inconsistencies, but if the user submits some data to send and a connection method is set to "GET" (or "HEAD") SecureXHR will append the data to a target URL address if the data is either of the "string" type or a literal object in the form of { parameter_1 : value_1 , parameter_2 : value_2 } - such object will be URL encoded if the dataKV configuration option is set to true.
    2. (getSecureXHRInterface().BAD_METHOD_REPAIR) SecureXHR will force the "GET" method in case there is no data to send (and a method other than "GET" or "HEAD" is set) and the "POST" method in case there is some data to send (and a method set is either "GET" or "HEAD").
    3. (getSecureXHRInterface().BAD_METHOD_RESIGN) SecureXHR exec() method will return an error if the inconsistency is detected.
    Default value: 0 (getSecureXHRInterface().BAD_METHOD_IGNORE).
  • dataKV (boolean) - a flag which tells whether or not to treat data to be sent as a literal object of the { parameter_1 : value_1 , parameter_2 : value_2 } structure so that SecureXHR should convert it into a URI encoded string in the form of "parameter_1=value_1&parameter_2=value_2". Default value: true.
  • showDataRaw (boolean) - a flag which tells whether or not to include the original (initial, not URI encoded or otherwise modified) data in an object which is passed to the onDone delegate method. For more details see SecureXHR delegate functions below. Default value: false.
  • showDataURI (boolean) - a flag which tells whether or not to include data which has been sent (in the form of a URI encoded string) in an object which is passed to the onDone delegate method. This option applies only if the dataKV configuration option is set to true. For more details see SecureXHR delegate functions below. Default value: false.
  • getType (string) - the name of an expected response content type ("arraybuffer", "blob", "document", "json", "text" or "" - an empty string is the same as "text"). If an option other than "text" or "" is set SecureXHR will attempt to convert the response string into a proper JavaScript object instance (e.g. Document or JSON). Forcing a response type (other than "" or "text") is possible for asynchronous requests only. Default value: "text".
  • setHead (object) - a literal object in the form of { "Header-Name-A" : "Header-Value-A" , "Header-Name-B" : "Header-Value-B" } which defines request headers to be sent. If the method option is "POST" and the "Content-Type" header is not defined SecureXHR will set it automatically and assign it the value of "application/x-www-form-urlencoded; charset=UTF-8" (if window.document.characterSet or window.document.charSet defines a different charset it will be adopted accordingly). Default value: null.
  • getHead (boolean / array) - a flag which tells whether or not to retrieve response headers:
    • false - do not retrieve headers,
    • true - retrieve all headers as a string,
    • [ "Header-Name-A" , "Header-Name-B" ] - retrieve selected headers as an object in the form of { "Header-Name-A" : "Header-Value-A" , "Header-Name-B" : "Header-Value-B" }.
    Default value: false.
  • async (boolean) - a flag which tells whether or not a request should be asynchronous. The developer must be aware of dangers and limitations related to synchronous requests (no way to abort or time out a request, problems related to benchmarking or monitoring a request, the possibility of browser window freezing). Default value: true.
  • newXHR (boolean) - a flag which tells whether to create a new XMLHttpRequest object instance or use a singleton XMLHttpRequest instance to run a request. A singleton instance can handle only one request at a time so all other requests with the newXHR option set to true are placed on the pending list (requests using new instances can also be queued but only if the number of all concurrent requests reaches the limit defined by the maxOpen SecureXHR setup option - see above). For this reason, using new XHR instances for requests results in much faster performance. However, in some cases, relying on a singleton instance is preferable, e.g. when the developer wants to make sure that separate AJAX requests are run subsequently and not simultaneously. Default value: true.
  • token (any type) - a temporary (single cycle use) temporary password required to access those methods of the SecureXHR interface which make it possible to terminate a request or obtain information of its current state. If not supplied SecureXHR will generate a relatively strong password itself. Default value: null.
  • login and password (string) - a login and a password to be used with a request if accessing a target address requires authentication. In practice, this information is prepended to the host name, e.g. "http://login:password@examplesite.com/path/". Default value (in both cases): undefined.
  • cookies (boolean) - a flag which tells whether or not a cross-site Access-Control request should be made using credentials (cookies or authorization headers). The value applies to asynchronous requests only and does not affect same-site requests. For a cross-origin request to be successful (no matter what value is assigned to this option) the server has to respond with Access-Control-Allow-Origin header which may have either of the two values:
    • "*" (an asterisk) meaning that any site is allowed to access a given resource. However, using the "*" value won't be enough if a request is made with credentials, i.e. when the cookies flag is set to true;
    • a site (or a list of sites) allowed to access the content (e.g. "Access-Control-Allow-Origin: http://foo.example"). Such a solution should be applied if a request is made with credentials, i.e. when the cookies flag is set to true).
    Moreover, for this option to work, the server must respond with the "Access-Control-Allow-Credentials: true" header. Default value: false.

Interface methods (API)

SecureXHR interface is returned by a function of the name defined in the interfaceExposeFuncName option of the setup configuration object (see information on preparing the SecureXHR setup script above for more details), e.g.:

JavaScript
var sxhr = getSecureXHRInterface();

For security reasons the getSecureXHRInterface method should be deleted from the global scope as soon as no longer needed. The SecureXHR API consists of the following methods:

  • info() - obtain some information on SecureXHR
  • conf() - define a new request configuration (reusable)
  • exec() - execute a request (setup, open, send, get data)
  • stat() - get the current state of an ongoing request
  • stop() - try to abort an ongoing request
  • priv() - get access to some private methods (in the "testing" mode)

and constants:

  • BAD_METHOD_IGNORE - to be used with the ifBadMet request configuration option (see the the "Request configuration settings" section)
  • BAD_METHOD_REPAIR - see above
  • BAD_METHOD_RESIGN - see above

More detailed description with examples:

  • info( string type_of_information ) - used to retrieve some SecureXHR specific data like the SecureXHR version (supplying "version" as an argument) or SecureXHR setup process results (passing "setup" as an argument). Examples:
  • JavaScript
    var secureXhrVersion = sxhr.info( "version" );
    // returns a string in the form of "VERSION_NUMBER.YYYY.MM.DD", e.g.: "3.2013.06.09"
    JavaScript
    var secureXhrSetupResults = sxhr.info( "setup" );
    // returns an object with two fields ("used" and "failed") which contain deep copies of other objects:
    // "used" contains SecureXHR setup object with all possible options and values which have been adopted
    // "failed" contains only those setup options (and their values) which were defined by the developer but could not be applied
    // for instance, a potential result in some IE versions might be:
    /*
    {
    	"used" :
    	{
    		"interfaceExposeFuncName" :	"getXhrApi" ,
    		"deleteWindowXHR" :		false ,
    		"allowXHRViaActiveX" :		false ,
    		"onXHRPrototypeForged" :	null ,
    		"allowOtherSites" :
    		[
    			"http://www.mysite.com" ,
    			"http://mysite.com"
    		] ,
    		"modifyXHRToFilterSites" :	false ,
    		"modifyXHRToRequireToken" :	false ,
    		"maxOpen" :			7 ,
    		"rerunPendingMs" :		20 ,
    		"testing" :			false
    	} ,
    	"failed" :
    	{
    		"deleteWindowXHR" :		true ,
    		"modifyXHRToFilterSites" :	true ,
    		"modifyXHRToRequireToken" :	true ,
    	}
    }
    */
  • conf( object configuration_settings ) - used to create a new validated and reusable AJAX configuration set to be applied in multiple requests. The argument should be a literal object containing request configuration options and their values as described in the "Request configuration settings" section (see above). If an option is not defined it will be assigned its default value. The method returns an object containing three fields:
    • err which itself includes an object with three fields:
      • fatal - false if no request configuration errors encountered, otherwise true,
      • msg - null or a request configuration error message generated by SecureXHR,
      • at - null or the name of a request configuration option whose value is unacceptable,
    • inf which itself includes an object with one field:
      • cfgId - the ID assigned to a new request configuration set (it is later used as an argument of the exec method - see below) - in case of an error cfgId is given value 0 which points to the default request configuration options set,
    • cfg which itself includes an object containing the names all possible request configuration options and values which have been assigned to them.
    Examples:
  • JavaScript
    var myConfig = 
    {
    	"onDone"	: setAtomicTime ,
    	"wait"		: 3000 ,
    	"onTime"	: xhrTimedOut ,
    	"sameSite"	: false ,
    	"site"		: "http://www.getatomictime.com"
    	"path"		: "/getAsTimestamp.php" ,
    }
    
    var myConfigXhr = sxhr.conf( myConfig );
    // myConfigXhr possible structure:
    /*
    {
    	"err" :
    	{
    		"fatal"	: false ,
    		"msg"	: null ,
    		"at"	: null
    	} ,
    	"inf" :
    	{
    		"cfgId"	: 11
    	} ,
    	"cfg" :
    	{
    		"onDone"	: setAtomicTime ,
    		"wait"		: 3000 ,
    		"onTime"	: xhrTimedOut ,
    		"onStat"	: null ,
    		"onProg"	: null ,
    		"method"	: "GET" ,
    		"ifBadMet"	: 0 , // sxhr.BAD_METHOD_IGNORE
    		"site"		: "http://www.getatomictime.com" ,
    		"path"		: "/getAsTimestamp.php" ,
    		"sameSite"	: false ,
    		"cookies"	: false ,
    		"noCache"	: true ,
    		"reqIdChar"	: "_" ,
    		"async"		: true ,
    		"dataKV"	: true ,
    		"showDataURI"	: false ,
    		"showDataRaw"	: false ,
    		"getType"	: "text",
    		"setHead"	: null ,
    		"getHead"	: false ,
    		"token"		: null ,
    		"newXHR"	: true ,
    		"login"		: undefined ,
    		"password"	: undefined
    	}
    }
    */
    
    // check if the suggested configuration options were valid:
    if( myConfigXhr.err.fatal )
    {
    	alert( "An AJAX request configuration error encountered: " + myConfigXhr.err.msg );
    	return;
    }
    // no fatal error means that a new configuration set has been successfully created
  • exec( string | object data_to_send , integer configuration_settings_id , object additional_configuration_settings , string unique_request_name ) - used to execute an AJAX request (define XMLHttpRequest event listeners' functions, open a connection, send data, collect information etc.). The method takes three arguments:
    1. obligatory: data to be sent - if empty (null, {}, [], undefined, NaN, 0, "", false) it will be converted to null. Otherwise, the data should be an object or a URI encoded string. If the data is a literal object of the { parameter_1 : value_1 , parameter_2 : value_2 } structure and the dataKV configuration option is set to true SecureXHR will convert the object into a URI encoded string in the form of "parameter_1=value_1&parameter_2=value_2",
    2. obligatory: a configuration setting ID which defines parameters to be used with the request - this is the id found in an object ({ inf : { cfgId : VALUE } }) returned by the getSecureXHRInterface().conf() method (see the conf method description above for more details), however 0 should be used as the value if the default SecureXHR request configuration settings are to be used as basic settings for the request,
    3. optional: some additional temporary configuration settings (in the form of { option_1 : value_1 , option_2 : value_2 }) to be used with this particular request only, i.e. these settings overwrite values defined and created by the conf method (see the "Request configuration settings" section above for more details),
    4. optional: a unique request name whose purpose is to recognise and/or distinguish between various requests which might share the same "onDone" (or any other: "onStat", "onProg", "onTime") delegate function - this name is later to be found in the inf.name field of the object passed to the "onDone" method (the same is true for "onStat", "onProg" and "onTime").
    The function returns an object of the following structure:
    • err which itself includes an object with three fields:
      • fatal - a flag set to false if there are no additional request configuration errors and an XMLHttpRequest instance is obtained, otherwise true,
      • msg - a message with error details or null if no error encountered,
      • at - the name of a step at which the problem has been encountered, if any, otherwise null,
    • ids which itself includes an object with three fields:
      • id - the ID (the number / counter) of the current XMLHttpRequest object instance (a singleton instance has always ID 1),
      • cycle - the number of all requests (including the current one) which have been performed via the instance of a given ID (non-singleton instances will always have their cycle value 1 as they are destroyed as soon as the request has been dealt with),
      • token - a secret temporary (one cycle use) password needed to terminate a request or access information on its current state (see the token configuration option description above or information on stop() and stat() methods below for more details),
    Examples:
  • JavaScript
    //no data to send, using the same settings as defined by the conf() method:
    var xhrInitiated = sxhr.exec( null , myConfig.inf.cfgId );
    
    //the same as above, but a unique request name added as an alternative way to recognise the request when completed:
    var xhrInitiated = sxhr.exec( null , myConfig.inf.cfgId , null , "getFileDescr" );
    
    //no data to send, overwriting some of the settings defined by the conf() method:
    var xhrInitiated = sxhr.exec( null , myConfig.inf.cfgId , {
    	"sameSite" : true ,
    	"path"     : "/log_activity.php"
    } );
    
    //some data to send, using the same settings as defined by the conf() method:
    var xhrInitiated = sxhr.exec( { timezone : -2 } , myConfig.inf.cfgId );
    
    //some data to send, overwriting some of the settings defined by the conf() method:
    var xhrInitiated = sxhr.exec( { "img_id" : 4253 } , myConfig.inf.cfgId , {
    	"getType"  : "json" ,
    	"path"     : "/get_img_by_id.php"
    } );
    
    //using the default request settings as the basic settings (configuration ID is 0):
    //some data to send, overwriting some of the default settings:
    var xhrInitiated = sxhr.exec( { "img_id" : 4253 } , 0 , {
    	"getType"  : "json" ,
    	"path"     : "/get_img_by_id.php"
    } );
    
    //possible xhrInitiated structure:
    /*
    {
    	"err" :
    	{
    		"fatal"	: false ,
    		"msg"	: null ,
    		"at"	: null
    	} ,
    	"ids" :
    	{
    		"id"	: 11 ,
    		"cycle" : 1 ,
    		"token" : 275120083634.0311
    	}
    }
    */
    
    //checking whether a request has been initiated or not:
    if( xhrInitiated.err.fatal )
    {
    	alert( "AJAX request could not be initiated. Error message: " + xhrInitiated.err.msg );
    }
  • stat( integer xhr_instance_id , integer xhr_instance_cycle_nr , any xhr_instance_token ) - used to obtain information on the current state of an ongoing request. The method takes three arguments which all can be obtained from an object returned by the getSecureXHRInterface().exec() method (see above):
    1. obligatory: the ID / number / counter of an XMLHttpRequest instance - this is the id found in an object ({ ids : { id : VALUE } }) returned by the exec method,
    2. obligatory: the number / counter of cycles an XMLHttpRequest instance has been used to run a request - this is the cycle number found in an object ({ ids : { cycle : VALUE } }) returned by the exec method,
    3. obligatory: a secret token associated with a given XMLHttpRequest instance cycle - this is the token found in an object ({ ids : { token : VALUE } }) returned by the exec method,
    The function returns an object of the following structure:
    • xhr which itself includes an object with one field:
      • readyState - the current readyState property value of an ongoing request - normally the value is an integer (1, 2, 3 or 4), but if a request is not running it will hold value 0,
    • inf which itself includes an object with one fields:
      • maxStage - the current stage of an ongoing request as defined by SecureXHR - normally the value is one of the set: "pending", "setting", "sending", "loading", "closing". However, if a request is not running it will hold value "" (an empty string).
    States and stages are registered typically in the following order:
    1. readyState 0: marked by SecureXHR right after an XMLHttpRequest instance is created and/or ready
    2. "pending" stage: recorded not long after readyState 0 (usually the same millisecond) just before a request is either placed on the pending list or prepared for execution (binding event listeners' methods etc.)
    3. "setting" stage: recorded as soon as a request setup process begins (preparing for execution) - this might happen in the same millisecond as the two previous states/stages if there are no requests on the pending list
    4. readyState 1: recorded right after the XMLHttpRequest.open() method is invoked - might happen in the same millisecond as the "setting" stage if the browser is fast enough
    5. "sending" stage: recorded just before the XMLHttpRequest.send() method is invoked - usually takes place in the same millisecond as the readyState 1 is recorded
    6. "loading" stage: recorded as soon as the XMLHttpRequest.onloadstart event is triggered or right after the XMLHttpRequest.send() method is invoked - often takes place in the same millisecond as the "sending" stage, especially if there is no data to send
    7. readyState 2: recorded as soon as response headers are received from the server
    8. readyState 3: recorded as soon as some partial response data is received from the server
    9. readyState 4: recorded as soon as the request is complete and response data is available (this state is not always reached in some browsers in case of certain errors)
    10. "closing" stage: recorded as soon as the request has been completed and response data is about to be parsed and converted, if required - usually takes place in the same millisecond as readyState 4 (if reached)
    Example:
  • JavaScript
    var currentXhrState = sxhr.stat( xhrInitiated.ids.id , xhrInitiated.ids.cycle , xhrInitiated.ids.token );
    
    if( currentXhrState.xhr.readyState === 1 && currentXhrState.inf.stage === "loading" )
    {
    	// try and abort the request if it is still not completed within 10 seconds:
    	setTimeout( function(){
    		sxhr.stop( xhrInitiated.ids.id , xhrInitiated.ids.cycle , xhrInitiated.ids.token )
    	} , 10000 );
    }
  • stop( integer xhr_instance_id , integer xhr_instance_cycle_nr , any xhr_instance_token ) - used to try to terminate an ongoing request. The method takes three arguments which all can be obtained from an object returned by the getSecureXHRInterface().exec() method (see above). These are the very same arguments which are necessary to invoke the getSecureXHRInterface().stat() method (see the description above for more details). The function returns true if a request termination is possible and has been started, otherwise the function returns false. The method is unsuccessful in either of the three cases:
    • a request is synchronous
    • the "loading" stage has not yet been reached
    • the request has been completed
    Example:
  • JavaScript
    var xhrTerminated = sxhr.stop( xhrInitiated.ids.id , xhrInitiated.ids.cycle , xhrInitiated.ids.token );
    
    if( xhrTerminated )
    	alert( "The request has been aborted" );
    else
    	alert( "Could not abort the request" );
  • priv( string secure_xhr_private_property_type ) - used to get access to some SecureXHR private properties which may be necessary for debugging purposes. By default, this method returns undefined. However, if the _SecureXHRIni.testing option is set to true (see the "Preparing the SecureXHR setup script" section for more details) the method returns a number of private SecureXHR properties, depending on their name defined in the argument:
    • "settingsGroups" - an array containing all request configuration sets. The default request configuration settings are stored at index 0, other configuration settings are stored at indices of greater values. Index values are typically obtained via getSecureXHRInterface().conf( object ).inf.cfgId;
    • "xhrInstances" - an array containing all existing SexureXHR instances. The singleton instance, if created, is stored at index 1, other instances are stored at indices greater than 1 (they are deleted as soon as the request has been done with so there will be typically gaps in the array). Index values are typically obtained via getSecureXHRInterface().exec( object , integer , object ).ids.id. Each index of the xhrInstances array (in case of existing instances) contains an object with two fields:
      • xhr - at which an XMLHttpRequest instance object is stored;
      • an instance cycle number - which stores an object containing all the necessary information related to a given request (this is the cycle number which is typically obtained via getSecureXHRInterface().exec( object , integer , object ).ids.cycle);
    • "runningXhrsNr" - the number of currently open XMLHttpRequest connections;
    • "singleton" - the object containing information on an XMLHttpRequest singleton instance. It has the following fields:
      • cycles - the number of times the singleton instance has been used to perform a request (0 if no singleton instance created);
      • current - the number of the current singleton instance cycle (0 if no currently running request using the singleton instance);
      • next - the number of the next cycle of the singleton instance waiting to be dealt with;
      • pending - an object containing all pending cycles' numbers waiting for their execution via the singleton instance;
    • "xhrOpenToken" - the value of a secret token to be used as an additional argument of the XMLHttpRequest.open() method (required if the _SecureXHRIni.modifyXHRToRequireToken option is set to true - see the "Preparing the SecureXHR setup script" section for more details);
    • "xhrSeq" - the ID of the most recently created non-singleton XMLHttpRequest instance.
    Examples:
  • JavaScript
    // get the most recent XHR ID:
    var lastXhrId = sxhr.priv( "xhrSeq" );
    
    // get the object containing all usable instances:
    var allXhrs = sxhr.priv( "xhrInstances" );
    
    // check if the instance of the most recent ID is still in use:
    if( allXhrs[ lastXhrId ] )
    {
    	// Display all the details related to the request:
    	// (non-singleton instances always have their cycle value equal 1):
    	console.log( allXhrs[ lastXhrId ]["1"] );
    }

SecureXHR delegate functions

Request configuration settings (see above) allow to define the following delegate functions:

  • "onDone" - obligatory, to be triggered as soon as the request has been done with or terminated
  • "onProg" - optional, to be triggered as soon as some computable amount of data has been uploaded or downloaded
  • "onStat" - optional, to be triggered as soon as a request changes its ready state or stage as defined by SecureXHR
  • "onTime" - optional, to be triggered as soon as the request has been timed out

More detailed description:

  • "onDone" - the most important delegate function - it is triggered as soon as the request has been dealt with. The method is passed just one parameter - a literal object consisting of the following fields:
    • cfg - configuration request settings applied to the request (see the "Request configuration settings" section and the SecureXHR interface conf() method description);
    • err - information on potential errors encountered while preparing and performing the request:
      • fatal - false if the request ended in success, true if there occurred a critical error resulting in failure
      • msg - null or a request runtime error message generated either by XMLHttpRequest or by SecureXHR
      • at - null or the name of an XMLHttpRequest method which caused the problem
      • type - null or one of the following error types:
        • "error" - an error (other than "abort" and "timeout") generated by XMLHttpRequest
        • "exception" - an unexpected error generated by SecureXHR
        • "timeout" - information about the request having been timed out
        • "abort" - information about the request having been aborted
        • "parsererror" - information about problems converting response data to a desired response type (usually "xml" or "json")
    • ids - values (id, cycle and token) which help identify and access the request (see the SecureXHR interface exec() method description)
    • inf - additional information about the request:
      • name (string) - an optional request name which might be useful to recognise and/or distinguish various requests which might share the same "onDone" delegate function (this is the name which is the optional 4th argument of the getSecureXHRInterface().exec() method)
      • cfgId (object) - a request configuration settings ID which served as a basic configuration for the request (its values may have been overwritten via the exec() method)
      • noData (boolean) - whether or not SecureXHR passed null as the argument of the XMLHttpRequest.send() method (even if the developer supplied some data in the form of a literal object it may have been URI encoded and appended to the URL address if the "GET" method was chosen, the dataKV request configuration option was set to true and the ifBadMet was set to 0, i.e. getSecureXHRInterface().BAD_METHOD_IGNORE)
      • data (object | string) - original data to have been sent which was supplied as the first argument of the exec() method; null if the showDataRaw request configuration option has been set to false
      • dataURI (string) - data to have been sent in the form of a URI encoded string; null if either the showDataURI or the dataKV request configuration options have been set to false
      • url (string) - the complete URL address which was passed as an argument to the XMLHttpRequest.open() method
      • autoHeaders (object) - request headers (and their values), if any, which were automatically set by SecureXHR
      • resHeaders (string | object) - response headers; this property's value depends on the getHead request configuration option
      • states (array) - an array with indices of 0 to 4 which correspond to the 5 XMLHttpRequest ready states whose values are Unix timestamps recorded when the request passed through the subsequent states
      • stages (object) - an object with indices which correspond to request stages recognized by SecureXHR ("pending", "setting", "sending", "loading", "closing") whose values are Unix timestamps recorded when the request passed through the subsequent stages
      • maxStage (string) - the maximum stage reached during the request (see the previous point)
      • uploaded (integer) - the number of bytes uploaded during the request (measured if the "onProg" delegate function is set)
      • downloaded (integer) - the number of bytes downloaded during the request (excluding response headers)
      • timeoutId (integer) - the ID returned by the setTimeout method which is invoked by SecureXHR to implement the request timeout functionality; if the value is greater than 0 it means that the request had been completed before the time when the function defined in the setTimeout method was to be triggered
      • requestId (integer) - the internal request counter used by SecureXHR, employed primarily to effectively implement the no-cache mechanism
    • xhr - contains copies of some properties of the XMLHttpRequest instance responsible for performing the request:
      • readyState
      • response
      • responseType
      • status
      • statusText
    Example (here all requests share the same delegate function triggered once they have been completed - that's why a container with request ids+cycles and their associated names is created -, but the developer can choose to define different "onDone" methods for various requests):
  • JavaScript
    //create a container to associate XHR ids (and cycles) with some script actions:
    var xhrActions = {};
    
    function getTopProd()
    {
    	//use default settings, just change some parameters:
    	var xhrInitiated = sxhr.exec( null , 0 , {"onDone":xhrDone, "path":"/xhr/action_id=374"} );
    	xhrActions[ xhrInitiated.ids.id + ":" + xhrInitiated.ids.cycle ] = "getTopRatedProduct";
    }
    
    function discountProd( productId, discountPercent )
    {
    	//similarly, use the same "onDone" delegate function:
    	var xhrInitiated = sxhr.exec(
    		{ prodId=productId , discPerc=discountPercent } ,
    		0 ,
    		{"onDone":xhrDone, "path":"/xhr/action_id=24"}
    	);
    	xhrActions[ xhrInitiated.ids.id + ":" + xhrInitiated.ids.cycle ] = "discountProduct";
    }
    
    getTopProd();
    
    function xhrDone( respObj )
    {
    	// distinguish requests on the basis of their ids and cycles:
    	//if the developer had defined the 4th argument in each exec() method...
    	//... requests could be distinguished on the basis of the respObj.inf.name property:
    	switch( xhrActions[ respObj.ids.id + ":" + respObj.ids.cycle ] )
    	{
    		case "getTopRatedProduct":
    			if( respObj.err.fatal )
    			{
    				alert( "Could not obtain the top rated product (error: " + respObj.err.msg + ")" );
    				return;
    			}
    			//else:
    
    			// put the top product on a 15 percent discount:
    			discountProd( respObj.xhr.response , 15 );
    			break;
    		case "discountProduct":
    			if( respObj.err.fatal )
    			{
    				alert( "Could put the top rated product on a discount (error: " + respObj.err.msg + ")" );
    				return;
    			}
    			break;
    	}
    }
  • "onStat" - it is triggered as soon as the request has changed its ready stage or stage (as defined by SecureXHR: "pending", "setting", "sending", "loading", "closing"). The method is passed just one parameter - a literal object consisting of the following fields (a reduced version of the object passed to the "onDone" delegate function - see its description for more details):
    • ids - values (id, cycle and token) which help identify and access the request (see the SecureXHR interface exec() method description)
    • inf - additional information about the request:
      • name (string) - an optional request name which might be useful to recognise and/or distinguish various requests which might share the same "onStat" delegate function (this is the name which is the optional 4th argument of the getSecureXHRInterface().exec() method)
      • maxStage (string) - the maximum stage reached during the request
    • xhr - contains copies of some properties of the XMLHttpRequest instance responsible for performing the request:
      • readyState (integer)
    Example:
  • JavaScript
    var inputWord = document.getElementById("search_word").value;
    var ajaxInfoLabel = document.getElementById("search_info");
    
    //use default settings, just change some parameters:
    var xhrIni = sxhr.exec(
    	{word:inputWord, lang:"English"} ,
    	0 ,
    	{"onDone":xhrSerachComplete, "onStat":xhrInfo, "path":"/search.php"} ,
    	"Searching for the word '" + inputWord + "'"
    );
    
    function xhrInfo( infoObj ) {
    	ajaxInfoLabel.innerHTML = infoObj.inf.name + " (stage: " + infoObj.inf.maxStage + ")";
    	//the output will be something like: "Searching for the word 'heckuva' (stage: loading)"
    };
  • "onProg" - it is triggered as soon as some computable amount of data has been uploaded or downloaded during an asynchronous request. The method is passed just one parameter - a literal object consisting of the following fields:
    • ids - values (id, cycle and token) which help identify and access the request (see the SecureXHR interface exec() method description)
    • inf - additional information about the request:
      • name (string) - an optional request name which might be useful to recognise and/or distinguish various requests which might share the same "onProg" delegate function (this is the name which is the optional 4th argument of the getSecureXHRInterface().exec() method)
      • lengthComputable (boolean) - whether or not the total size of uploaded or downloaded data is known
      • total (integer) - the total size of an uploaded or downloaded file (in bytes)
      • loaded (integer) - the amount of bytes which have been uploaded or downloaded so far during the request
      • download (boolean) - whether it is an upload or download process
    Example:
  • JavaScript
    function submitCanvasImg()
    {
    	var imgUrlString = imgCanvas.toDataURL("image/png");
    
    	sxhr.exec(
    		imgUrlString ,
    		0 ,
    		{
    			"method" : "POST" ,
    			"path" : "/save_new_img.php" ,
    			"onDone" : function( responseObj )
    			{
    				if( responseObj.err.fatal || !responseObj.xhr.response )
    					alert( "Failed to save the image on the server" );
    				else
    					alert( "The image has been successfully saved" );
    			}
    			"onProg" : function( progressObj )
    			{
    				// do not report any download but only upload process:
    				if( progressObj.inf.download )
    					return;
    				setProgressBarPercentage( progressObj.inf.loaded * 100 / imgUrlString.length );
    			}
    		}
    	);
    }
  • "onTime" - it is triggered if an asynchronous request has not been completed within the number of milliseconds defined in the wait request configuration option. If the browser is busy with executing some consuming JavaScript code the "onTime" function may occasionally not be invoked despite the timeout period having been reached - this might happen especially on slower machines. The method is passed just one parameter - a literal object consisting of the following fields:
    • ids - values (id, cycle and token) which help identify and access the request (see the SecureXHR interface exec() method description)
    • inf - additional information about the request:
      • name (string) - an optional request name which might be useful to recognise and/or distinguish various requests which might share the same "onTime" delegate function (this is the name which is the optional 4th argument of the getSecureXHRInterface().exec() method)
    • cfg - some request configuration options:
      • wait (integer) - the number of milliseconds (counting from the time of the XMLHttpRequest.send method execution) after which the "onTime" delegate method is to be triggered.
    Example:
  • JavaScript
    //check whether a remote host is available
    // if not - the value is false
    // if yes - the value is the amount of milliseconds which passed between sending data and closing the connection
    // the value is to be passed to a callback function which should continue the process
    function checkRemoteHost( hostName , continueAtCallback )
    {
    	var ini = sxhr.exec(
    		null ,
    		0 ,
    		{
    			"method" : "HEAD" ,
    			"path" : "" ,
    			"sameSite" : false ,
    			"site" : hostName ,
    			"wait" : 1000 ,
    			"onDone" : function( responseObj )
    			{
    				if( responseObj.err.fatal )
    					continueAtCallback( false );
    				else
    					continueAtCallback( responseObj.inf.stages.closing - responseObj.inf.stages.sending );
    			}
    			"onTime" : function( timeoutObj )
    			{
    				// check the current ready state of the request
    				var statObj = sxhr.stat( ini.ids.id , ini.ids.cycle , ini.ids.token );
    				var stopped = false;
    				// make the user decide whether to keep waiting or to abort the request
    				if( confirm( "Checking host '" + hostName +
    					"' - current ready state: " + statObj.xhr.readyState + ". Terminate?") )
    				{
    					stopped = sxhr.stop( ini.ids.id , ini.ids.cycle , ini.ids.token );
    				}
    				// if the user decided to keep waiting or the request could not be stopped:
    				if( !stopped )
    				{
    					// trigger the same anonymous function again
    					setTimeout( function(){ arguments.callee() } , 1000 );
    				}
    			}
    		}
    	);
    
    	if(ini.err.fatal)
    		throw new Error( "Could not initialize an AJAX request. Error message: " + ini.err.msg );
    }

    Browser compatibility

    SecureXHR works perfectly with most current browser versions. However, some browsers do not support all functionalities offered by SecureXHR, like overwriting XMLHttpRequest object prototype methods or reporting on data upload progress. This is especially true of Internet Explorer and many older versions of popular browsers. Nevertheless, SecureXHR is still usable with older browsers (most unit tests end in success):

    • Mozilla Firefox 3.6.17 - passes 131 out of 135 unit tests - 97%
    • Google Chrome 13 - passes 135 out of 135 unit tests - 100%
    • Internet Explorer 7 - passes 125 out of 135 unit tests - 93%
    • Safari 4 - passes 131 out of 135 unit tests - 97%
    • Opera 10.61 - passes 127 out of 135 unit tests - 94%

    SecureXHR unit tests files and instructions on running the test are included in the complete SecureXHR package.

    History

    2013.06.09 - version 3.2013.06.09

    • setting the default request site option to the window site name
    • placing analysis of the sameSite option before the site option in order to overwrite the site parameter if necessary
    • correcting the site option validation
    • adding the reqIdChar request configuration option (in order to prevent passing a numeric request ID as a parameter name in a URL string as numeric names are not allowed in some environments, e.g. Joomla)
    • adding examples showing usage of the default request configuration settings

    2013.04.13 - version 2.2013.04.13

    • effectively removing the XMLHttpRequest object from the global scope in Google Chrome, if required
    • SecureXHR constants added: BAD_METHOD_IGNORE, BAD_METHOD_REPAIR, BAD_METHOD_RESIGN (to be used with the ifBadMet request configuration option)
    • removing minor errors from the code and the documentation

    2013.03.08 - version 1.2013.03.08

    • first release
    <!-- End Article -->

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


    Written By
    Web Developer
    Poland Poland
    This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

    Comments and Discussions

     
    GeneralMy vote of 4 Pin
    Prasad Khandekar15-Apr-13 1:34
    professionalPrasad Khandekar15-Apr-13 1:34 
    GeneralRe: My vote of 4 Pin
    Piotr Gałecki15-Apr-13 2:30
    Piotr Gałecki15-Apr-13 2:30 
    GeneralRe: My vote of 4 Pin
    Prasad Khandekar15-Apr-13 2:44
    professionalPrasad Khandekar15-Apr-13 2:44 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.