refactor(@embark/blockchain_process): remove http-proxy-middleware

The problems described in embark PR #1166 can be resolved by implementing the
blockchain proxy with `http-proxy` directly instead of using `express` together
with `http-proxy-middleware`. The ultimate cause of the buggy behavior (the
"stuck sockets" problems described in #1166) is unknown.

The need to swallow some errors as described in embark PR #1181 is also
eliminated by dropping `http-proxy-middleware` and `express`.
This commit is contained in:
Michael Bradley, Jr 2018-12-14 10:57:54 -06:00 committed by Michael Bradley
parent 944b392cc5
commit acf62668ab
3 changed files with 61 additions and 78 deletions

View File

@ -118,7 +118,7 @@
"hard-source-webpack-plugin": "0.12.0",
"helmet": "3.13.0",
"hosted-git-info": "2.7.1",
"http-proxy-middleware": "0.19.0",
"http-proxy": "1.17.0",
"http-shutdown": "1.2.0",
"i18n": "0.8.3",
"ipfs-api": "17.2.4",

View File

@ -3,9 +3,9 @@
const Asm = require('stream-json/Assembler');
const {canonicalHost, defaultHost} = require('../../utils/host');
const constants = require('../../constants.json');
const express = require('express');
const http = require('http');
const httpProxy = require('http-proxy');
const {parser: jsonParser} = require('stream-json');
const proxyMiddleware = require('http-proxy-middleware');
const pump = require('pump');
const utils = require('../../utils/utils');
const WsParser = require('simples/lib/parsers/ws');
@ -17,21 +17,17 @@ const hex = (n) => {
const parseJsonMaybe = (string) => {
let object;
if (typeof string === 'string') {
// ignore empty strings
if (string) {
try {
object = JSON.parse(string);
} catch(e) {
// ignore client/server byte sequences sent when connections are closing
if (Array.from(Buffer.from(string)).map(hex).join(':') !==
'03:ef:bf:bd') {
console.error(`Proxy: Error parsing string as JSON '${string}'`);
}
// ignore empty strings
if (string !== '') {
try {
object = JSON.parse(string);
} catch(e) {
// ignore client/server byte sequences sent when connections are closing
if (Array.from(Buffer.from(string)).map(hex).join(':') !==
'03:ef:bf:bd') {
console.error(`Proxy: Error parsing string as JSON '${string}'`);
}
}
} else {
console.error(`Proxy: Expected a string but got type '${typeof string}'`);
}
return object;
};
@ -119,78 +115,75 @@ exports.serve = async (ipc, host, port, ws, origin, certOptions={}) => {
});
}());
const proxyOpts = {
logLevel: 'warn',
target: `http://${canonicalHost(host)}:${port}`,
ws: ws,
let proxy = httpProxy.createProxyServer({
ssl: certOptions,
onError(err, _req, _res) {
console.error(
__('Proxy: Error forwarding requests to blockchain/simulator'),
err.message
);
target: {
host: canonicalHost(host),
port: port
},
ws: ws
});
onProxyReq(_proxyReq, req, _res) {
if (req.method === 'POST') {
// messages TO the target
Asm.connectTo(
pump(req, jsonParser())
).on('done', ({current: object}) => {
trackRequest(object);
});
}
},
proxy.on('error', (err) => {
console.error(
__('Proxy: Error forwarding requests to blockchain/simulator'),
err.message
);
});
onProxyRes(proxyRes, req, _res) {
if (req.method === 'POST') {
// messages FROM the target
Asm.connectTo(
pump(proxyRes, jsonParser())
).on('done', ({current: object}) => {
trackResponse(object);
});
}
proxy.on('proxyRes', (proxyRes, req, _res) => {
if (req.method === 'POST') {
// messages FROM the target
Asm.connectTo(
pump(proxyRes, jsonParser())
).on('done', ({current: object}) => {
trackResponse(object);
});
}
};
});
if (ws) {
proxyOpts.onProxyReqWs = (_proxyReq, _req, socket, _options, _head) => {
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
// messages TO the target
pump(socket, new WsParser(0, false)).on('frame', ({data: buffer}) => {
const object = parseJsonMaybe(buffer.toString());
Asm.connectTo(
pump(req, jsonParser())
).on('done', ({current: object}) => {
trackRequest(object);
});
};
}
proxyOpts.onOpen = (proxySocket) => {
if (!ws) {
proxy.web(req, res);
}
});
if (ws) {
server.on('upgrade', function (msg, socket, head) {
proxy.ws(msg, socket, head);
});
proxy.on('open', (proxySocket) => {
// messages FROM the target
pump(proxySocket, new WsParser(0, true)).on('frame', ({data: buffer}) => {
const object = parseJsonMaybe(buffer.toString());
trackResponse(object);
});
};
});
proxy.on('proxyReqWs', (_proxyReq, _req, socket) => {
// messages TO the target
pump(socket, new WsParser(0, false)).on('frame', ({data: buffer}) => {
const object = parseJsonMaybe(buffer.toString());
trackRequest(object);
});
});
}
const proxy = proxyMiddleware(proxyOpts);
const app = express();
app.use('*', proxy);
return new Promise(resolve => {
const server = app.listen(
server.listen(
port - constants.blockchain.servicePortOnProxy,
defaultHost,
() => { resolve(server); }
);
if (ws) {
server.on('upgrade', (msg, socket, head) => {
const swallowError = (err) => {
console.error(`Proxy: Network error '${err.message}'`);
};
socket.on('error', swallowError);
proxy.upgrade(msg, socket, head);
});
}
});
};

View File

@ -4965,17 +4965,7 @@ http-https@^1.0.0:
resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b"
integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=
http-proxy-middleware@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.0.tgz#40992b5901dc44bc7bc3795da81b0b248eca02d8"
integrity sha512-Ab/zKDy2B0404mz83bgki0HHv/xqpYKAyFXhopAiJaVAUSJfLYrpBYynTl4ZSUJ7TqrAgjarTsxdX5yBb4unRQ==
dependencies:
http-proxy "^1.17.0"
is-glob "^4.0.0"
lodash "^4.17.10"
micromatch "^3.1.10"
http-proxy@^1.17.0:
http-proxy@1.17.0:
version "1.17.0"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a"
integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==