From abf71a81ff064a9efe9e1dcc79cc568a84c23e54 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 4 Aug 2014 10:11:12 -0700 Subject: [PATCH] paypro: use an http proxy to handle self-signed certs - probably not a good idea. --- app.js | 79 ++++++++++++++++++-- js/models/core/Wallet.js | 154 +++++++++++++++++++++++++++------------ package.json | 3 +- 3 files changed, 181 insertions(+), 55 deletions(-) diff --git a/app.js b/app.js index 7c0f08a4d..ba4043c92 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ var express = require('express'); var http = require('http'); var app = express(); +var request = require('request'); app.use('/', express.static(__dirname + '/')); app.get('*', function(req, res) { @@ -12,29 +13,95 @@ app.start = function(port, callback) { app.set('port', port); app.use(express.static(__dirname)); + // XHR'ing from a site with a self-signed + // cert on the same port seems to work. if (process.env.USE_HTTPS) { - process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; var path = require('path'); + var bc = path.dirname(require.resolve('bitcore/package.json')); - // var fs = require('fs'); - // var server = require('https').createServer({ - // key: fs.readFileSync(bc + '/test/data/x509.key'), - // cert: fs.readFileSync(bc + '/test/data/x509.crt') - // }); var pserver = require(bc + '/examples/PayPro/server.js'); + pserver.removeListener('request', pserver.app); + pserver.on('request', function(req, res) { if (req.url.indexOf('/-/') === 0) { return pserver.app(req, res); } return app(req, res); }); + pserver.listen(port, function() { callback('https://localhost:' + port); }); + return; } + if (process.env.USE_REQUEST_PROXY) { + // Disable strict SSL + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; + + // NOTE: Should be .use(), but the router is invoked + // to early above, which puts it on the stack. + // Only allow proxy requests from localhost + app.post('/_request', function(req, res, next) { + var address = req.socket.remoteAddress; + if (address !== '127.0.0.1' && address !== '::1') { + res.statusCode = 403; + res.end(); + return; + } + return next(); + }); + + // NOTE: Should be .use(), but the router is invoked + // to early above, which puts it on the stack. + app.post('/_request', function(req, res, next) { + var buf = ''; + + req.setEncoding('utf8'); + + req.on('error', function(err) { + try { + req.socket.destroy(); + } catch (e) { + ; + } + }); + + req.on('data', function(data) { + buf += data; + }); + + req.on('end', function(data) { + if (data) buf += data; + try { + req.reqOptions = JSON.parse(buf); + } catch (e) { + req.reqOptions = {}; + } + return next(); + }) + }); + + app.post('/_request', function(req, res, next) { + var options = req.reqOptions; + if (options.body) { + options.body = new Buffer(options.body, 'hex'); + } + request(options, function(err, response, body) { + if (err) { + res.statusCode = 500; + res.setHeader('Content-Type', 'text/plain; charset=utf-8'); + res.end(err.stack + ''); + return; + } + res.writeHead(response.statusCode, response.headers); + res.end(body); + }); + }); + } + app.listen(port, function() { callback('http://localhost:' + port); }); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 8e635cb56..9c556da99 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -1600,61 +1600,119 @@ G.$http = G.$http || function $http(options, callback) { var req = options; req.headers = req.headers || {}; - req.body = req.body || {}; + req.body = req.body || req.data || {}; - if (typeof XMLHttpRequest !== 'undefined') { - var xhr = new XMLHttpRequest(); - xhr.open(method, uri, true); + var xhr = new XMLHttpRequest(); + xhr.open(method, uri, true); - Object.keys(options.headers).forEach(function(key) { - var val = options.headers[key]; - if (key === 'Content-Length') return; - if (key === 'Content-Transfer-Encoding') return; - xhr.setRequestHeader(key, val); - }); + Object.keys(req.headers).forEach(function(key) { + var val = req.headers[key]; + if (key === 'Content-Length') return; + if (key === 'Content-Transfer-Encoding') return; + xhr.setRequestHeader(key, val); + }); - // For older browsers (binary data): - // xhr.overrideMimeType('text/plain; charset=x-user-defined'); + // For older browsers (binary data): + // xhr.overrideMimeType('text/plain; charset=x-user-defined'); - // Newer browsers (binary data): - // xhr.responseType = 'arraybuffer'; + // Newer browsers (binary data): + // xhr.responseType = 'arraybuffer'; - if (options.responseType) { - xhr.responseType = options.responseType; - } - - // xhr.onreadystatechange = function() { - // if (xhr.readyState == 4) { - // ; - // } - // }; - - xhr.onload = function(event) { - var response = xhr.response; - var buf = new Uint8Array(response); - var headers = {}; - (xhr.getAllResponseHeaders() || '').replace( - /(?:\r?\n|^)([^:\r\n]+): *([^\r\n]+)/g, - function($0, $1, $2) { - headers[$1.toLowerCase()] = $2; - } - ); - return ret._success(buf, xhr.status, headers, options); - }; - - xhr.onerror = function(event) { - return ret._error(null, new Error(event.message), null, options); - }; - - if (options.data || options.body) { - xhr.send(options.data || options.body); - } else { - xhr.send(null); - } - - return ret; + if (req.responseType) { + xhr.responseType = req.responseType; } + // xhr.onreadystatechange = function() { + // if (xhr.readyState == 4) { + // ; + // } + // }; + + xhr.onload = function(event) { + var response = xhr.response; + var buf = new Uint8Array(response); + var headers = {}; + (xhr.getAllResponseHeaders() || '').replace( + /(?:\r?\n|^)([^:\r\n]+): *([^\r\n]+)/g, + function($0, $1, $2) { + headers[$1.toLowerCase()] = $2; + } + ); + return ret._success(buf, xhr.status, headers, req); + }; + + xhr.onerror = function(event) { + return ret._error(null, new Error(event.message), null, req); + }; + + if (req.body) { + xhr.send(req.body); + } else { + xhr.send(null); + } + + return ret; + + return ret; +}; + +G.$http = G.$http || function $http(options, callback) { + if (typeof options === 'string') { + options = { uri: options }; + } + + var ret = { + success: function(cb) { + this._success = cb; + return this; + }, + error: function(cb) { + this._error = cb; + return this; + }, + _success: function() { + ; + }, + _error: function(_, err) { + throw err; + } + }; + + var xhr = new XMLHttpRequest(); + xhr.open('POST', '/_request', true); + xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); + xhr.responseType = 'arraybuffer'; + + xhr.onload = function(event) { + var response = xhr.response; + var buf = new Uint8Array(response); + var headers = {}; + (xhr.getAllResponseHeaders() || '').replace( + /(?:\r?\n|^)([^:\r\n]+): *([^\r\n]+)/g, + function($0, $1, $2) { + headers[$1.toLowerCase()] = $2; + } + ); + return ret._success(buf, xhr.status, headers, req); + }; + + xhr.onerror = function(event) { + return ret._error(null, new Error(event.message), null, req); + }; + + options.body = options.body || options.data; + + if (options.body) { + if (!Buffer.isBuffer(options.body)) { + options.body = new Buffer(options.body); + } + options.body = options.body.toString('hex'); + } + + options.encoding = null; + + xhr.send(JSON.stringify(options)); + return ret; }; diff --git a/package.json b/package.json index 6504fb200..8c53f6257 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "preconditions": "^1.0.7", "sinon": "1.9.1", "mocha-lcov-reporter": "0.0.1", - "mocha": "^1.18.2" + "mocha": "^1.18.2", + "request": "2.39.0" }, "scripts": { "shell": "node shell/scripts/launch.js",