Skip to content

Commit 6e2cbde

Browse files
fix: proxy logging and allow to pass options without the target option (#3651)
1 parent c9ccc96 commit 6e2cbde

File tree

2 files changed

+224
-33
lines changed

2 files changed

+224
-33
lines changed

lib/Server.js

+45-32
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,12 @@ class Server {
492492
* }
493493
*/
494494
if (typeof options.proxy !== "undefined") {
495+
// TODO remove in the next major release, only accept `Array`
495496
if (!Array.isArray(options.proxy)) {
496-
if (Object.prototype.hasOwnProperty.call(options.proxy, "target")) {
497+
if (
498+
Object.prototype.hasOwnProperty.call(options.proxy, "target") ||
499+
Object.prototype.hasOwnProperty.call(options.proxy, "router")
500+
) {
497501
options.proxy = [options.proxy];
498502
} else {
499503
options.proxy = Object.keys(options.proxy).map((context) => {
@@ -513,38 +517,42 @@ class Server {
513517
proxyOptions.context = correctedContext;
514518
}
515519

516-
const getLogLevelForProxy = (level) => {
517-
if (level === "none") {
518-
return "silent";
519-
}
520+
return proxyOptions;
521+
});
522+
}
523+
}
520524

521-
if (level === "log") {
522-
return "info";
523-
}
525+
options.proxy = options.proxy.map((item) => {
526+
const getLogLevelForProxy = (level) => {
527+
if (level === "none") {
528+
return "silent";
529+
}
524530

525-
if (level === "verbose") {
526-
return "debug";
527-
}
531+
if (level === "log") {
532+
return "info";
533+
}
528534

529-
return level;
530-
};
535+
if (level === "verbose") {
536+
return "debug";
537+
}
531538

532-
if (typeof proxyOptions.logLevel === "undefined") {
533-
proxyOptions.logLevel = getLogLevelForProxy(
534-
compilerOptions.infrastructureLogging
535-
? compilerOptions.infrastructureLogging.level
536-
: "info"
537-
);
538-
}
539+
return level;
540+
};
539541

540-
if (typeof proxyOptions.logProvider === "undefined") {
541-
proxyOptions.logProvider = () => this.logger;
542-
}
542+
if (typeof item.logLevel === "undefined") {
543+
item.logLevel = getLogLevelForProxy(
544+
compilerOptions.infrastructureLogging
545+
? compilerOptions.infrastructureLogging.level
546+
: "info"
547+
);
548+
}
543549

544-
return proxyOptions;
545-
});
550+
if (typeof item.logProvider === "undefined") {
551+
item.logProvider = () => this.logger;
546552
}
547-
}
553+
554+
return item;
555+
});
548556
}
549557

550558
if (typeof options.setupExitSignals === "undefined") {
@@ -875,22 +883,24 @@ class Server {
875883

876884
// It is possible to use the `bypass` method without a `target`.
877885
// However, the proxy middleware has no use in this case, and will fail to instantiate.
878-
if (proxyConfig.target) {
886+
if (context) {
879887
return createProxyMiddleware(context, proxyConfig);
880888
}
889+
890+
return createProxyMiddleware(proxyConfig);
881891
};
882892
/**
883893
* Assume a proxy configuration specified as:
884894
* proxy: [
885895
* {
886-
* context: ...,
887-
* ...options...
896+
* context: "value",
897+
* ...options,
888898
* },
889899
* // or:
890900
* function() {
891901
* return {
892-
* context: ...,
893-
* ...options...
902+
* context: "context",
903+
* ...options,
894904
* };
895905
* }
896906
* ]
@@ -903,7 +913,9 @@ class Server {
903913
? proxyConfigOrCallback()
904914
: proxyConfigOrCallback;
905915

906-
proxyMiddleware = getProxyMiddleware(proxyConfig);
916+
if (!proxyConfig.bypass) {
917+
proxyMiddleware = getProxyMiddleware(proxyConfig);
918+
}
907919

908920
if (proxyConfig.ws) {
909921
this.webSocketProxies.push(proxyMiddleware);
@@ -922,6 +934,7 @@ class Server {
922934
// - Check if we have a bypass function defined
923935
// - In case the bypass function is defined we'll retrieve the
924936
// bypassUrl from it otherwise bypassUrl would be null
937+
// TODO remove in the next major in favor `context` and `router` options
925938
const isByPassFuncDefined = typeof proxyConfig.bypass === "function";
926939
const bypassUrl = isByPassFuncDefined
927940
? await proxyConfig.bypass(req, res, proxyConfig)

test/server/proxy-option.test.js

+179-1
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,35 @@ const proxyOptionOfArray = [
6666
bypass: () => {
6767
if (req && req.query.foo) {
6868
res.end(`foo+${next.name}+${typeof next}`);
69+
6970
return false;
7071
}
7172
},
7273
};
7374
},
7475
];
7576

77+
const proxyOptionOfArrayWithoutTarget = [
78+
{
79+
router: () => `http://localhost:${port1}`,
80+
},
81+
];
82+
83+
const proxyWithPath = {
84+
"/proxy1": {
85+
path: `http://localhost:${port1}`,
86+
target: `http://localhost:${port1}`,
87+
},
88+
};
89+
90+
const proxyWithString = {
91+
"/proxy1": `http://localhost:${port1}`,
92+
};
93+
94+
const proxyWithRouterAsObject = {
95+
router: () => `http://localhost:${port1}`,
96+
};
97+
7698
describe("proxy option", () => {
7799
let proxyServer1;
78100
let proxyServer2;
@@ -204,7 +226,7 @@ describe("proxy option", () => {
204226
});
205227
});
206228

207-
describe("as an option is an object", () => {
229+
describe("as an option is an object with the `context` option", () => {
208230
let server;
209231
let req;
210232

@@ -243,6 +265,123 @@ describe("proxy option", () => {
243265
});
244266
});
245267

268+
describe("as an option is an object with `context` and `target` as string", () => {
269+
let server;
270+
let req;
271+
272+
beforeAll(async () => {
273+
const compiler = webpack(config);
274+
275+
server = new Server(
276+
{
277+
static: {
278+
directory: staticDirectory,
279+
watch: false,
280+
},
281+
proxy: proxyWithString,
282+
port: port3,
283+
},
284+
compiler
285+
);
286+
287+
await server.start();
288+
289+
await listenProxyServers();
290+
291+
req = request(server.app);
292+
});
293+
294+
afterAll(async () => {
295+
await server.stop();
296+
await closeProxyServers();
297+
});
298+
299+
it("respects a proxy option", async () => {
300+
const response = await req.get("/proxy1");
301+
302+
expect(response.status).toEqual(200);
303+
expect(response.text).toContain("from proxy1");
304+
});
305+
});
306+
307+
describe("as an option is an object with the `path` option (`context` alias)", () => {
308+
let server;
309+
let req;
310+
311+
beforeAll(async () => {
312+
const compiler = webpack(config);
313+
314+
server = new Server(
315+
{
316+
static: {
317+
directory: staticDirectory,
318+
watch: false,
319+
},
320+
proxy: proxyWithPath,
321+
port: port3,
322+
},
323+
compiler
324+
);
325+
326+
await server.start();
327+
328+
await listenProxyServers();
329+
330+
req = request(server.app);
331+
});
332+
333+
afterAll(async () => {
334+
await server.stop();
335+
await closeProxyServers();
336+
});
337+
338+
it("respects a proxy option", async () => {
339+
const response = await req.get("/proxy1");
340+
341+
expect(response.status).toEqual(200);
342+
expect(response.text).toContain("from proxy1");
343+
});
344+
});
345+
346+
describe("as an option is an object with the `router` option", () => {
347+
let server;
348+
let req;
349+
350+
beforeAll(async () => {
351+
const compiler = webpack(config);
352+
353+
server = new Server(
354+
{
355+
static: {
356+
directory: staticDirectory,
357+
watch: false,
358+
},
359+
proxy: proxyWithRouterAsObject,
360+
port: port3,
361+
},
362+
compiler
363+
);
364+
365+
await server.start();
366+
367+
await listenProxyServers();
368+
369+
req = request(server.app);
370+
});
371+
372+
afterAll(async () => {
373+
await server.stop();
374+
await closeProxyServers();
375+
});
376+
377+
it("respects a proxy option", async () => {
378+
const response = await req.get("/proxy1");
379+
380+
expect(response.status).toEqual(200);
381+
expect(response.text).toContain("from proxy1");
382+
});
383+
});
384+
246385
describe("as an array", () => {
247386
let server;
248387
let req;
@@ -296,6 +435,45 @@ describe("proxy option", () => {
296435
});
297436
});
298437

438+
describe("as an array without the `route` option", () => {
439+
let server;
440+
let req;
441+
442+
beforeAll(async () => {
443+
const compiler = webpack(config);
444+
445+
server = new Server(
446+
{
447+
static: {
448+
directory: staticDirectory,
449+
watch: false,
450+
},
451+
proxy: proxyOptionOfArrayWithoutTarget,
452+
port: port3,
453+
},
454+
compiler
455+
);
456+
457+
await server.start();
458+
459+
await listenProxyServers();
460+
461+
req = request(server.app);
462+
});
463+
464+
afterAll(async () => {
465+
await server.stop();
466+
await closeProxyServers();
467+
});
468+
469+
it("respects a proxy option", async () => {
470+
const response = await req.get("/proxy1");
471+
472+
expect(response.status).toEqual(200);
473+
expect(response.text).toContain("from proxy1");
474+
});
475+
});
476+
299477
describe("should sharing a proxy option", () => {
300478
let server;
301479
let req;

0 commit comments

Comments
 (0)