Skip to content

Commit

Permalink
Web frameworks simpleProxy (#5582)
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesdaniels committed Mar 30, 2023
1 parent 616e9f6 commit 6d25faa
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 64 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- The hosting emulator integration with web frameworks now has improved support for HMR and dev-tools. (#5582)
5 changes: 2 additions & 3 deletions src/frameworks/angular/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import {
SupportLevel,
} from "..";
import { promptOnce } from "../../prompt";
import { proxyRequestHandler } from "../../hosting/proxy";
import { warnIfCustomBuildScript } from "../utils";
import { simpleProxy, warnIfCustomBuildScript } from "../utils";

export const name = "Angular";
export const support = SupportLevel.Experimental;
Expand Down Expand Up @@ -106,7 +105,7 @@ export async function getDevModeHandle(dir: string) {
process.stderr.write(data);
});
});
return proxyRequestHandler(await host, "Angular Live Development Server", { forceCascade: true });
return simpleProxy(await host);
}

export async function ɵcodegenPublicDirectory(sourceDir: string, destDir: string) {
Expand Down
59 changes: 7 additions & 52 deletions src/frameworks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,9 @@ export async function prepareFrameworks(
}
}
}
if (firebaseDefaults) process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
if (firebaseDefaults) {
process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
}
const results = await discover(getProjectPath());
if (!results) throw new Error("Epic fail.");
const { framework, mayWantBackend, publicDirectory } = results;
Expand Down Expand Up @@ -442,7 +444,10 @@ export async function prepareFrameworks(
}
config.webFramework = `${framework}${codegenFunctionsDirectory ? "_ssr" : ""}`;
if (codegenFunctionsDirectory) {
if (firebaseDefaults) firebaseDefaults._authTokenSyncURL = "/__session";
if (firebaseDefaults) {
firebaseDefaults._authTokenSyncURL = "/__session";
process.env.__FIREBASE_DEFAULTS__ = JSON.stringify(firebaseDefaults);
}

const rewrite: HostingRewrites = {
source: "**",
Expand Down Expand Up @@ -625,53 +630,3 @@ function codegenDevModeFunctionsDirectory() {
const packageJson = {};
return Promise.resolve({ packageJson, frameworksEntry: "_devMode" });
}

/**
*
*/
export function createServerResponseProxy(
req: IncomingMessage,
res: ServerResponse,
next: () => void
) {
const proxiedRes = new ServerResponse(req);
const buffer: [string, any[]][] = [];
proxiedRes.write = new Proxy(proxiedRes.write.bind(proxiedRes), {
apply: (target: any, thisArg, args) => {
target.call(thisArg, ...args);
buffer.push(["write", args]);
},
});
proxiedRes.setHeader = new Proxy(proxiedRes.setHeader.bind(proxiedRes), {
apply: (target: any, thisArg, args) => {
target.call(thisArg, ...args);
buffer.push(["setHeader", args]);
},
});
proxiedRes.removeHeader = new Proxy(proxiedRes.removeHeader.bind(proxiedRes), {
apply: (target: any, thisArg, args) => {
target.call(thisArg, ...args);
buffer.push(["removeHeader", args]);
},
});
proxiedRes.writeHead = new Proxy(proxiedRes.writeHead.bind(proxiedRes), {
apply: (target: any, thisArg, args) => {
target.call(thisArg, ...args);
buffer.push(["writeHead", args]);
},
});
proxiedRes.end = new Proxy(proxiedRes.end.bind(proxiedRes), {
apply: (target: any, thisArg, args) => {
target.call(thisArg, ...args);
if (proxiedRes.statusCode === 404) {
next();
} else {
for (const [fn, args] of buffer) {
(res as any)[fn](...args);
}
res.end(...args);
}
},
});
return proxiedRes;
}
10 changes: 4 additions & 6 deletions src/frameworks/next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { streamObject } from "stream-json/streamers/StreamObject";

import {
BuildResult,
createServerResponseProxy,
findDependency,
FrameworkType,
NODE_VERSION,
Expand All @@ -40,7 +39,7 @@ import {
allDependencyNames,
} from "./utils";
import type { Manifest, NpmLsDepdendency } from "./interfaces";
import { readJSON } from "../utils";
import { readJSON, simpleProxy } from "../utils";
import { warnIfCustomBuildScript } from "../utils";
import type { EmulatorInfo } from "../../emulator/types";
import { usesAppDirRouter, usesNextImage, hasUnoptimizedImage } from "./utils";
Expand Down Expand Up @@ -444,11 +443,10 @@ export async function getDevModeHandle(dir: string, hostingEmulatorInfo?: Emulat
const handler = nextApp.getRequestHandler();
await nextApp.prepare();

return (req: IncomingMessage, res: ServerResponse, next: () => void) => {
return simpleProxy(async (req: IncomingMessage, res: ServerResponse) => {
const parsedUrl = parse(req.url!, true);
const proxy = createServerResponseProxy(req, res, next);
handler(req, proxy, parsedUrl);
};
await handler(req, res, parsedUrl);
});
}

async function getConfig(dir: string): Promise<NextConfig & { distDir: string }> {
Expand Down
52 changes: 52 additions & 0 deletions src/frameworks/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { readJSON as originalReadJSON } from "fs-extra";
import type { ReadOptions } from "fs-extra";
import { join } from "path";
import { readFile } from "fs/promises";
import { IncomingMessage, request as httpRequest, ServerResponse, Agent } from "http";
import { logger } from "../logger";

/**
* Whether the given string starts with http:// or https://
Expand Down Expand Up @@ -39,3 +41,53 @@ export async function warnIfCustomBuildScript(
);
}
}

type RequestHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;

export function simpleProxy(hostOrRequestHandler: string | RequestHandler) {
const agent = new Agent({ keepAlive: true });
return async (originalReq: IncomingMessage, originalRes: ServerResponse, next: () => void) => {
const { method, headers, url: path } = originalReq;
if (!method || !path) {
return originalRes.end();
}
// If the path is a the auth token sync URL pass through to Cloud Functions
const firebaseDefaultsJSON = process.env.__FIREBASE_DEFAULTS__;
const authTokenSyncURL: string | undefined =
firebaseDefaultsJSON && JSON.parse(firebaseDefaultsJSON)._authTokenSyncURL;
if (path === authTokenSyncURL) {
return next();
}
if (typeof hostOrRequestHandler === "string") {
const host = hostOrRequestHandler;
const { hostname, port, protocol, username, password } = new URL(host);
const auth = username || password ? `${username}:${password}` : undefined;
const opts = {
agent,
auth,
protocol,
hostname,
port,
path,
method,
headers: {
...headers,
host,
"X-Forwarded-Host": headers.host,
},
};
const req = httpRequest(opts, (response) => {
const { statusCode, statusMessage, headers } = response;
originalRes.writeHead(statusCode!, statusMessage, headers);
response.pipe(originalRes);
});
originalReq.pipe(req);
req.on("error", (err) => {
logger.debug("Error encountered while proxying request:", method, path, err);
originalRes.end();
});
} else {
await hostOrRequestHandler(originalReq, originalRes);
}
};
}
5 changes: 2 additions & 3 deletions src/frameworks/vite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { existsSync } from "fs";
import { copy, pathExists } from "fs-extra";
import { join } from "path";
import { findDependency, FrameworkType, relativeRequire, SupportLevel } from "..";
import { proxyRequestHandler } from "../../hosting/proxy";
import { promptOnce } from "../../prompt";
import { warnIfCustomBuildScript } from "../utils";
import { simpleProxy, warnIfCustomBuildScript } from "../utils";

export const name = "Vite";
export const support = SupportLevel.Experimental;
Expand Down Expand Up @@ -92,7 +91,7 @@ export async function getDevModeHandle(dir: string) {
process.stderr.write(data);
});
});
return proxyRequestHandler(await host, "Vite Development Server", { forceCascade: true });
return simpleProxy(await host);
}

async function getConfig(root: string) {
Expand Down

0 comments on commit 6d25faa

Please sign in to comment.