This commit is contained in:
+38
-12
@@ -1,9 +1,13 @@
|
||||
/*
|
||||
* Single-file binary entry point (compiled with `bun build --compile`).
|
||||
*
|
||||
* Not part of upstream. Copied to the server submodule root by scripts/apply.sh.
|
||||
* The built UI is embedded into the binary as `ui.tar.gz` (created by
|
||||
* scripts/build.sh) and extracted to a temp dir on first run.
|
||||
* Not part of upstream. Copied to the server clone root by scripts/patch.sh.
|
||||
* Two archives are embedded into the binary by scripts/build.sh and extracted to
|
||||
* a temp dir on first run:
|
||||
* - ui.tar.gz the built web UI, served over HTTP
|
||||
* - overrides.tar.gz the interception overrides tree (terminal shims, the JVM
|
||||
* agent, frida, the browser webextension) that upstream
|
||||
* expects to find on disk at APP_ROOT/overrides
|
||||
*
|
||||
* Usage: httptoolkit [--port 8080] [--server-port 45457] [--mockttp-port 45456] [--no-open]
|
||||
*/
|
||||
@@ -17,11 +21,16 @@ import * as fs from 'fs';
|
||||
import * as fsp from 'fs/promises';
|
||||
import { x as extractTar } from 'tar';
|
||||
|
||||
import { startHtkApp } from './src/htk-app';
|
||||
import { SERVER_VERSION } from './src/constants';
|
||||
|
||||
// Embedded UI bundle. Resolves to a path Bun can read from the compiled binary:
|
||||
// Embedded archives. These resolve to paths Bun can read from the compiled binary:
|
||||
import uiArchive from './ui.tar.gz' with { type: 'file' };
|
||||
import overridesArchive from './overrides.tar.gz' with { type: 'file' };
|
||||
|
||||
// Deliberately NOT imported from './src/constants': that module computes APP_ROOT
|
||||
// at load time, and we have to set HTK_APP_ROOT before it is ever evaluated (see
|
||||
// main()). package.json carries the version without pulling in any of that.
|
||||
import pkg from './package.json';
|
||||
|
||||
const SERVER_VERSION: string = pkg.version;
|
||||
|
||||
function printHelp() {
|
||||
console.log(`HTTP Toolkit (self-hosted single binary) v${SERVER_VERSION}
|
||||
@@ -64,16 +73,18 @@ function parseArgs(argv: string[]) {
|
||||
return opts;
|
||||
}
|
||||
|
||||
async function extractUi(): Promise<string> {
|
||||
const dir = path.join(os.tmpdir(), `httptoolkit-ui-${SERVER_VERSION}`);
|
||||
// Extract one embedded tarball into `dir`, unless it's already there for this
|
||||
// version. Modes are preserved, which matters: overrides/path holds executable
|
||||
// shims that only work if they stay +x.
|
||||
async function extractArchive(archivePath: string, dir: string): Promise<string> {
|
||||
const marker = path.join(dir, '.extracted');
|
||||
if (fs.existsSync(marker)) return dir; // already extracted for this version
|
||||
|
||||
await fsp.rm(dir, { recursive: true, force: true });
|
||||
await fsp.mkdir(dir, { recursive: true });
|
||||
|
||||
const bytes = new Uint8Array(await Bun.file(uiArchive).arrayBuffer());
|
||||
const tmpArchive = path.join(dir, 'ui.tar.gz');
|
||||
const bytes = new Uint8Array(await Bun.file(archivePath).arrayBuffer());
|
||||
const tmpArchive = path.join(dir, 'archive.tar.gz');
|
||||
await fsp.writeFile(tmpArchive, bytes);
|
||||
|
||||
await extractTar({ file: tmpArchive, cwd: dir });
|
||||
@@ -84,7 +95,22 @@ async function extractUi(): Promise<string> {
|
||||
|
||||
async function main() {
|
||||
const opts = parseArgs(process.argv.slice(2));
|
||||
const uiDir = await extractUi();
|
||||
|
||||
// One app root per version, laid out the way upstream expects to find it:
|
||||
// <tmp>/httptoolkit-<version>/ui
|
||||
// <tmp>/httptoolkit-<version>/overrides
|
||||
const appRoot = path.join(os.tmpdir(), `httptoolkit-${SERVER_VERSION}`);
|
||||
const uiDir = path.join(appRoot, 'ui');
|
||||
|
||||
await extractArchive(uiArchive, uiDir);
|
||||
await extractArchive(overridesArchive, path.join(appRoot, 'overrides'));
|
||||
|
||||
// Must be set before ./src/constants is evaluated, since APP_ROOT (and hence
|
||||
// OVERRIDES_DIR) is computed once at module load. That's why the app is pulled
|
||||
// in with a dynamic import here rather than a static one at the top of the file.
|
||||
process.env.HTK_APP_ROOT = appRoot;
|
||||
|
||||
const { startHtkApp } = await import('./src/htk-app');
|
||||
await startHtkApp({ ...opts, uiDir });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user