Using Peertube v5.0.0 websocket capacities.
This commit is contained in:
parent
e7eca75736
commit
0be08c7b57
1
package-lock.json
generated
1
package-lock.json
generated
@ -25076,6 +25076,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
|
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import type { RegisterServerOptions, PeerTubeHelpers } from '@peertube/peertube-types'
|
import type { RegisterServerOptions, PeerTubeHelpers } from '@peertube/peertube-types'
|
||||||
import { Response } from 'express'
|
import type { Response } from 'express'
|
||||||
|
import type { IncomingMessage } from 'http'
|
||||||
|
import type { Duplex } from 'stream'
|
||||||
|
|
||||||
const packagejson: any = require('../../../package.json')
|
const packagejson: any = require('../../../package.json')
|
||||||
const version: string = packagejson.version || ''
|
const version: string = packagejson.version || ''
|
||||||
@ -19,14 +21,34 @@ function getBaseRouterRoute (options: RegisterServerOptions): string {
|
|||||||
return options.peertubeHelpers.plugin.getBaseRouterRoute()
|
return options.peertubeHelpers.plugin.getBaseRouterRoute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RegisterServerWebSocketRouteOptions {
|
||||||
|
route: string
|
||||||
|
handler: (request: IncomingMessage, socket: Duplex, head: Buffer) => any
|
||||||
|
}
|
||||||
|
// getBaseWebSocketRoute() comes with Peertube 5.0.0.
|
||||||
|
type RegisterServerOptionsV5 = RegisterServerOptions & {
|
||||||
|
registerWebSocketRoute?: (options: RegisterServerWebSocketRouteOptions) => void
|
||||||
|
peertubeHelpers: {
|
||||||
|
plugin: {
|
||||||
|
getBaseWebSocketRoute?: () => string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base router route, but without the plugin version.
|
* Returns the base route for Websocket endpoint.
|
||||||
|
* This features comes with Peertube >=5.0.0.
|
||||||
* @param options server options
|
* @param options server options
|
||||||
|
* @returns the route, or undefined if the Peertube version does not provide this feature
|
||||||
*/
|
*/
|
||||||
function getBaseRouterCanonicalRoute (options: RegisterServerOptions): string {
|
function getBaseWebSocketRoute (options: RegisterServerOptionsV5): string | undefined {
|
||||||
let route = getBaseRouterRoute(options)
|
if (!options.peertubeHelpers.plugin) {
|
||||||
route = route.replace(pluginShortName + '/' + version + '/', pluginShortName + '/')
|
throw new Error('Missing peertubeHelpers.plugin, have you the correct Peertube version?')
|
||||||
return route
|
}
|
||||||
|
if (!options.peertubeHelpers.plugin.getBaseWebSocketRoute) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return options.peertubeHelpers.plugin.getBaseWebSocketRoute()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBaseStaticRoute (options: RegisterServerOptions): string {
|
function getBaseStaticRoute (options: RegisterServerOptions): string {
|
||||||
@ -71,8 +93,9 @@ async function getUserNickname (options: RegisterServerOptions, user: AuthUserFi
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
RegisterServerOptionsV5,
|
||||||
getBaseRouterRoute,
|
getBaseRouterRoute,
|
||||||
getBaseRouterCanonicalRoute,
|
getBaseWebSocketRoute,
|
||||||
getBaseStaticRoute,
|
getBaseStaticRoute,
|
||||||
isUserAdmin,
|
isUserAdmin,
|
||||||
getUserNickname,
|
getUserNickname,
|
||||||
|
@ -4,7 +4,9 @@ import type {
|
|||||||
ProsodyListRoomsResult, ProsodyListRoomsResultRoom
|
ProsodyListRoomsResult, ProsodyListRoomsResultRoom
|
||||||
} from '../../../shared/lib/types'
|
} from '../../../shared/lib/types'
|
||||||
import { createProxyServer } from 'http-proxy'
|
import { createProxyServer } from 'http-proxy'
|
||||||
import { getBaseRouterRoute, getBaseRouterCanonicalRoute, getBaseStaticRoute, isUserAdmin } from '../helpers'
|
import {
|
||||||
|
RegisterServerOptionsV5, getBaseRouterRoute, getBaseWebSocketRoute, getBaseStaticRoute, isUserAdmin
|
||||||
|
} from '../helpers'
|
||||||
import { asyncMiddleware } from '../middlewares/async'
|
import { asyncMiddleware } from '../middlewares/async'
|
||||||
import { getProsodyDomain } from '../prosody/config/domain'
|
import { getProsodyDomain } from '../prosody/config/domain'
|
||||||
import { getAPIKey } from '../apikey'
|
import { getAPIKey } from '../apikey'
|
||||||
@ -14,7 +16,6 @@ import * as path from 'path'
|
|||||||
const got = require('got')
|
const got = require('got')
|
||||||
|
|
||||||
const fs = require('fs').promises
|
const fs = require('fs').promises
|
||||||
// const proxy = require('express-http-proxy')
|
|
||||||
|
|
||||||
interface ProsodyProxyInfo {
|
interface ProsodyProxyInfo {
|
||||||
host: string
|
host: string
|
||||||
@ -23,15 +24,11 @@ interface ProsodyProxyInfo {
|
|||||||
let currentProsodyProxyInfo: ProsodyProxyInfo | null = null
|
let currentProsodyProxyInfo: ProsodyProxyInfo | null = null
|
||||||
let currentHttpBindProxy: ReturnType<typeof createProxyServer> | null = null
|
let currentHttpBindProxy: ReturnType<typeof createProxyServer> | null = null
|
||||||
let currentWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
let currentWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
||||||
interface CurrentWebsocketUpgradeEvent {
|
|
||||||
server: any
|
|
||||||
listener: Function
|
|
||||||
}
|
|
||||||
let currentWebsocketUpgradeEvent: CurrentWebsocketUpgradeEvent | null = null
|
|
||||||
|
|
||||||
async function initWebchatRouter (options: RegisterServerOptions): Promise<Router> {
|
async function initWebchatRouter (options: RegisterServerOptionsV5): Promise<Router> {
|
||||||
const {
|
const {
|
||||||
getRouter,
|
getRouter,
|
||||||
|
registerWebSocketRoute,
|
||||||
peertubeHelpers,
|
peertubeHelpers,
|
||||||
settingsManager
|
settingsManager
|
||||||
} = options
|
} = options
|
||||||
@ -50,6 +47,10 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
|
|||||||
'converse-theme', 'converse-autocolors'
|
'converse-theme', 'converse-autocolors'
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const boshUri = getBaseRouterRoute(options) + 'http-bind'
|
||||||
|
let wsUri = getBaseWebSocketRoute(options) // can be undefined
|
||||||
|
wsUri = wsUri !== undefined ? wsUri + 'xmpp-websocket' : ''
|
||||||
|
|
||||||
let room: string
|
let room: string
|
||||||
let authenticationUrl: string = ''
|
let authenticationUrl: string = ''
|
||||||
let advancedControls: boolean = false // auto join the chat in viewer mode, if not logged in
|
let advancedControls: boolean = false // auto join the chat in viewer mode, if not logged in
|
||||||
@ -81,13 +82,7 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
|
|||||||
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
|
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Here we are using getBaseRouterCanonicalRoute,
|
|
||||||
// which correspond to a path without the plugin version.
|
|
||||||
// We are doing this, so the path is predictible,
|
|
||||||
// and can be optimized in the nginx configuration (to bypass Peertube).
|
|
||||||
const proxyBaseUri = getBaseRouterCanonicalRoute(options) + 'webchat/'
|
|
||||||
const boshUri = proxyBaseUri + 'http-bind'
|
|
||||||
const wsUri = proxyBaseUri + 'xmpp-websocket'
|
|
||||||
authenticationUrl = options.peertubeHelpers.config.getWebserverUrl() +
|
authenticationUrl = options.peertubeHelpers.config.getWebserverUrl() +
|
||||||
getBaseRouterRoute(options) +
|
getBaseRouterRoute(options) +
|
||||||
'api/auth'
|
'api/auth'
|
||||||
@ -229,59 +224,19 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
router.all('/xmpp-websocket',
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
// Peertube >=5.0.0: Adding the websocket route.
|
||||||
try {
|
if (registerWebSocketRoute) {
|
||||||
|
registerWebSocketRoute({
|
||||||
|
route: '/xmpp-websocket',
|
||||||
|
handler: (request, socket, head) => {
|
||||||
if (!currentWebsocketProxy) {
|
if (!currentWebsocketProxy) {
|
||||||
res.status(404)
|
throw new Error('There is no current websocket proxy, should not get here.')
|
||||||
res.send('Not found')
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
currentWebsocketProxy.ws(request, socket, head)
|
||||||
// Now, we need to attach an listener for the update event on the server...
|
|
||||||
// But we don't have access to the server.
|
|
||||||
// To get this, we will wait for the first request, and then get the server from there!
|
|
||||||
if (!currentWebsocketUpgradeEvent) {
|
|
||||||
peertubeHelpers.logger.info(
|
|
||||||
'Here is the first websocket proxy connection, we are binding the upgrade listener...'
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Get the server object to subscribe to server events;
|
|
||||||
* 'upgrade' for websocket and 'close' for graceful shutdown
|
|
||||||
*
|
|
||||||
* NOTE:
|
|
||||||
* req.socket: node >= 13
|
|
||||||
* req.connection: node < 13 (Remove this when node 12/13 support is dropped)
|
|
||||||
*
|
|
||||||
* This code was inspired by:
|
|
||||||
* https://github.com/chimurai/http-proxy-middleware, file /src/http-proxy-middleware.ts#L53
|
|
||||||
*/
|
|
||||||
const s: any = (req.socket ?? req.connection)
|
|
||||||
const server = 'server' in s ? s.server : null
|
|
||||||
if (!server) {
|
|
||||||
peertubeHelpers.logger.error('Cant access to the ExpressJS server, wont be able to handle websocket.')
|
|
||||||
} else {
|
|
||||||
currentWebsocketUpgradeEvent = {
|
|
||||||
server,
|
|
||||||
listener: (req: any, socket: any, head: any) => {
|
|
||||||
// We are not the only websocket server! Peertube has its own. We must match the url.
|
|
||||||
if (/webchat\/xmpp-websocket/.test(req.url)) {
|
|
||||||
peertubeHelpers.logger.info('Got an http upgrade event that match the correct path')
|
|
||||||
currentWebsocketProxy?.ws(req, socket, head)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server.on('upgrade', currentWebsocketUpgradeEvent.listener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.url = 'xmpp-websocket'
|
|
||||||
currentWebsocketProxy.web(req, res)
|
|
||||||
} catch (err) {
|
|
||||||
next(err)
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
}
|
||||||
|
|
||||||
router.get('/prosody-list-rooms', asyncMiddleware(
|
router.get('/prosody-list-rooms', asyncMiddleware(
|
||||||
async (req: Request, res: Response, _next: NextFunction) => {
|
async (req: Request, res: Response, _next: NextFunction) => {
|
||||||
@ -356,10 +311,6 @@ async function disableProxyRoute ({ peertubeHelpers }: RegisterServerOptions): P
|
|||||||
currentWebsocketProxy.close()
|
currentWebsocketProxy.close()
|
||||||
currentWebsocketProxy = null
|
currentWebsocketProxy = null
|
||||||
}
|
}
|
||||||
if (currentWebsocketUpgradeEvent) {
|
|
||||||
peertubeHelpers.logger.info('Removing the upgrade listener')
|
|
||||||
currentWebsocketUpgradeEvent.server.off('upgrade', currentWebsocketUpgradeEvent.listener)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
peertubeHelpers.logger.error('Seems that the http bind proxy close has failed: ' + (err as string))
|
peertubeHelpers.logger.error('Seems that the http bind proxy close has failed: ' + (err as string))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user