mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 12:57:46 +00:00
[cli] Poll the Dev Command server on both IPv4 and IPv6 in vc dev (#8542)
This change will allow the downstream Dev Command server be able to listen on either of `127.0.0.1` for IPv4 or `[::1]` for IPv6. - Fixes #6639 - Fixes #8511 - Fixes #8121 - Closes #8512 - Closes #8384
This commit is contained in:
@@ -153,7 +153,7 @@ export default class DevServer {
|
|||||||
private filter: (path: string) => boolean;
|
private filter: (path: string) => boolean;
|
||||||
private podId: string;
|
private podId: string;
|
||||||
private devProcess?: ChildProcess;
|
private devProcess?: ChildProcess;
|
||||||
private devProcessPort?: number;
|
private devProcessOrigin?: string;
|
||||||
private devServerPids: Set<number>;
|
private devServerPids: Set<number>;
|
||||||
private originalProjectSettings?: ProjectSettings;
|
private originalProjectSettings?: ProjectSettings;
|
||||||
private projectSettings?: ProjectSettings;
|
private projectSettings?: ProjectSettings;
|
||||||
@@ -1014,14 +1014,14 @@ export default class DevServer {
|
|||||||
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
||||||
this.server.on('upgrade', async (req, socket, head) => {
|
this.server.on('upgrade', async (req, socket, head) => {
|
||||||
await this.startPromise;
|
await this.startPromise;
|
||||||
if (!this.devProcessPort) {
|
if (!this.devProcessOrigin) {
|
||||||
this.output.debug(
|
this.output.debug(
|
||||||
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
||||||
);
|
);
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const target = `http://127.0.0.1:${this.devProcessPort}`;
|
const target = this.devProcessOrigin;
|
||||||
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
||||||
this.proxy.ws(req, socket, head, { target });
|
this.proxy.ws(req, socket, head, { target });
|
||||||
});
|
});
|
||||||
@@ -1820,8 +1820,8 @@ export default class DevServer {
|
|||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
// If the dev command is started, then proxy to it
|
// If the dev command is started, then proxy to it
|
||||||
if (this.devProcessPort) {
|
if (this.devProcessOrigin) {
|
||||||
const upstream = `http://127.0.0.1:${this.devProcessPort}`;
|
const upstream = this.devProcessOrigin;
|
||||||
debug(`Proxying to frontend dev server: ${upstream}`);
|
debug(`Proxying to frontend dev server: ${upstream}`);
|
||||||
|
|
||||||
// Add the Vercel platform proxy request headers
|
// Add the Vercel platform proxy request headers
|
||||||
@@ -2000,7 +2000,7 @@ export default class DevServer {
|
|||||||
// - when there is no asset
|
// - when there is no asset
|
||||||
// - when the asset is not a Lambda (the dev server must take care of all static files)
|
// - when the asset is not a Lambda (the dev server must take care of all static files)
|
||||||
if (
|
if (
|
||||||
this.devProcessPort &&
|
this.devProcessOrigin &&
|
||||||
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
|
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
|
||||||
) {
|
) {
|
||||||
debug('Proxying to frontend dev server');
|
debug('Proxying to frontend dev server');
|
||||||
@@ -2012,14 +2012,7 @@ export default class DevServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setResponseHeaders(res, requestId);
|
this.setResponseHeaders(res, requestId);
|
||||||
return proxyPass(
|
return proxyPass(req, res, this.devProcessOrigin, this, requestId, false);
|
||||||
req,
|
|
||||||
res,
|
|
||||||
`http://127.0.0.1:${this.devProcessPort}`,
|
|
||||||
this,
|
|
||||||
requestId,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundAsset) {
|
if (!foundAsset) {
|
||||||
@@ -2348,12 +2341,11 @@ export default class DevServer {
|
|||||||
|
|
||||||
p.on('exit', (code, signal) => {
|
p.on('exit', (code, signal) => {
|
||||||
this.output.debug(`Dev command exited with "${signal || code}"`);
|
this.output.debug(`Dev command exited with "${signal || code}"`);
|
||||||
this.devProcessPort = undefined;
|
this.devProcessOrigin = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
await checkForPort(port, 1000 * 60 * 5);
|
const devProcessHost = await checkForPort(port, 1000 * 60 * 5);
|
||||||
|
this.devProcessOrigin = `http://${devProcessHost}:${port}`;
|
||||||
this.devProcessPort = port;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2641,15 +2633,29 @@ function needsBlockingBuild(buildMatch: BuildMatch): boolean {
|
|||||||
return typeof builder.shouldServe !== 'function';
|
return typeof builder.shouldServe !== 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkForPort(port: number, timeout: number): Promise<void> {
|
async function checkForPort(port: number, timeout: number): Promise<string> {
|
||||||
const opts = { host: '127.0.0.1' };
|
let host;
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
while (!(await isPortReachable(port, opts))) {
|
while (!(host = await getReachableHostOnPort(port))) {
|
||||||
if (Date.now() - start > timeout) {
|
if (Date.now() - start > timeout) {
|
||||||
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
|
break;
|
||||||
}
|
}
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
}
|
}
|
||||||
|
if (!host) {
|
||||||
|
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
|
||||||
|
}
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getReachableHostOnPort(port: number): Promise<string | false> {
|
||||||
|
const optsIpv4 = { host: '127.0.0.1' };
|
||||||
|
const optsIpv6 = { host: '::1' };
|
||||||
|
const results = await Promise.all([
|
||||||
|
isPortReachable(port, optsIpv6).then(r => r && `[${optsIpv6.host}]`),
|
||||||
|
isPortReachable(port, optsIpv4).then(r => r && optsIpv4.host),
|
||||||
|
]);
|
||||||
|
return results.find(Boolean) || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterFrontendBuilds(build: Builder) {
|
function filterFrontendBuilds(build: Builder) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port $PORT",
|
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
|
|||||||
3
packages/cli/test/dev/fixtures/vite-dev/vercel.json
Normal file
3
packages/cli/test/dev/fixtures/vite-dev/vercel.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"devCommand": "vite --port $PORT --host ::1"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user