Skip to content

Instantly share code, notes, and snippets.

@snj14
Created August 24, 2008 12:24
Show Gist options
  • Save snj14/6981 to your computer and use it in GitHub Desktop.
Save snj14/6981 to your computer and use it in GitHub Desktop.
XHR
// XHR -- XMLHttpRequest
// Argmunets
//
// url
// method
// data
// headers
// Accept
// Referer
// User-Agent etc...
// onload
// onerror
// onreadeychange
// async (default: true)
// Arguments of onload/onerror
//
// channel
// responseText
// responseHeaders
// requestHeaders
// status
// finalUrl
// etc...
// TODO:
// authentication
// Example
/*
var opt = {
url : 'http://localhost/index.rdf'
, method : 'head'
, headers : {
'Referer' : 'http://example.com/referer'
, 'User-Agent' : 'Mozilla/5.0 foo bar baz'
}
, onload : function(response){
alert('onload \n\n' + response.responseXML)
alert('onload \n\n' + response.requestHeaders)
}
, onerror : function(response){
alert('onerror \n\n' + response.responseXML)
}
}
XHR(opt);
*/
function XHR({method,url,headers,data,onload,onerror,onreadystatechange,overrideMimeType,async}){
const Ci = Components.interfaces;
const Cc = Components.classes;
async = (typeof async == 'undefined') ? true : !!async;
var cancel = false;
var xhr = new XMLHttpRequest();
xhr.mozBackgroundRequest = async;
xhr.open(method || (method = data ? "post" : "get"), url, async);
if(overrideMimeType) xhr.overrideMimeType(overrideMimeType);
xhr.onload = function(){
addHeadersInfo();
if(onload && !cancel) onload(xhr);
};
xhr.onerror = function(){
addHeadersInfo();
if(onerror && !cancel) onerror(xhr);
};
if(method == "post") xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var referrer;
if(headers){
for(var header in headers){
if(headers.hasOwnProperty(header)){
if(header == "Referer"){
referrer = headers[header];
}else{
xhr.setRequestHeader(header, headers[header]);
}
}
}
}
if(referrer){
var RefererSetter = {
observe: function(aSubject, aTopic, aData){
if ((aTopic == 'http-on-modify-request')
&& (typeof Components != "undefined")) {
aSubject.QueryInterface(Ci.nsIHttpChannel);
if(aSubject.originalURI.spec == url){
observer.removeObserver(RefererSetter, aTopic, false);
aSubject.setRequestHeader('Referer',referrer,false);
}
}
}
};
var observer = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observer.addObserver(RefererSetter, "http-on-modify-request", false);
}
function addHeadersInfo(){
if(!xhr.channel.contentCharset && !overrideMimeType){ // wrong charset
var mimeType = getEncoding(xhr.responseText);
if(mimeType){
cancel = true;
XHR({ method: method
, url: url
, headers: headers
, data: data
, onload: onload
, onerror: onerror
, onreadystatechange: onreadystatechange
, overrideMimeType: mimeType
, async: async
});
return;
}
}
xhr.channel.QueryInterface(Ci.nsIHttpChannel);
xhr.responseHeaders = {};
xhr.channel.visitResponseHeaders({visitHeader: function(aHeader,aValue){xhr.responseHeaders[aHeader] = aValue}});
xhr.requestHeaders = {};
xhr.channel.visitRequestHeaders({visitHeader: function(aHeader,aValue){xhr.requestHeaders[aHeader] = aValue}});
xhr.finalUrl = xhr.channel.URI.spec;
}
function getEncoding(text){
var matched = text.match(new RegExp("<meta.+?http-equiv.+?Content-Type.+?content=([\"'])([^\\1]+?)\\1",'i'));
return (matched && !matched[2].match(/UTF-8/i) && matched[2]);
}
xhr.send(data || null);
return xhr;
}
XHR.Test = function(){
XHR({
// url: "http://white.s151.xrea.com/wiki/index.php?cmd=edit&page=FrontPage" // test 401
url: "http://white.s151.xrea.com/blog/"
, onload: function(response){log('XHR load',response)}
, onerror: function(response){log('XHR error',response)}
, headers: {'Referer':'http://example.org/referrer'}
});
}
// XHR.JSDeferred ---
XHR.JSDeferred = function(opt){
var d = Deferred();
var stop = false;
try{
opt.onload = function(res){
if(stop) return;
d.call(res);
}
opt.onerror = function(res){ d.fail(res); }
var xhr = XHR(opt);
d.canceller = function(){ xhr.abort(); }
}catch(e){
d.fail(e);
}
return d;
}
XHR.JSDeferred.Test = function(){
XHR.JSDeferred({ url: "http://white.s151.xrea.com/blog/"
, headers: {'Referer':'http://example.org/referrer'}
})
.next(function(d){
log('XHR.JSDeferred ', d);
})
}
XHR.JSDeferred.ParallelTest = function(){
Deferred.parallel({
root: XHR.JSDeferred({ url:"http://white.s151.xrea.com/", headers:{'Referer':'http://example.org/referrer'}})
, blog: XHR.JSDeferred({ url:"http://white.s151.xrea.com/blog/", headers:{'Referer':'http://example.org/referrer'}})
, wiki: XHR.JSDeferred({ url:"http://white.s151.xrea.com/wiki/", headers:{'Referer':'http://example.org/referrer'}})
})
.next(function(d){
log('XHR.JSDeferred.ParallelTest ', d);
})
}
// XHR.Arrow ---
XHR.Arrow = function(opt){
return Arrow.fromCPS(function(x, k){
var stop = false;
try {
opt.onload = function(res){
if(stop) return;
k(res);
}
opt.onerror = function(res){
k(Arrow.Error(xhr));
}
XHR(opt);
} catch (e) {
k(Arrow.Error(e));
}
this.cancel = function() { stop = true };
});
}
XHR.Arrow.Test = function(){
var arrow = ((XHR.Arrow({url: "http://white.s151.xrea.com/blog/"
, headers: {'Referer':'http://example.org/referrer'}
}))
['>>>']
(Arrow.fromCPS(function(x, k){
log('XHR.Arrow ', x)
})));
arrow.run();
}
// XHR.ArrowParallel ---
XHR.ArrowParallel = function(opts){
var arrow = new Arrow;
arrow.cpsFunction = function(x, k) {
var arrows = this.arrows;
var results = [];
var count = arrows.length;
for (var i = 0; i < arrows.length; i++) {
with ({ i: i }) {
arrows[i].callCPS(x, function(y) { results[i] = y; if (!--count) k(results) });
}
}
}
arrow.type = '&&&';
arrow.arrows = opts.map(function(opt){
return XHR.Arrow(opt);
});
return arrow;
}
XHR.ArrowParallel.Test = function(){
((XHR.ArrowParallel([{url: "http://white.s151.xrea.com/"},
{url: "http://white.s151.xrea.com/wiki/"},
{url: "http://white.s151.xrea.com/blog/"}]))
['>>>']
(Arrow.fromCPS(function(x, k){
log('xhr response list:', x)
}))).run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment