Skip to content

Commit

Permalink
Merge branch 'master' into joehanley-ext-links-to-console
Browse files Browse the repository at this point in the history
  • Loading branch information
bkendall committed Nov 13, 2019
2 parents 0d2b5a6 + 3be6495 commit c55b606
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1 +1,3 @@
* Fixes a bug where the Functions emulator ignored the "host" configuration (#1722)
* Fixes a bug where the Functions emulator accepted requests to too many paths (#1773)
* Print Firebase Console links for Extensions after operations.
11 changes: 5 additions & 6 deletions src/emulator/controller.ts
Expand Up @@ -19,22 +19,22 @@ import * as getProjectId from "../getProjectId";

export const VALID_EMULATOR_STRINGS: string[] = ALL_EMULATORS;

export async function checkPortOpen(port: number): Promise<boolean> {
export async function checkPortOpen(port: number, host: string): Promise<boolean> {
try {
const inUse = await tcpport.check(port);
const inUse = await tcpport.check(port, host);
return !inUse;
} catch (e) {
return false;
}
}

export async function waitForPortClosed(port: number): Promise<void> {
export async function waitForPortClosed(port: number, host: string): Promise<void> {
const interval = 250;
const timeout = 30000;
try {
await tcpport.waitUntilUsed(port, interval, timeout);
} catch (e) {
throw new FirebaseError(`TIMEOUT: Port ${port} was not active within ${timeout}ms`);
throw new FirebaseError(`TIMEOUT: Port ${port} on ${host} was not active within ${timeout}ms`);
}
}

Expand All @@ -45,8 +45,7 @@ export async function startEmulator(instance: EmulatorInstance): Promise<void> {
// Log the command for analytics
track("emulators:start", name);

// TODO(samstern): This check should only occur when the host is localhost
const portOpen = await checkPortOpen(info.port);
const portOpen = await checkPortOpen(info.port, info.host);
if (!portOpen) {
await cleanShutdown();
utils.logWarning(`Port ${info.port} is not open, could not start ${name} emulator.`);
Expand Down
6 changes: 3 additions & 3 deletions src/emulator/emulatorServer.ts
Expand Up @@ -11,12 +11,12 @@ export class EmulatorServer {
constructor(public instance: EmulatorInstance) {}

async start(): Promise<void> {
const port = this.instance.getInfo().port;
const portOpen = await controller.checkPortOpen(port);
const { port, host } = this.instance.getInfo();
const portOpen = await controller.checkPortOpen(port, host);

if (!portOpen) {
throw new FirebaseError(
`Port ${port} is not open, could not start ${this.instance.getName()} emulator.`
`Port ${port} is not open on ${host}, could not start ${this.instance.getName()} emulator.`
);
}

Expand Down
6 changes: 4 additions & 2 deletions src/emulator/functionsEmulator.ts
Expand Up @@ -112,10 +112,12 @@ export class FunctionsEmulator implements EmulatorInstance {

// The URL for the function that the other emulators (Firestore, etc) use.
// TODO(abehaskins): Make the other emulators use the route below and remove this.
const backgroundFunctionRoute = "/functions/projects/:project_id/triggers/:trigger_name";
const backgroundFunctionRoute = `/functions/projects/${
this.args.projectId
}/triggers/:trigger_name`;

// The URL that the developer sees, this is the same URL that the legacy emulator used.
const httpsFunctionRoute = `/:project_id/:region/:trigger_name`;
const httpsFunctionRoute = `/${this.args.projectId}/:region/:trigger_name`;

// A trigger named "foo" needs to respond at "foo" as well as "foo/*" but not "fooBar".
const httpsFunctionRoutes = [httpsFunctionRoute, `${httpsFunctionRoute}/*`];
Expand Down
5 changes: 3 additions & 2 deletions src/emulator/registry.ts
Expand Up @@ -19,10 +19,11 @@ export class EmulatorRegistry {

// Start the emulator and wait for it to grab its assigned port.
await instance.start();
await controller.waitForPortClosed(instance.getInfo().port);

this.set(instance.getName(), instance);
const info = instance.getInfo();
await controller.waitForPortClosed(info.port, info.host);

this.set(instance.getName(), instance);
utils.logLabeledSuccess(
instance.getName(),
`Emulator started at ${clc.bold.underline(`http://${info.host}:${info.port}`)}`
Expand Down
20 changes: 19 additions & 1 deletion src/test/emulators/functionsEmulator.spec.ts
Expand Up @@ -20,7 +20,7 @@ if ((process.env.DEBUG || "").toLowerCase().indexOf("spec") >= 0) {
}

const functionsEmulator = new FunctionsEmulator({
projectId: "",
projectId: "fake-project-id",
functionsDir: "",
});
const startFunctionRuntime = functionsEmulator.startFunctionRuntime;
Expand Down Expand Up @@ -107,6 +107,24 @@ describe("FunctionsEmulator-Hub", () => {
});
}).timeout(TIMEOUT_LONG);

it("should reject requests to a non-emulator path", async () => {
UseFunctions(() => {
return {
function_id: require("firebase-functions").https.onRequest(
(req: express.Request, res: express.Response) => {
res.json({ path: req.path });
}
),
};
});

await supertest(
functionsEmulator.createHubServer(FunctionRuntimeBundles.template, process.execPath)
)
.get("/foo/bar/baz")
.expect(404);
}).timeout(TIMEOUT_LONG);

it("should rewrite req.path to hide /:project_id/:region/:trigger_id", async () => {
UseFunctions(() => {
require("firebase-admin").initializeApp();
Expand Down

0 comments on commit c55b606

Please sign in to comment.