mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
* Add support for unix sockets with (unix://) scheme * Add support for listening socket FD (fd+listening:// scheme) * Add support for connected socket FD (fd+connected:// scheme) --------- Co-authored-by: Addison Beck <github@addisonbeck.com>
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
import http from "node:http";
|
|
import net from "node:net";
|
|
|
|
import * as koaRouter from "@koa/router";
|
|
import { OptionValues } from "commander";
|
|
import * as koa from "koa";
|
|
import * as koaBodyParser from "koa-bodyparser";
|
|
import * as koaJson from "koa-json";
|
|
|
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
|
|
|
import { OssServeConfigurator } from "../oss-serve-configurator";
|
|
import { ServiceContainer } from "../service-container/service-container";
|
|
|
|
export class ServeCommand {
|
|
constructor(
|
|
protected serviceContainer: ServiceContainer,
|
|
protected serveConfigurator: OssServeConfigurator,
|
|
) {}
|
|
|
|
async run(options: OptionValues) {
|
|
const protectOrigin = !options.disableOriginProtection;
|
|
const port = options.port || 8087;
|
|
const hostname = options.hostname || "localhost";
|
|
this.serviceContainer.logService.info(
|
|
`Starting server on ${hostname}:${port} with ${
|
|
protectOrigin ? "origin protection" : "no origin protection"
|
|
}`,
|
|
);
|
|
|
|
const server = new koa();
|
|
const router = new koaRouter();
|
|
process.env.BW_SERVE = "true";
|
|
process.env.BW_NOINTERACTION = "true";
|
|
|
|
server
|
|
.use(async (ctx, next) => {
|
|
if (protectOrigin && ctx.headers.origin != undefined) {
|
|
ctx.status = 403;
|
|
this.serviceContainer.logService.warning(
|
|
`Blocking request from "${
|
|
Utils.isNullOrEmpty(ctx.headers.origin)
|
|
? "(Origin header value missing)"
|
|
: ctx.headers.origin
|
|
}"`,
|
|
);
|
|
return;
|
|
}
|
|
await next();
|
|
})
|
|
.use(koaBodyParser())
|
|
.use(koaJson({ pretty: false, param: "pretty" }));
|
|
|
|
this.serveConfigurator.configureRouter(router);
|
|
|
|
server.use(router.routes()).use(router.allowedMethods());
|
|
|
|
if (hostname.startsWith("fd+connected://")) {
|
|
const fd = parseInt(hostname.slice("fd+connected://".length));
|
|
const httpServer = http.createServer(server.callback());
|
|
const socket = new net.Socket({ fd: fd, readable: true, writable: true });
|
|
// allow idle sockets, incomplete handshakes and slow requests
|
|
httpServer.keepAliveTimeout = 0;
|
|
httpServer.headersTimeout = 0;
|
|
httpServer.timeout = 0;
|
|
socket.pause();
|
|
httpServer.emit("connection", socket);
|
|
socket.resume(); // Let the HTTP parser start reading
|
|
} else if (hostname.startsWith("fd+listening://")) {
|
|
const fd = parseInt(hostname.slice("fd+listening://".length));
|
|
server.listen({ fd }, () => {
|
|
this.serviceContainer.logService.info("Listening on " + hostname);
|
|
});
|
|
} else if (hostname.startsWith("unix://")) {
|
|
const socketPath = hostname.slice("unix://".length);
|
|
server.listen(socketPath, () => {
|
|
this.serviceContainer.logService.info("Listening on " + hostname);
|
|
});
|
|
} else {
|
|
server.listen(port, hostname === "all" ? null : hostname, () => {
|
|
this.serviceContainer.logService.info("Listening on " + hostname + ":" + port);
|
|
});
|
|
}
|
|
}
|
|
}
|