Skip to content

Commit 079b9f1

Browse files
authored
Use http server for file references (#461)
1 parent 297fa9f commit 079b9f1

File tree

6 files changed

+94
-48
lines changed

6 files changed

+94
-48
lines changed

packages/runner/src/commands/test/parse-options.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ function parseOptions(args, config) {
5656
targetFilter: argv.targetFilter,
5757
configurationFilter: argv.configurationFilter || argv._[1],
5858
dockerWithSudo: $('dockerWithSudo'),
59-
chromeDockerUseCopy: $('chromeDockerUseCopy'),
6059
chromeDockerWithoutSeccomp: $('chromeDockerWithoutSeccomp'),
6160
passWithNoStories: $('passWithNoStories'),
6261
device: $('device'),

packages/runner/src/commands/test/run-tests.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ async function runTests(flatConfigurations, options) {
256256
chromeFlags: options.chromeFlags,
257257
dockerNet: options.dockerNet,
258258
dockerWithSudo: options.dockerWithSudo,
259-
chromeDockerUseCopy: options.chromeDockerUseCopy,
260259
chromeDockerWithoutSeccomp: options.chromeDockerWithoutSeccomp,
261260
}),
262261
configurations,

packages/target-chrome-docker/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"debug": "^4.1.1",
2727
"execa": "^5.0.0",
2828
"fs-extra": "^9.1.0",
29-
"get-port": "^5.1.1",
29+
"find-free-port-sync": "^1.0.0",
30+
"mime-types": "^2.1.35",
3031
"wait-on": "^5.2.1"
3132
},
3233
"publishConfig": {

packages/target-chrome-docker/src/create-chrome-docker-target.js

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const { execSync } = require('child_process');
33
const execa = require('execa');
44
const waitOn = require('wait-on');
55
const CDP = require('chrome-remote-interface');
6-
const getRandomPort = require('get-port');
6+
const getRandomPort = require('find-free-port-sync');
77
const {
88
ChromeError,
99
ensureDependencyAvailable,
@@ -12,6 +12,7 @@ const {
1212
const { createChromeTarget } = require('@loki/target-chrome-core');
1313
const { getLocalIPAddress } = require('./get-local-ip-address');
1414
const { getNetworkHost } = require('./get-network-host');
15+
const { createStaticServer } = require('./create-static-server');
1516

1617
const getExecutor = (dockerWithSudo) => (dockerPath, args) => {
1718
if (dockerWithSudo) {
@@ -46,16 +47,16 @@ function createChromeDockerTarget({
4647
chromeFlags = ['--headless', '--disable-gpu', '--hide-scrollbars'],
4748
dockerNet = null,
4849
dockerWithSudo = false,
49-
chromeDockerUseCopy = false,
5050
chromeDockerWithoutSeccomp = false,
5151
}) {
52-
let port;
52+
let debuggerPort;
53+
let staticServer;
54+
let staticServerPath;
55+
let staticServerPort;
5356
let dockerId;
5457
let host;
55-
let localPath;
5658
let dockerUrl = getAbsoluteURL(baseUrl);
5759
const isLocalFile = dockerUrl.indexOf('file:') === 0;
58-
const staticMountPath = '/var/loki';
5960
const dockerPath = 'docker';
6061
const runArgs = ['run', '--rm', '-d', '-P'];
6162
const execute = getExecutor(dockerWithSudo);
@@ -65,21 +66,19 @@ function createChromeDockerTarget({
6566
}
6667
runArgs.push('--add-host=host.docker.internal:host-gateway');
6768

68-
if (dockerUrl.indexOf('http://localhost') === 0) {
69+
if (dockerUrl.indexOf('http://localhost') === 0 || isLocalFile) {
6970
const ip = getLocalIPAddress();
7071
if (!ip) {
7172
throw new Error(
7273
'Unable to detect local IP address, try passing --host argument'
7374
);
7475
}
75-
dockerUrl = dockerUrl.replace('localhost', ip);
76-
} else if (isLocalFile) {
77-
localPath = dockerUrl.substr('file:'.length);
78-
dockerUrl = `file://${staticMountPath}`;
79-
if (!chromeDockerUseCopy) {
80-
// setup volume mount if we're not using copy
81-
runArgs.push('-v');
82-
runArgs.push(`${localPath}:${staticMountPath}`);
76+
if (isLocalFile) {
77+
staticServerPort = getRandomPort();
78+
staticServerPath = dockerUrl.substr('file:'.length);
79+
dockerUrl = `http://${ip}:${staticServerPort}`;
80+
} else {
81+
dockerUrl = dockerUrl.replace('localhost', ip);
8382
}
8483
}
8584

@@ -96,19 +95,6 @@ function createChromeDockerTarget({
9695
return stdout.trim().length !== 0;
9796
}
9897

99-
async function copyFiles() {
100-
const { exitCode, stdout, stderr } = await execute(dockerPath, [
101-
'cp',
102-
localPath,
103-
`${dockerId}:${staticMountPath}`,
104-
]);
105-
106-
if (exitCode !== 0) {
107-
throw new Error(`Failed to copy files, ${stderr}`);
108-
}
109-
return stdout.trim().length !== 0;
110-
}
111-
11298
async function ensureImageDownloaded() {
11399
ensureDependencyAvailable('docker');
114100

@@ -119,13 +105,19 @@ function createChromeDockerTarget({
119105
}
120106

121107
async function start() {
122-
port = await getRandomPort();
123-
124108
ensureDependencyAvailable('docker');
109+
110+
debuggerPort = getRandomPort();
111+
if (isLocalFile) {
112+
staticServer = createStaticServer(staticServerPath);
113+
staticServer.listen(staticServerPort);
114+
debug(`Starting static file server at ${dockerUrl}`);
115+
}
116+
125117
const dockerArgs = runArgs.concat([
126118
'--shm-size=1g',
127119
'-p',
128-
`${port}:${port}`,
120+
`${debuggerPort}:${debuggerPort}`,
129121
]);
130122

131123
if (dockerNet) {
@@ -139,7 +131,7 @@ function createChromeDockerTarget({
139131
'--no-first-run',
140132
'--disable-extensions',
141133
'--remote-debugging-address=0.0.0.0',
142-
`--remote-debugging-port=${port}`,
134+
`--remote-debugging-port=${debuggerPort}`,
143135
])
144136
.concat(chromeFlags);
145137

@@ -151,9 +143,6 @@ function createChromeDockerTarget({
151143
const { exitCode, stdout, stderr } = await execute(dockerPath, args);
152144
if (exitCode === 0) {
153145
dockerId = stdout;
154-
if (chromeDockerUseCopy) {
155-
await copyFiles();
156-
}
157146
const logs = execute(dockerPath, ['logs', dockerId, '--follow']);
158147
const errorLogs = [];
159148
logs.stderr.on('data', (chunk) => {
@@ -162,7 +151,7 @@ function createChromeDockerTarget({
162151

163152
host = await getNetworkHost(execute, dockerId);
164153
try {
165-
await waitOnCDPAvailable(host, port);
154+
await waitOnCDPAvailable(host, debuggerPort);
166155
} catch (error) {
167156
if (
168157
error.message.startsWith('Timed out waiting for') &&
@@ -195,17 +184,20 @@ function createChromeDockerTarget({
195184
} else {
196185
debug('No chrome docker instance to kill');
197186
}
187+
if (staticServer) {
188+
staticServer.close();
189+
}
198190
}
199191

200192
async function createNewDebuggerInstance() {
201-
debug(`Launching new tab with debugger at port ${host}:${port}`);
202-
const target = await CDP.New({ host, port });
193+
debug(`Launching new tab with debugger at port ${host}:${debuggerPort}`);
194+
const target = await CDP.New({ host, port: debuggerPort });
203195
debug(`Launched with target id ${target.id}`);
204-
const client = await CDP({ host, port, target });
196+
const client = await CDP({ host, port: debuggerPort, target });
205197

206198
client.close = () => {
207199
debug('Closing tab');
208-
return CDP.Close({ host, port, id: target.id });
200+
return CDP.Close({ host, port: debuggerPort, id: target.id });
209201
};
210202

211203
return client;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* eslint-disable consistent-return */
2+
const http = require('http');
3+
const fs = require('fs');
4+
const path = require('path');
5+
const mime = require('mime-types');
6+
7+
async function sendFile(res, filePath) {
8+
const file = await fs.promises.open(filePath, 'r');
9+
try {
10+
const stat = await file.stat();
11+
if (!stat.isFile()) {
12+
const err = new Error('Path is directory');
13+
err.code = 'EISDIR';
14+
throw err;
15+
}
16+
const contentType = mime.contentType(path.basename(filePath));
17+
18+
const headers = {
19+
'Content-Length': stat.size,
20+
'Cache-Control': 'no-store, must-revalidate',
21+
};
22+
if (contentType) {
23+
headers['Content-Type'] = contentType;
24+
}
25+
res.writeHead(200, headers);
26+
27+
const readStream = file.createReadStream({ autoClose: true });
28+
readStream.pipe(res, { end: true });
29+
readStream.on('close', () => {
30+
file.close();
31+
});
32+
} catch (err) {
33+
file.close();
34+
throw err;
35+
}
36+
}
37+
38+
const createStaticServer = (dir) =>
39+
http.createServer(async (req, res) => {
40+
const url = new URL(`http://localhost${req.url}`);
41+
const staticFilePath = path.normalize(
42+
path.join(dir, url.pathname === '/' ? 'index.html' : url.pathname)
43+
);
44+
if (staticFilePath.startsWith(dir)) {
45+
try {
46+
return await sendFile(res, staticFilePath);
47+
} catch (err) {
48+
if (err.code !== 'ENOENT' && err.code !== 'EISDIR') {
49+
throw err;
50+
}
51+
}
52+
}
53+
});
54+
55+
module.exports = { createStaticServer };

yarn.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10758,6 +10758,11 @@ find-cache-dir@^3.2.0, find-cache-dir@^3.3.1:
1075810758
make-dir "^3.0.2"
1075910759
pkg-dir "^4.1.0"
1076010760

10761+
find-free-port-sync@^1.0.0:
10762+
version "1.0.0"
10763+
resolved "https://registry.yarnpkg.com/find-free-port-sync/-/find-free-port-sync-1.0.0.tgz#10c9007655b6b65a7900e79d391e8da21e31cc19"
10764+
integrity sha512-wRkO8crYqjaTvCnqEfQGuV8LOp4JO0Ctjn6qROGPcradK+6jQ7giLMGLnKlNxQm6dEdYD3/TBABQ7Xi/5ZhWcg==
10765+
1076110766
find-root@^1.1.0:
1076210767
version "1.1.0"
1076310768
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
@@ -11150,11 +11155,6 @@ get-port@^4.2.0:
1115011155
resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119"
1115111156
integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==
1115211157

11153-
get-port@^5.1.1:
11154-
version "5.1.1"
11155-
resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193"
11156-
integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==
11157-
1115811158
get-proxy@^2.0.0:
1115911159
version "2.1.0"
1116011160
resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93"
@@ -14785,7 +14785,7 @@ mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19,
1478514785
dependencies:
1478614786
mime-db "1.45.0"
1478714787

14788-
mime-types@^2.1.30, mime-types@^2.1.31:
14788+
mime-types@^2.1.30, mime-types@^2.1.31, mime-types@^2.1.35:
1478914789
version "2.1.35"
1479014790
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
1479114791
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==

0 commit comments

Comments
 (0)