Initial commit — OFApp client + server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
90
server/index.js
Normal file
90
server/index.js
Normal file
@@ -0,0 +1,90 @@
|
||||
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();
|
||||
Reference in New Issue
Block a user