mirror of
https://github.com/ad1217/PrinterStatus
synced 2024-11-21 15:03:48 -05:00
server: Switch from generic http-proxy
to mjpeg-proxy
for webcam streams
This commit is contained in:
parent
5d19c77dce
commit
ecd5185dc4
101
server/package-lock.json
generated
101
server/package-lock.json
generated
@ -7,15 +7,14 @@
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "^5.0.2",
|
||||
"http-proxy": "^1.18.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"mjpeg-proxy": "^0.3.0",
|
||||
"node-fetch": "^2.6.5",
|
||||
"ws": "^8.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/express-ws": "^3.0.0",
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
"@types/js-yaml": "^4.0.3",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
@ -122,15 +121,6 @@
|
||||
"@types/ws": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-proxy": {
|
||||
"version": "1.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
|
||||
"integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-yaml": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz",
|
||||
@ -388,11 +378,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
@ -484,25 +469,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
||||
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||
@ -548,19 +514,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^4.0.0",
|
||||
"follow-redirects": "^1.0.0",
|
||||
"requires-port": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@ -653,6 +606,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mjpeg-proxy": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mjpeg-proxy/-/mjpeg-proxy-0.3.0.tgz",
|
||||
"integrity": "sha512-XpdOIPIw/as8djKkJyiT1YaxlM10vqA/KJmymnVl+bZcZYdLrNPYJjkJt+x+5I77vLxyD8QmDbmJrpb63YyRJw==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
@ -743,11 +704,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@ -1053,15 +1009,6 @@
|
||||
"@types/ws": "*"
|
||||
}
|
||||
},
|
||||
"@types/http-proxy": {
|
||||
"version": "1.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
|
||||
"integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/js-yaml": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz",
|
||||
@ -1274,11 +1221,6 @@
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
@ -1346,11 +1288,6 @@
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
||||
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||
@ -1384,16 +1321,6 @@
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"http-proxy": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||
"requires": {
|
||||
"eventemitter3": "^4.0.0",
|
||||
"follow-redirects": "^1.0.0",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
@ -1459,6 +1386,11 @@
|
||||
"mime-db": "1.50.0"
|
||||
}
|
||||
},
|
||||
"mjpeg-proxy": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mjpeg-proxy/-/mjpeg-proxy-0.3.0.tgz",
|
||||
"integrity": "sha512-XpdOIPIw/as8djKkJyiT1YaxlM10vqA/KJmymnVl+bZcZYdLrNPYJjkJt+x+5I77vLxyD8QmDbmJrpb63YyRJw=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
@ -1525,11 +1457,6 @@
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
|
@ -2,7 +2,6 @@
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/express-ws": "^3.0.0",
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
"@types/js-yaml": "^4.0.3",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
@ -13,12 +12,12 @@
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"express-ws": "^5.0.2",
|
||||
"http-proxy": "^1.18.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"mjpeg-proxy": "^0.3.0",
|
||||
"node-fetch": "^2.6.5",
|
||||
"ws": "^8.2.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "ts-node ./src/server.ts"
|
||||
"start": "ts-node --files ./src/server.ts"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import * as WebSocket from 'ws';
|
||||
import fetch from 'node-fetch';
|
||||
/// <reference path="mjpeg-proxy.d.ts"/>
|
||||
import { MjpegProxy } from 'mjpeg-proxy';
|
||||
|
||||
import {ExtendedMessage} from '../../types/messages';
|
||||
import * as octoprint from '../../types/octoprint';
|
||||
@ -9,8 +11,8 @@ const PING_TIME = 10000;
|
||||
type Timeout = ReturnType<typeof setTimeout>;
|
||||
|
||||
export default class OctoprintConnection {
|
||||
public webcamURL?: URL;
|
||||
public name?: string;
|
||||
public webcamProxy?: MjpegProxy;
|
||||
protected lastStatus?: ExtendedMessage;
|
||||
|
||||
constructor(
|
||||
@ -34,7 +36,11 @@ export default class OctoprintConnection {
|
||||
|
||||
async connect_websocket() {
|
||||
const settings = await this.api_get('settings');
|
||||
this.webcamURL = new URL(settings.webcam.streamUrl, this.address);
|
||||
const webcamURL = new URL(settings.webcam.streamUrl, this.address);
|
||||
// TODO: handle recreating proxy on URL change
|
||||
if (this.webcamProxy === undefined) {
|
||||
this.webcamProxy = new MjpegProxy(webcamURL.toString());
|
||||
}
|
||||
this.name = settings.appearance.name;
|
||||
|
||||
// do passive login to get a session key from the API key
|
||||
|
12
server/src/mjpeg-proxy.d.ts
vendored
Normal file
12
server/src/mjpeg-proxy.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
declare module 'mjpeg-proxy' {
|
||||
import {Request, Response} from 'express';
|
||||
export class MjpegProxy {
|
||||
mjpegOptions: URL;
|
||||
|
||||
constructor(mjpegUrl: string | URL);
|
||||
proxyRequest(
|
||||
req: Request,
|
||||
res: Response
|
||||
): void;
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
import * as express from 'express';
|
||||
import * as httpProxy from 'http-proxy';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as expressWs from 'express-ws';
|
||||
import * as WebSocket from 'ws';
|
||||
@ -22,11 +21,6 @@ const config: configuration = yaml.load(
|
||||
fs.readFileSync('config.yaml', 'utf8')
|
||||
) as configuration;
|
||||
|
||||
const proxy = httpProxy.createProxyServer({});
|
||||
proxy.on('error', function (e) {
|
||||
console.error('Proxy failed:');
|
||||
console.error(e);
|
||||
});
|
||||
let octoprintConnections: OctoPrintConnection[] = [];
|
||||
|
||||
function broadcast(data: WebSocket.Data) {
|
||||
@ -52,9 +46,8 @@ app.get('/webcam/:printer', (req, res) => {
|
||||
let printer: OctoPrintConnection | undefined = octoprintConnections.find(
|
||||
(op) => op.slug === req.params.printer
|
||||
);
|
||||
if (printer?.webcamURL) {
|
||||
req.url = ''; // truncate the url for passing to the proxy
|
||||
proxy.web(req, res, { target: printer.webcamURL.toString() });
|
||||
if (printer?.webcamProxy) {
|
||||
return printer.webcamProxy.proxyRequest(req, res);
|
||||
} else res.status(404).send('Not Found: Printer not known or has no webcam.');
|
||||
});
|
||||
|
||||
@ -63,7 +56,12 @@ app.listen(PORT);
|
||||
function initPrinters() {
|
||||
octoprintConnections = Object.entries(config.printers).map(
|
||||
([slug, printer]) =>
|
||||
new OctoPrintConnection(slug, printer.address, printer.apikey, broadcastPayload)
|
||||
new OctoPrintConnection(
|
||||
slug,
|
||||
printer.address,
|
||||
printer.apikey,
|
||||
broadcastPayload
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user