Archived
1
0

Provide WsRouter to plugins

This commit is contained in:
Asher
2021-01-20 14:11:08 -06:00
parent fb37473e72
commit 055e0ef9ec
8 changed files with 101 additions and 34 deletions

View File

@ -7,6 +7,7 @@ import * as pluginapi from "../../typings/pluginapi"
import { version } from "./constants"
import { proxy } from "./proxy"
import * as util from "./util"
import { Router as WsRouter, WebsocketRouter } from "./wsRouter"
const fsp = fs.promises
/**
@ -21,6 +22,7 @@ require("module")._load = function (request: string, parent: object, isMain: boo
express,
field,
proxy,
WsRouter,
}
}
return originalLoad.apply(this, [request, parent, isMain])
@ -103,14 +105,16 @@ export class PluginAPI {
}
/**
* mount mounts all plugin routers onto r.
* mount mounts all plugin routers onto r and websocket routers onto wr.
*/
public mount(r: express.Router): void {
public mount(r: express.Router, wr: express.Router): void {
for (const [, p] of this.plugins) {
if (!p.router) {
continue
if (p.router) {
r.use(`${p.routerPath}`, p.router())
}
if (p.wsRouter) {
wr.use(`${p.routerPath}`, (p.wsRouter() as WebsocketRouter).router)
}
r.use(`${p.routerPath}`, p.router())
}
}

View File

@ -6,20 +6,20 @@ import { promises as fs } from "fs"
import http from "http"
import * as path from "path"
import * as tls from "tls"
import * as pluginapi from "../../../typings/pluginapi"
import { HttpCode, HttpError } from "../../common/http"
import { plural } from "../../common/util"
import { AuthType, DefaultedArgs } from "../cli"
import { rootPath } from "../constants"
import { Heart } from "../heart"
import { replaceTemplates, redirect } from "../http"
import { redirect, replaceTemplates } from "../http"
import { PluginAPI } from "../plugin"
import { getMediaMime, paths } from "../util"
import { WebsocketRequest } from "../wsRouter"
import * as apps from "./apps"
import * as domainProxy from "./domainProxy"
import * as health from "./health"
import * as login from "./login"
import * as proxy from "./pathProxy"
import * as pathProxy from "./pathProxy"
// static is a reserved keyword.
import * as _static from "./static"
import * as update from "./update"
@ -104,21 +104,21 @@ export const register = async (
wsApp.use("/", domainProxy.wsRouter.router)
app.all("/proxy/(:port)(/*)?", (req, res) => {
proxy.proxy(req, res)
pathProxy.proxy(req, res)
})
wsApp.get("/proxy/(:port)(/*)?", (req, res) => {
proxy.wsProxy(req as WebsocketRequest)
wsApp.get("/proxy/(:port)(/*)?", (req) => {
pathProxy.wsProxy(req as pluginapi.WebsocketRequest)
})
// These two routes pass through the path directly.
// So the proxied app must be aware it is running
// under /absproxy/<someport>/
app.all("/absproxy/(:port)(/*)?", (req, res) => {
proxy.proxy(req, res, {
pathProxy.proxy(req, res, {
passthroughPath: true,
})
})
wsApp.get("/absproxy/(:port)(/*)?", (req, res) => {
proxy.wsProxy(req as WebsocketRequest, {
wsApp.get("/absproxy/(:port)(/*)?", (req) => {
pathProxy.wsProxy(req as pluginapi.WebsocketRequest, {
passthroughPath: true,
})
})
@ -146,7 +146,7 @@ export const register = async (
const papi = new PluginAPI(logger, process.env.CS_PLUGIN, process.env.CS_PLUGIN_PATH)
await papi.loadPlugins()
papi.mount(app)
papi.mount(app, wsApp)
app.use("/api/applications", apps.router(papi))
app.use(() => {
@ -187,7 +187,7 @@ export const register = async (
const wsErrorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
logger.error(`${err.message} ${err.stack}`)
;(req as WebsocketRequest).ws.end()
;(req as pluginapi.WebsocketRequest).ws.end()
}
wsApp.use(wsErrorHandler)

View File

@ -1,11 +1,11 @@
import { Request, Response } from "express"
import * as path from "path"
import qs from "qs"
import * as pluginapi from "../../../typings/pluginapi"
import { HttpCode, HttpError } from "../../common/http"
import { normalize } from "../../common/util"
import { authenticated, ensureAuthenticated, redirect } from "../http"
import { proxy as _proxy } from "../proxy"
import { WebsocketRequest } from "../wsRouter"
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
if (passthroughPath) {
@ -46,7 +46,7 @@ export function proxy(
}
export function wsProxy(
req: WebsocketRequest,
req: pluginapi.WebsocketRequest,
opts?: {
passthroughPath?: boolean
},

View File

@ -1,7 +1,7 @@
import * as express from "express"
import * as expressCore from "express-serve-static-core"
import * as http from "http"
import * as net from "net"
import * as pluginapi from "../../typings/pluginapi"
export const handleUpgrade = (app: express.Express, server: http.Server): void => {
server.on("upgrade", (req, socket, head) => {
@ -20,31 +20,20 @@ export const handleUpgrade = (app: express.Express, server: http.Server): void =
})
}
export interface WebsocketRequest extends express.Request {
ws: net.Socket
head: Buffer
}
interface InternalWebsocketRequest extends WebsocketRequest {
interface InternalWebsocketRequest extends pluginapi.WebsocketRequest {
_ws_handled: boolean
}
export type WebSocketHandler = (
req: WebsocketRequest,
res: express.Response,
next: express.NextFunction,
) => void | Promise<void>
export class WebsocketRouter {
public readonly router = express.Router()
public ws(route: expressCore.PathParams, ...handlers: WebSocketHandler[]): void {
public ws(route: expressCore.PathParams, ...handlers: pluginapi.WebSocketHandler[]): void {
this.router.get(
route,
...handlers.map((handler) => {
const wrapped: express.Handler = (req, res, next) => {
;(req as InternalWebsocketRequest)._ws_handled = true
return handler(req as WebsocketRequest, res, next)
return handler(req as pluginapi.WebsocketRequest, res, next)
}
return wrapped
}),