Files
OFApp/server/index.js
Trey t c60de19348 Initial commit — OFApp client + server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:07:06 -06:00

91 lines
2.9 KiB
JavaScript

import express from 'express';
import https from 'https';
import cors from 'cors';
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { initRules } from './signing.js';
import proxyRouter from './proxy.js';
import downloadRouter from './download.js';
import galleryRouter from './gallery.js';
import hlsRouter from './hls.js';
import settingsRouter from './settings.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const PORT = process.env.PORT || 3001;
const HTTPS_PORT = process.env.HTTPS_PORT || 3443;
app.use(cors());
// Parse DRM license request bodies as raw binary BEFORE global JSON parser
// (express.json can interfere with reading the raw body stream)
app.use('/api/drm-license', express.raw({ type: '*/*', limit: '1mb' }));
app.use(express.json());
// API routes
app.use(proxyRouter);
app.use(downloadRouter);
app.use(galleryRouter);
app.use(hlsRouter);
app.use(settingsRouter);
// Serve static client build in production
const clientDist = join(__dirname, '..', 'client', 'dist');
if (existsSync(clientDist)) {
app.use(express.static(clientDist));
app.get('*', (req, res) => {
if (req.path.startsWith('/api/')) return res.status(404).json({ error: 'Not found' });
res.sendFile(join(clientDist, 'index.html'));
});
}
// Error handler
app.use((err, req, res, _next) => {
console.error('[server] Error:', err.message);
res.status(500).json({ error: err.message || 'Internal server error' });
});
async function start() {
try {
await initRules();
} catch (err) {
console.error('[server] Failed to load signing rules:', err.message);
console.error('[server] Signing will not work until rules are available');
}
app.listen(PORT, () => {
console.log(`[server] Listening on http://localhost:${PORT}`);
});
// Start HTTPS server for DRM/EME support (requires secure context)
try {
const certDir = '/data/certs';
const certPath = `${certDir}/server.crt`;
const keyPath = `${certDir}/server.key`;
if (!existsSync(certPath) || !existsSync(keyPath)) {
mkdirSync(certDir, { recursive: true });
execSync(`openssl req -x509 -newkey rsa:2048 -keyout ${keyPath} -out ${certPath} -days 3650 -nodes -subj '/CN=ofapp'`);
console.log('[server] Generated self-signed HTTPS certificate');
}
const httpsServer = https.createServer({
key: readFileSync(keyPath),
cert: readFileSync(certPath),
}, app);
httpsServer.listen(HTTPS_PORT, () => {
console.log(`[server] HTTPS listening on https://localhost:${HTTPS_PORT}`);
});
} catch (err) {
console.error('[server] HTTPS setup failed:', err.message);
console.error('[server] DRM video playback will not work without HTTPS');
}
}
start();