proxy doesn't know if karma webserver runs on different port than originally configured
See original GitHub issueI’m using karma to test a project loaded by systemjs. For lack of a better way, my karma config depends heavily on use of proxies to rewrite paths (but I’m proxying back to karma’s internal webserver, not a different webserver).
I’m also running these tests via a parallel test runner that runs several copies of karma. The first karma starts up on the port configured in karma.conf.js (9050 for me). The second one gets EADDRINUSE, logs “port 9050 in use”, and happily rolls onto port 9051.
The problem is that karma configures the proxy with the port specified via config (thanks to https://github.com/karma-runner/karma/pull/1007) falling back to default 443/80 if the config doesn’t specify. And karma configures the proxy library before it calls listen on its internal webserver, that is, before it discovers the port conflict and starts the webserver on a different port. And when it does discover the port conflict, it never tells the proxy library.
The result in my parallel test runner scenario is this: I start N copies of karma, they start their internal webservers on N different ports starting at 9050, but they’ve all configured their proxy to proxy to 9050. So all the proxied requests go to the webserver for the first karma instance to start. This actually works out better than you might expect, since they’re all serving the same code… until the first karma test passes and exits (the batch tests run in single-run mode), and the rest of the tests keep trying to talk to the webserver that just exited.
This is easy to repro without the parallel scenario; any port conflict will do:
- take any karma test that has a config which proxies requests back to the internal webserver
netcat -lp [the port the karma config uses]
- run the karma test
You’ll see karma itself log “port in use” and increment until it finds an open port, but continue throwing proxied requests at the originally configured port.
A brute force fix for this is to defer evaluation of the proxyConfig port until it’s actually needed, by which time karma’s listening on the right port. A cleaner fix that doesn’t rely on getters would probably have the outer glue code that starts everything wait till the internal webserver owns a port and then tell the proxy code explicitly to use that port. The initialization order and data flow is not very explicit thanks to DI so it’s not immediately obvious to me how to accomplish that.
diff --git a/node_modules/karma/lib/middleware/proxy.js b/node_modules/karma/lib/middleware/proxy.js
index e439c52..9485965 100644
--- a/node_modules/karma/lib/middleware/proxy.js
+++ b/node_modules/karma/lib/middleware/proxy.js
@@ -45,7 +45,12 @@ var parseProxyConfig = function(proxies, config) {
if (!proxyConfig[proxyPath].port) {
if (!proxyConfig[proxyPath].host) {
proxyConfig[proxyPath].host = config.hostname;
- proxyConfig[proxyPath].port = config.port;
+ Object.defineProperty(proxyConfig[proxyPath], 'port', {
+ get: function() {
+ return config.port;
+ },
+ });
} else {
proxyConfig[proxyPath].port = proxyConfig[proxyPath].https ? '443' : '80';
}
Issue Analytics
- State:
- Created 8 years ago
- Reactions:7
- Comments:7 (1 by maintainers)
Top GitHub Comments
Also experienced this just now, took some time to figure out what went wrong, hence my follow-up question: is it possible to tell karma to fail if the port is in use?
I encountered this bug when running tests concurrently (using different instances of Karma).
An easy way to reproduce it is to launch your instance of karma (one that uses proxies). In a different terminal window launch another identical instance. The second instance will notice that
[karma]: Port 9876 in use
and use the next available port. So far so good. Now kill the first instance. This will interrupt the proxy on port9876
. The second one will start throwing 404 errors.