feat: integrate FIR library and AI FIR controls
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/** Development relay for FIR WAV POSTs and GETs to private IPv4 devices. */
|
||||
import http from 'node:http';
|
||||
import type { Plugin } from 'vite';
|
||||
export function firDevProxy(): Plugin {
|
||||
return { name: 'fir-device-dev-proxy', apply: 'serve', configureServer(server) {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (!req.url?.startsWith('/fir-device/')) return next();
|
||||
const match = /^\/fir-device\/(\d+\.\d+\.\d+\.\d+)\/(left|right)$/.exec(req.url);
|
||||
const octets = match?.[1].split('.').map(Number);
|
||||
const privateIp = octets && octets.every(n => n >= 0 && n <= 255) &&
|
||||
(octets[0] === 10 || (octets[0] === 192 && octets[1] === 168) || (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31));
|
||||
if (!['GET', 'POST'].includes(req.method || '') || !match || !privateIp) { res.statusCode = 400; res.end('Invalid FIR device request'); return; }
|
||||
const length = Number(req.headers['content-length']);
|
||||
if (req.method === 'POST' && ![32822, 32826].includes(length)) { res.statusCode = 422; res.end('Invalid FIR payload size'); return; }
|
||||
let upstreamResponse: http.IncomingMessage | undefined;
|
||||
const upstream = http.request({ hostname: match[1], port: 80, method: req.method, agent: false,
|
||||
path: `/dev/info.cgi?action=fir&channel=${match[2]}`,
|
||||
headers: req.method === 'POST' ? { 'Content-Type': 'audio/wav', 'Content-Length': length } : {},
|
||||
}, response => {
|
||||
upstreamResponse = response;
|
||||
res.statusCode = response.statusCode || 502;
|
||||
res.setHeader('Content-Type', response.headers['content-type'] || 'text/plain');
|
||||
response.pipe(res);
|
||||
response.on('error', () => res.destroy());
|
||||
});
|
||||
upstream.setTimeout(3500, () => upstream.destroy(new Error('Device upload timed out')));
|
||||
upstream.on('error', () => {
|
||||
// Firmware can append bytes after Content-Length. Node reports a parse error
|
||||
// for that tail even when the entire declared WAV has already arrived.
|
||||
if (upstreamResponse?.complete) return;
|
||||
if (!res.headersSent) { res.statusCode = 502; res.end('Device FIR upload failed'); } else res.destroy(); });
|
||||
req.on('aborted', () => upstream.destroy());
|
||||
req.pipe(upstream);
|
||||
});
|
||||
}};
|
||||
}
|
||||
Reference in New Issue
Block a user