Skip to content

Commit

Permalink
Fixes #1280 - Emulator Socket on Windows (#1306)
Browse files Browse the repository at this point in the history
  • Loading branch information
abeisgoat authored and samtstern committed May 16, 2019
1 parent d0b3c7c commit fd8bace
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 16 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ fixed - Functions emulator no longer watches node_modules files.
fixed - Functions emulator fails to route HTTPS functions to user-provided Express app
fixed - Functions emulator fails to provide correct req.path
fixed - Functions emulator fails on various malformed body requests
fixed - Functions emulator fails on Windows with EACCESS error
fixed - Fixed race condition where downloading emulators would sometimes resolve too early and fail.
fixed - Fixed a number of issues that broke functions:shell.
fixed - Fixed an issue where Firestore emulator would not start if rules file can't be found.
8 changes: 8 additions & 0 deletions src/emulator/functionsEmulatorRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import * as path from "path";
import * as admin from "firebase-admin";
import * as bodyParser from "body-parser";
import { EventUtils } from "./events/types";
import * as fs from "fs";
import { URL } from "url";

let app: admin.app.App;
let adminModuleProxy: typeof admin;
Expand Down Expand Up @@ -535,6 +537,12 @@ async function ProcessHTTPS(frb: FunctionsRuntimeBundle, trigger: EmulatedTrigge
res.on("finish", () => {
instance.close();
resolveEphemeralServer();

// If we're on a Unix platform, then the pipe is not cleaned up automatically so...
if (process.platform !== "win32") {
// We manually remove the pipe file
fs.unlinkSync(socketPath);
}
});

await RunHTTPS([req, res], func);
Expand Down
8 changes: 7 additions & 1 deletion src/emulator/functionsEmulatorShared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,13 @@ export function getEmulatedTriggersFromDefinitions(
}

export function getTemporarySocketPath(pid: number): string {
return path.join(os.tmpdir(), `firebase_emulator_invocation_${pid}.sock`);
// See "net" package docs for information about IPC pipes on Windows
// https://nodejs.org/api/net.html#net_identifying_paths_for_ipc_connections
if (process.platform === "win32") {
return path.join("\\\\?\\pipe", process.cwd(), pid.toString());
} else {
return path.join(os.tmpdir(), `firebase_emulator_invocation_${pid}.sock`);
}
}

export function getFunctionRegion(def: EmulatedTriggerDefinition): string {
Expand Down
57 changes: 42 additions & 15 deletions src/test/emulators/functionsEmulatorRuntime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,61 @@ function _is_verbose(runtime: FunctionsRuntimeInstance): void {
describe("FunctionsEmulator-Runtime", () => {
describe("Stubs, Mocks, and Helpers (aka Magic, Glee, and Awesomeness)", () => {
describe("_InitializeNetworkFiltering(...)", () => {
it("should log outgoing HTTPS requests", async () => {
it("should log outgoing unknown HTTP requests via 'http'", async () => {
const runtime = InvokeRuntimeWithFunctions(FunctionRuntimeBundles.onCreate, () => {
require("firebase-admin").initializeApp();
return {
function_id: require("firebase-functions")
.firestore.document("test/test")
.onCreate(async () => {
await Promise.all([
require("node-fetch")("https://httpstat.us/302"),
require("node-fetch")("https://storage.googleapis.com/"),
new Promise((resolve) => {
require("http").get("http://example.com", resolve);
}),
new Promise((resolve) => {
require("https").get("https://example.com", resolve);
}),
]);
await new Promise((resolve) => {
// tslint:disable-next-line:no-console
console.log(require("http").get.toString());
require("http").get("http://example.com", resolve);
});
}),
};
});

const logs = await _countLogEntries(runtime);
expect(logs["unidentified-network-access"]).to.gte(1);
}).timeout(TIMEOUT_LONG);

it("should log outgoing unknown HTTP requests via 'https'", async () => {
const runtime = InvokeRuntimeWithFunctions(FunctionRuntimeBundles.onCreate, () => {
require("firebase-admin").initializeApp();
return {
function_id: require("firebase-functions")
.firestore.document("test/test")
.onCreate(async () => {
await new Promise((resolve) => {
require("https").get("https://example.com", resolve);
});
}),
};
});

const logs = await _countLogEntries(runtime);

// In Node 6 we get >=5 events here, Node 8+ gets >=4 because of changes to
// HTTP libraries, either is fine because we'll whitelist / deny the request
// after the first prompt.
expect(logs["unidentified-network-access"]).to.gte(1);
}).timeout(TIMEOUT_LONG);

it("should log outgoing Google API requests", async () => {
const runtime = InvokeRuntimeWithFunctions(FunctionRuntimeBundles.onCreate, () => {
require("firebase-admin").initializeApp();
return {
function_id: require("firebase-functions")
.firestore.document("test/test")
.onCreate(async () => {
await new Promise((resolve) => {
require("https").get("https://storage.googleapis.com", resolve);
});
}),
};
});

const logs = await _countLogEntries(runtime);

expect(logs["unidentified-network-access"]).to.gte(3);
expect(logs["googleapis-network-access"]).to.gte(1);
}).timeout(TIMEOUT_LONG);
});
Expand Down

0 comments on commit fd8bace

Please sign in to comment.