Skip to content

Commit a6c5a94

Browse files
authored
Merge pull request #572 from minrk/http-proxy-3
switch to http-proxy-3
2 parents 176c1e4 + 57376a9 commit a6c5a94

File tree

6 files changed

+189
-416
lines changed

6 files changed

+189
-416
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ on:
2424
jobs:
2525
# Audit dependencies for known vulnerabilities
2626
audit-dependencies:
27-
runs-on: ubuntu-22.04
27+
runs-on: ubuntu-24.04
2828
steps:
2929
- uses: actions/checkout@v4
3030
- uses: actions/setup-node@v4
@@ -50,21 +50,18 @@ jobs:
5050
npm audit --production --audit-level=moderate
5151
5252
test:
53-
runs-on: ubuntu-20.04
53+
runs-on: ubuntu-24.04
5454
strategy:
5555
fail-fast: false # Do not cancel all jobs if one fails
5656
matrix:
5757
# IMPORTANT: Make sure to update package.json's engines.node field to
5858
# always require at least the oldest version, as well as our
5959
# README.md file under the install section.
6060
node_version:
61-
# Removing node 10 is dropping support for ubuntu 20.04 LTS
62-
- "10"
63-
- "12"
64-
- "14"
65-
- "16"
61+
# Removing node 18 is dropping support for ubuntu 24.04 LTS, debian 12
6662
- "18"
6763
- "20"
64+
- "22"
6865
- current
6966

7067
steps:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ functionality to [JupyterHub] deployments.
3636

3737
## Install
3838

39-
Prerequisite: [Node.js](https://nodejs.org/en/download/)10
39+
Prerequisite: [Node.js](https://nodejs.org/en/download/)18
4040

4141
If you're installing `configurable-http-proxy` in Linux, you can follow [the instruction of nodesource](https://github.com/nodesource/distributions#installation-instructions) to install arbitrary version of Node.js.
4242

lib/configproxy.js

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ var http = require("http"),
1313
fs = require("fs"),
1414
path = require("path"),
1515
EventEmitter = require("events").EventEmitter,
16-
httpProxy = require("http-proxy-node16"),
16+
httpProxy = require("http-proxy-3"),
1717
winston = require("winston"),
1818
util = require("util"),
19-
URL = require("url"),
2019
defaultLogger = require("./log").defaultLogger,
21-
querystring = require("querystring"),
2220
metrics = require("./metrics");
2321

2422
function bound(that, method) {
@@ -311,23 +309,20 @@ class ConfigurableProxy extends EventEmitter {
311309
}
312310
// GET returns routing table as JSON dict
313311
var that = this;
314-
var parsed = URL.parse(req.url);
312+
var parsed = new URL(req.url, "https://example.com");
315313
var inactiveSince = null;
316-
if (parsed.query) {
317-
var query = querystring.parse(parsed.query);
318-
if (query.inactive_since !== undefined) {
319-
// camelCaseify
320-
query.inactiveSince = query.inactive_since;
321-
}
322-
323-
if (query.inactiveSince !== undefined) {
324-
var timestamp = Date.parse(query.inactiveSince);
325-
if (isFinite(timestamp)) {
326-
inactiveSince = new Date(timestamp);
327-
} else {
328-
fail(req, res, 400, "Invalid datestamp '" + query.inactiveSince + "' must be ISO8601.");
329-
return;
330-
}
314+
var inactiveSinceParam = parsed.searchParams.get("inactiveSince");
315+
if (!inactiveSinceParam) {
316+
// camelCaseify old inactive_since
317+
inactiveSinceParam = parsed.searchParams.get("inactive_since");
318+
}
319+
if (inactiveSinceParam) {
320+
var timestamp = Date.parse(inactiveSinceParam);
321+
if (isFinite(timestamp)) {
322+
inactiveSince = new Date(timestamp);
323+
} else {
324+
fail(req, res, 400, "Invalid datestamp '" + inactiveSinceParam + "' must be ISO8601.");
325+
return;
331326
}
332327
}
333328
res.writeHead(200, { "Content-Type": "application/json" });
@@ -393,7 +388,7 @@ class ConfigurableProxy extends EventEmitter {
393388
var metricsTimerEnd = this.metrics.findTargetForReqSummary.startTimer();
394389
// return proxy target for a given url path
395390
var basePath = this.hostRouting ? "/" + parseHost(req) : "";
396-
var path = basePath + decodeURIComponent(URL.parse(req.url).pathname);
391+
var path = basePath + decodeURIComponent(new URL(req.url, "http://example.com").pathname);
397392
var route = await this._routes.getTarget(path);
398393
metricsTimerEnd();
399394
if (route) {
@@ -460,26 +455,27 @@ class ConfigurableProxy extends EventEmitter {
460455
return;
461456
}
462457
if (this.errorTarget) {
463-
var urlSpec = URL.parse(this.errorTarget);
458+
var urlSpec = new URL(this.errorTarget);
464459
// error request is $errorTarget/$code?url=$requestUrl
465-
urlSpec.search = "?" + querystring.encode({ url: req.url });
460+
urlSpec.searchParams.set("url", req.url);
466461
urlSpec.pathname = urlSpec.pathname + code.toString();
467462
var secure = /https/gi.test(urlSpec.protocol) ? true : false;
468-
var url = URL.format(urlSpec);
469-
this.log.debug("Requesting custom error page: %s", urlSpec.format());
463+
var url = urlSpec.toString();
464+
this.log.debug("Requesting custom error page: %s", url);
470465

471-
// construct request target from urlSpec
472-
var target = URL.parse(url);
473-
target.method = "GET";
466+
// construct request options
467+
var options = {
468+
method: "GET",
469+
};
474470

475471
// add client SSL config if error target is using https
476472
if (secure && this.options.clientSsl) {
477-
target.key = this.options.clientSsl.key;
478-
target.cert = this.options.clientSsl.cert;
479-
target.ca = this.options.clientSsl.ca;
473+
options.key = this.options.clientSsl.key;
474+
options.cert = this.options.clientSsl.cert;
475+
options.ca = this.options.clientSsl.ca;
480476
}
481477

482-
var errorRequest = (secure ? https : http).request(target, function (upstream) {
478+
var errorRequest = (secure ? https : http).request(url, options, function (upstream) {
483479
if (res.writableEnded) return; // response already done
484480
["content-type", "content-encoding"].map(function (key) {
485481
if (!upstream.headers[key]) return;
@@ -556,15 +552,15 @@ class ConfigurableProxy extends EventEmitter {
556552
req.url = req.url.slice(prefix.length);
557553
}
558554

559-
target = URL.parse(target);
555+
target = new URL(target);
556+
var proxyOptions = { target: target };
560557
if (that.options.clientSsl) {
561-
target.key = that.options.clientSsl.key;
562-
target.cert = that.options.clientSsl.cert;
563-
target.ca = that.options.clientSsl.ca;
558+
proxyOptions.key = that.options.clientSsl.key;
559+
proxyOptions.cert = that.options.clientSsl.cert;
560+
proxyOptions.ca = that.options.clientSsl.ca;
564561
}
565562

566563
// add config argument
567-
var proxyOptions = { target: target };
568564
if (target.protocol.slice(-2) === "s:") {
569565
proxyOptions.agent = that.httpsAgent;
570566
} else {
@@ -657,7 +653,7 @@ class ConfigurableProxy extends EventEmitter {
657653
function pushPathArg(arg) {
658654
args.push(arg === undefined ? arg : decodeURIComponent(arg));
659655
}
660-
var path = URL.parse(req.url).pathname;
656+
var path = new URL(req.url, "https://example.com").pathname;
661657
for (var i = 0; i < this.apiHandlers.length; i++) {
662658
var pat = this.apiHandlers[i][0];
663659
var match = pat.exec(path);

lib/testutil.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
"use strict";
22

33
var http = require("http");
4-
var URL = require("url");
54
var extend = require("util")._extend;
65
var WebSocketServer = require("ws").WebSocketServer;
7-
var querystring = require("querystring");
86

97
var configproxy = require("./configproxy");
108
var defaultLogger = require("./log").defaultLogger;
@@ -112,17 +110,17 @@ exports.setupProxy = function (port, options, paths) {
112110
if (options.errorTarget) {
113111
countdown++;
114112
var errorServer = http.createServer(function (req, res) {
115-
var parsed = URL.parse(req.url);
116-
var query = querystring.parse(parsed.query);
113+
var query = new URL(req.url, "http://example.com").searchParams;
117114
res.setHeader("Content-Type", "text/plain");
118115
req.on("data", function () {});
119116
req.on("end", function () {
120-
res.write(query.url);
117+
res.write(query.get("url"));
121118
res.end();
122119
});
123120
});
124121
errorServer.on("listening", onlisten);
125-
errorServer.listen(URL.parse(options.errorTarget).port, ip);
122+
const errorUrl = new URL(options.errorTarget);
123+
errorServer.listen(errorUrl.port, ip);
126124
servers.push(errorServer);
127125
}
128126

0 commit comments

Comments
 (0)