Pick a language, copy the server, deploy it — it accepts a POST / JSON envelope and forwards the request. Each server prints the port it is listening on at startup.
import express from 'express';
import axios from 'axios';
const PORT = parseInt(process.env.PORT || '8080', 10);
const HOST = process.env.HOST || '0.0.0.0';
const TIMEOUT_MS = parseInt(process.env.TIMEOUT_MS || '45000', 10);
const MAX_BODY = process.env.MAX_BODY || '20mb';
const app = express();
app.use(express.json({ limit: MAX_BODY }));
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', '*');
res.setHeader('Access-Control-Max-Age', '86400');
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
app.post('/', async (req, res) => {
const env = req.body;
// ---- validate envelope ----
if (!env || typeof env !== 'object') {
return res.status(400).json({ error: 'request body must be a JSON envelope' });
}
const { url, method = 'GET', headers = {}, body = null } = env;
if (!url || typeof url !== 'string') {
return res.status(400).json({ error: 'envelope.url is required' });
}
let parsed;
try {
parsed = new URL(url);
} catch (_) {
return res.status(400).json({ error: 'envelope.url is not a valid URL' });
}
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
return res.status(400).json({ error: 'only http(s) targets are allowed' });
}
// ---- build axios request ----
const axiosReq = {
method: String(method).toUpperCase(),
url,
headers: { ...headers },
responseType: 'arraybuffer',
timeout: TIMEOUT_MS,
maxRedirects: 5,
validateStatus: () => true, // forward 4xx/5xx instead of throwing
decompress: true,
};
// Forward body only for methods that allow one.
if (!['GET', 'HEAD'].includes(axiosReq.method) && body != null) {
axiosReq.data = body;
}
// ---- forward ----
let upstream;
try {
upstream = await axios(axiosReq);
} catch (e) {
const code = e.code || '';
const status =
code === 'ECONNABORTED' ? 504 :
code === 'ENOTFOUND' || code === 'ECONNREFUSED' ? 502 :
502;
return res.status(status).json({
error: 'upstream request failed',
code,
detail: e.message,
target: url,
});
}
// ---- decode body as UTF-8 text ----
const raw = Buffer.from(upstream.data);
const text = raw.toString('utf8');
// ---- normalise response headers (drop hop-by-hop / encoding) ----
const outHeaders = {};
const SKIP = new Set([
'content-encoding',
'transfer-encoding',
'connection',
'content-length',
'keep-alive',
]);
for (const [k, v] of Object.entries(upstream.headers || {})) {
if (SKIP.has(k.toLowerCase())) continue;
outHeaders[k] = v;
}
// ---- reply ----
res.status(200).json({
status: upstream.status,
statusText: upstream.statusText || '',
headers: outHeaders,
body: text,
});
});
// ---------------------------------------------------------------------------
// Health check — quick way to confirm the server is alive from a browser.
// ---------------------------------------------------------------------------
app.get('/health', (req, res) => {
res.json({
ok: true,
service: 'yt-ffmpeg-proxy',
port: PORT,
host: HOST,
uptime: process.uptime(),
timestamp: new Date().toISOString(),
});
});
// ---------------------------------------------------------------------------
// 404 fallback for any other path.
// ---------------------------------------------------------------------------
app.use((req, res) => {
res.status(404).json({
error: 'not found',
hint: 'POST a JSON envelope to / — see /health',
method: req.method,
path: req.path,
});
});
// ---------------------------------------------------------------------------
// Start
// ---------------------------------------------------------------------------
const server = app.listen(PORT, HOST, () => {
const shownHost = HOST === '0.0.0.0' || HOST === '::' ? 'localhost' : HOST;
console.log('');
console.log(' ┌─────────────────────────────────────────────┐');
console.log(' │ YT-FFmpeg proxy server is running │');
console.log(' └─────────────────────────────────────────────┘');
console.log(` → Local: http://${shownHost}:${PORT}/`);
console.log(` → Health: http://${shownHost}:${PORT}/health`);
console.log(` → Endpoint: POST http://${shownHost}:${PORT}/`);
console.log(` → Timeout: ${TIMEOUT_MS} ms Max body: ${MAX_BODY}`);
console.log(' Press Ctrl+C to stop.');
console.log('');
});
server.on('error', (err) => {
console.error('server error:', err.message);
if (err.code === 'EADDRINUSE') {
console.error(`Port ${PORT} is already in use. Set PORT=... to change it.`);
}
process.exit(1);
});
Run with npm i express axios then node server.js. The startup banner
prints the port. Visit /health to confirm it is alive.
http://localhost:<port>/
CORS is already handled by each server. If your client needs to forward cookies, include them in
the envelope's headers object.