diff --git a/lib/configproxy.js b/lib/configproxy.js index 3b34f429..619a8dfc 100644 --- a/lib/configproxy.js +++ b/lib/configproxy.js @@ -378,21 +378,19 @@ class ConfigurableProxy extends EventEmitter { }); } - targetForReq(req) { + async targetForReq(req) { var metricsTimerEnd = this.metrics.findTargetForReqSummary.startTimer(); // return proxy target for a given url path var basePath = this.hostRouting ? "/" + parseHost(req) : ""; var path = basePath + decodeURIComponent(URL.parse(req.url).pathname); - - return this._routes.getTarget(path).then(function (route) { - metricsTimerEnd(); - if (route) { - return { - prefix: route.prefix, - target: route.data.target, - }; - } - }); + var route = await this._routes.getTarget(path); + metricsTimerEnd(); + if (route) { + return { + prefix: route.prefix, + target: route.data.target, + }; + } } updateLastActivity(prefix) { @@ -528,72 +526,77 @@ class ConfigurableProxy extends EventEmitter { var args = Array.prototype.slice.call(arguments, 1); // get the proxy target - return this.targetForReq(req).then((match) => { - if (!match) { - that.handleProxyError(404, kind, req, res); - return; - } - - if (kind === "web") { - that.emit("proxyRequest", req, res); - } else { - that.emit("proxyRequestWs", req, res, args[2]); - } - var prefix = match.prefix; - var target = match.target; - that.log.debug("PROXY %s %s to %s", kind.toUpperCase(), _logUrl(req.url), target); - if (!that.includePrefix) { - req.url = req.url.slice(prefix.length); - } + return this.targetForReq(req) + .then((match) => { + if (!match) { + that.handleProxyError(404, kind, req, res); + return; + } - target = URL.parse(target); - if (that.options.clientSsl) { - target.key = that.options.clientSsl.key; - target.cert = that.options.clientSsl.cert; - target.ca = that.options.clientSsl.ca; - } + if (kind === "web") { + that.emit("proxyRequest", req, res); + } else { + that.emit("proxyRequestWs", req, res, args[2]); + } + var prefix = match.prefix; + var target = match.target; + that.log.debug("PROXY %s %s to %s", kind.toUpperCase(), _logUrl(req.url), target); + if (!that.includePrefix) { + req.url = req.url.slice(prefix.length); + } - // add config argument - args.push({ target: target }); + target = URL.parse(target); + if (that.options.clientSsl) { + target.key = that.options.clientSsl.key; + target.cert = that.options.clientSsl.cert; + target.ca = that.options.clientSsl.ca; + } - // add error handling - args.push(function (e) { - that.handleProxyError(503, kind, req, res, e); - }); + // add config argument + args.push({ target: target }); - // dispatch the actual method, either: - // - proxy.web(req, res, options, errorHandler) - // - proxy.ws(req, socket, head, options, errorHandler) - that.proxy[kind].apply(that.proxy, args); + // add error handling + args.push(function (e) { + that.handleProxyError(503, kind, req, res, e); + }); - // update timestamp on any request/reply data as well (this includes websocket data) - req.on("data", function () { - that.updateLastActivity(prefix); - }); + // dispatch the actual method, either: + // - proxy.web(req, res, options, errorHandler) + // - proxy.ws(req, socket, head, options, errorHandler) + that.proxy[kind].apply(that.proxy, args); - res.on("data", function () { - that.updateLastActivity(prefix); - }); + // update timestamp on any request/reply data as well (this includes websocket data) + req.on("data", function () { + that.updateLastActivity(prefix); + }); - if (kind === "web") { - // update last activity on completion of the request - // only consider 'successful' requests activity - // A flood of invalid requests such as 404s or 403s - // or 503s because the endpoint is down - // shouldn't make it look like the endpoint is 'active' - - // we no longer register activity at the *start* of the request - // because at that point we don't know if the endpoint is even available - res.on("finish", function () { - // (don't count redirects...but should we?) - if (res.statusCode < 300) { - that.updateLastActivity(prefix); - } else { - that.log.debug("Not recording activity for status %s on %s", res.statusCode, prefix); - } + res.on("data", function () { + that.updateLastActivity(prefix); }); - } - }); + + if (kind === "web") { + // update last activity on completion of the request + // only consider 'successful' requests activity + // A flood of invalid requests such as 404s or 403s + // or 503s because the endpoint is down + // shouldn't make it look like the endpoint is 'active' + + // we no longer register activity at the *start* of the request + // because at that point we don't know if the endpoint is even available + res.on("finish", function () { + // (don't count redirects...but should we?) + if (res.statusCode < 300) { + that.updateLastActivity(prefix); + } else { + that.log.debug("Not recording activity for status %s on %s", res.statusCode, prefix); + } + }); + } + }) + .catch(function (e) { + if (res.finished) throw e; + that.handleProxyError(500, kind, req, res, e); + }); } handleProxyWs(req, socket, head) { diff --git a/test/proxy_spec.js b/test/proxy_spec.js index 2dfbef66..a659f10c 100644 --- a/test/proxy_spec.js +++ b/test/proxy_spec.js @@ -379,6 +379,20 @@ describe("Proxy Tests", function () { .then(done); }); + it("backend error", function (done) { + var proxyPort = 55550; + util + .setupProxy(proxyPort, { errorTarget: "http://127.0.0.1:55565" }, []) + .then(() => r("http://127.0.0.1:" + proxyPort + "/%")) + .then((body) => done.fail("Expected 500")) + .catch((err) => { + expect(err.statusCode).toEqual(500); + expect(err.response.headers["content-type"]).toEqual("text/plain"); + expect(err.response.body).toEqual("/%"); + }) + .then(done); + }); + it("Redirect location untouched without rewrite options", function (done) { var redirectTo = "http://foo.com:12345/whatever"; util