Skip to content

Commit

Permalink
fix: waitOn and fetch IPv4&v6 instead of localhost (#704)
Browse files Browse the repository at this point in the history
* fix: waitOn and fetch IPv4&v6 instead of localhost
  • Loading branch information
cjk7989 authored Jun 6, 2023
1 parent aa3c1a7 commit 863fa3b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/azuresdkdrop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
node-version: [14.x, 16.x]
node-version: [14.x, 16.x, 18.x]

steps:
- uses: actions/checkout@v2
Expand Down
28 changes: 21 additions & 7 deletions src/core/utils/net.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ export async function validateDevServerConfig(url: string | undefined, timeout:
const resolvedPortNumber = await isAcceptingTcpConnections({ port, host: hostname });
if (resolvedPortNumber !== 0) {
const spinner = ora();
try {
spinner.start(`Waiting for ${chalk.green(url)} to be ready`);
await waitOn({
resources: [`tcp:${hostname}:${port}`],
const waitOnOneOfResources = hostname === "localhost" ? [`tcp:127.0.0.1:${port}`, `tcp:[::1]:${port}`] : [`tcp:${hostname}:${port}`];
spinner.start(`Waiting for ${chalk.green(url)} to be ready`);

let promises = waitOnOneOfResources.map((resource) => {
return waitOn({
resources: [resource],
delay: 1000, // initial delay in ms, default 0
interval: 100, // poll interval in ms, default 250ms
simultaneous: 1, // limit to 1 connection per resource at a time
Expand All @@ -115,10 +117,22 @@ export async function validateDevServerConfig(url: string | undefined, timeout:
window: 1000, // stabilization time in ms, default 750ms
strictSSL: false,
verbose: false, // force disable verbose logs even if SWA_CLI_DEBUG is enabled
});
spinner.succeed(`Connected to ${chalk.green(url)} successfully`);
})
.then(() => {
logger.silly(`Connected to ${resource} successfully`);
return resource;
})
.catch((err) => {
logger.silly(`Could not connect to ${resource}`);
throw err;
});
});

try {
await Promise.any(promises);
spinner.succeed(`Connected to ${url} successfully`);
spinner.clear();
} catch (err) {
} catch {
spinner.fail();
logger.error(`Could not connect to "${url}". Is the server up and running?`, true);
}
Expand Down
43 changes: 42 additions & 1 deletion src/msha/handlers/function.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import httpProxy from "http-proxy";
import fetch from "node-fetch";
import { decodeCookie, logger, logRequest, registerProcessExit, validateCookie } from "../../core";
import { HAS_API, SWA_CLI_API_URI } from "../../core/constants";
import { parseUrl } from "../../core/utils/net";
import { onConnectionLost } from "../middlewares/request.middleware";

const proxyApi = httpProxy.createProxyServer({ autoRewrite: true });
Expand Down Expand Up @@ -53,8 +54,40 @@ function injectClientPrincipalCookies(req: http.ClientRequest) {
}
}

async function resolveLocalhostByFetching(url: string) {
const { protocol, port } = parseUrl(url);
const fetchOneOfUrl = [`${protocol}//127.0.0.1:${port}`, `${protocol}//[::1]:${port}`];

let promises = fetchOneOfUrl.map((Url) => {
return fetch(Url)
.then((response) => {
if (response.ok || response.redirected) {
logger.silly(`Fetch ${Url} successfully`);
return Url;
} else {
logger.silly(`Fetch ${Url} failed with status ${response.status} ${response.statusText}`);
throw new Error(`Fetch ${Url} failed with status ${response.status} ${response.statusText}`);
}
})
.catch((err) => {
logger.silly(`Could not fetch ${Url}`);
throw err;
});
});

try {
const availableUrl = await Promise.any(promises);
return availableUrl;
} catch {
throw new Error('Error: "localhost" can not be resolved to either IPv4 or IPv6. Please check your network settings.');
}
}

export function handleFunctionRequest(req: http.IncomingMessage, res: http.ServerResponse) {
const target = SWA_CLI_API_URI();
let cliApiUri = SWA_CLI_API_URI();
const { protocol, hostname, port } = parseUrl(cliApiUri);
const target = hostname === "localhost" ? `${protocol}//127.0.0.1:${port}` : cliApiUri;

if (HAS_API) {
logger.silly(`function request detected. Proxying to Azure Functions emulator`);
logger.silly(` - target: ${chalk.yellow(target)}`);
Expand Down Expand Up @@ -93,6 +126,14 @@ export function isFunctionRequest(req: http.IncomingMessage, rewritePath?: strin
}

export async function validateFunctionTriggers(url: string) {
const { hostname } = parseUrl(url);
if (hostname === "localhost") {
try {
url = await resolveLocalhostByFetching(url);
} catch (error: any) {
logger.error(error?.message, true);
}
}
try {
const functionsResponse = await fetch(`${url}/admin/functions`);
const functions = (await functionsResponse.json()) as Array<{ config: { bindings: string[] } }>;
Expand Down

0 comments on commit 863fa3b

Please sign in to comment.