|
|
|
/** Constructs the base URL from the headers from the given request. */
|
|
|
|
import fastify, {FastifyInstance, FastifyRequest} from "fastify";
|
|
|
|
import {Server, ServerOptions, ServerRequestHandler} from "slash-create";
|
|
|
|
|
|
|
|
export function getBaseUrl(request: FastifyRequest): string {
|
|
|
|
const hostHeader = request.hostname ?? "localhost"
|
|
|
|
const proto = getFirstValue(request.headers["x-forwarded-proto"]) ?? "http"
|
|
|
|
const path = getFirstValue(request.headers["x-base-path"]) ?? "/"
|
|
|
|
return `${proto}://${hostHeader}${path}`
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Translates a zero-to-many set of strings to one or zero strings. */
|
|
|
|
export function getFirstValue(value: string | string[] | undefined): string | undefined {
|
|
|
|
return typeof value === "string" ? value : Array.isArray(value) ? value[0] : undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A server for Fastify applications.
|
|
|
|
* @see https://fastify.io
|
|
|
|
*/
|
|
|
|
export class FastifyServerButItWorksUnlikeTheRealOne extends Server {
|
|
|
|
readonly app: FastifyInstance;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param app The fastify application
|
|
|
|
* @param opts The server options
|
|
|
|
*/
|
|
|
|
constructor(app?: FastifyInstance, opts?: ServerOptions) {
|
|
|
|
super(opts);
|
|
|
|
this.app = app || fastify();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds middleware to the Fastify server.
|
|
|
|
* <warn>This requires you to have the 'middie' module registered to the server before using.</warn>
|
|
|
|
* @param middleware The middleware to add.
|
|
|
|
* @see https://www.fastify.io/docs/latest/Middleware/
|
|
|
|
*/
|
|
|
|
addMiddleware(middleware: Function) {
|
|
|
|
// @ts-ignore
|
|
|
|
if ('use' in this.app) this.app.use(middleware);
|
|
|
|
else
|
|
|
|
throw new Error(
|
|
|
|
"In order to use Express-like middleware, you must initialize the server and register the 'middie' module."
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Alias for {@link FastifyServerButItWorksUnlikeTheRealOne#addMiddleware} */
|
|
|
|
use(middleware: Function) {
|
|
|
|
return this.addMiddleware(middleware);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @private */
|
|
|
|
createEndpoint(path: string, handler: ServerRequestHandler) {
|
|
|
|
this.app.post(path, (req: any, res: any) =>
|
|
|
|
handler(
|
|
|
|
{
|
|
|
|
headers: req.headers,
|
|
|
|
body: req.body,
|
|
|
|
request: req,
|
|
|
|
response: res
|
|
|
|
},
|
|
|
|
async (response) => {
|
|
|
|
res.status(response.status || 200);
|
|
|
|
if (response.headers) res.headers(response.headers);
|
|
|
|
res.send(response.body);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @private */
|
|
|
|
async listen(port = 8030, host = 'localhost') {
|
|
|
|
if (this.alreadyListening) return;
|
|
|
|
await this.app.listen(port, host);
|
|
|
|
}
|
|
|
|
}
|