Newer
Older
Lloyd Hilaiel
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla BrowserID.
*
* The Initial Developer of the Original Code is Mozilla.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* this is a small standalone abstraction which lets scripts be
* browserid WSAPI clients. It handles CSRF token fetching and
* extraction/resending of cookies. It also allows one to have
* any number of "client contexts" which are just objects, and lets
* you simulated different simultaneous sessions.
*/
const
http = require('http'),
https = require('https'),
Lloyd Hilaiel
committed
url = require('url'),
querystring = require('querystring');
Lloyd Hilaiel
committed
function injectCookies(ctx, headers) {
if (ctx.cookieJar && Object.keys(ctx.cookieJar).length) {
headers['Cookie'] = "";
for (var k in ctx.cookieJar) {
headers['Cookie'] += k + "=" + ctx.cookieJar[k];
}
}
}
function extractCookies(ctx, res) {
if (ctx.cookieJar === undefined) ctx.cookieJar = {};
if (res.headers['set-cookie']) {
res.headers['set-cookie'].forEach(function(cookie) {
var m = /^([^;]+)(?:;.*)$/.exec(cookie);
if (m) {
var x = m[1].split('=');
ctx.cookieJar[x[0]] = x[1];
}
});
}
}
exports.clearCookies = function(ctx) {
if (ctx && ctx.cookieJar) delete ctx.cookieJar;
if (ctx && ctx.csrf) delete ctx.csrf;
};
Lloyd Hilaiel
committed
exports.get = function(cfg, path, context, getArgs, cb) {
Lloyd Hilaiel
committed
// parse the server URL (cfg.browserid)
var uObj;
var meth;
try {
uObj = url.parse(cfg.browserid);
meth = uObj.protocol === 'http:' ? http : https;
} catch(e) {
cb(false);
return;
}
var headers = { };
injectCookies(context, headers);
Lloyd Hilaiel
committed
if (typeof getArgs === 'object')
path += "?" + querystring.stringify(getArgs);
Lloyd Hilaiel
committed
meth.get({
host: uObj.hostname,
port: uObj.port,
path: path,
headers: headers
}, function(res) {
extractCookies(context, res);
var body = '';
res.on('data', function(chunk) { body += chunk; })
.on('end', function() {
cb({code: res.statusCode, headers: res.headers, body: body});
});
}).on('error', function (e) {
cb();
});
};
function withCSRF(cfg, context, cb) {
Lloyd Hilaiel
committed
if (context.csrf) cb(context.csrf);
Lloyd Hilaiel
committed
else {
Lloyd Hilaiel
committed
exports.get(cfg, '/wsapi/csrf', context, undefined, function(r) {
if (r.code === 200 && typeof r.body === 'string')
context.csrf = r.body;
Lloyd Hilaiel
committed
cb(context.csrf);
Lloyd Hilaiel
committed
});
}
}
exports.post = function(cfg, path, context, postArgs, cb) {
Lloyd Hilaiel
committed
withCSRF(cfg, context, function(csrf) {
Lloyd Hilaiel
committed
// parse the server URL (cfg.browserid)
var uObj;
var meth;
try {
uObj = url.parse(cfg.browserid);
meth = uObj.protocol === 'http:' ? http : https;
} catch(e) {
cb(false);
return;
}
var headers = {
'content-type': 'application/x-www-form-urlencoded'
};
injectCookies(context, headers);
if (typeof postArgs === 'object') {
Lloyd Hilaiel
committed
postArgs['csrf'] = csrf;
Lloyd Hilaiel
committed
body = querystring.stringify(postArgs);
}
var req = meth.request({
host: uObj.hostname,
port: uObj.port,
path: path,
headers: headers,
method: "POST"
}, function(res) {
extractCookies(context, res);
var body = '';
res.on('data', function(chunk) { body += chunk; })
.on('end', function() {
cb({code: res.statusCode, headers: res.headers, body: body});
});
}).on('error', function (e) {
cb();
});
req.write(body);
req.end();
});
};