JM Tech Power

jm-tech-power-official/Flash Download

A desktop download manager that opens up to 32 connections against one file and can send each of them out a different proxy route.

Public Uncategorized
Clone jm-tech-power-official/flash-download.jmproj
test/fixture-server.js
// Local origin + two proxies, so the running app exercises real range requests
// and real proxy routing. Bytes are generated, never stored.
const http = require('http');
const { URL } = require('url');

// Real servers do not hand every connection the same throughput. Every third
// connection here gets a quarter of the rate, so lanes finish unevenly and the
// tail behaviour is actually exercised.
let conns = 0;
const rateFor = (kbps) => { conns += 1; return conns % 3 === 0 ? Math.round(kbps / 4) : kbps; };

const FILES = {
  '/ubuntu-24.04.3-live-server-amd64.iso': { size: 320 * 1024 * 1024, kbps: 900 },
  '/imagenet-val-2012.tar':                { size: 180 * 1024 * 1024, kbps: 420 },
  '/blender-4.2.1-linux-x64.tar.xz':       { size:  26 * 1024 * 1024, kbps: 2400 },
  '/tiny':                                 { size: 1024,              kbps: 0 },
};
const chunkOf = (() => { const b = Buffer.alloc(64 * 1024); for (let i = 0; i < b.length; i++) b[i] = (i * 2654435761) & 0xff; return b; })();

const origin = http.createServer((req, res) => {
  const path = new URL(req.url, 'http://x').pathname;
  const file = FILES[path];
  if (!file) { res.writeHead(404); return res.end(); }

  let start = 0, end = file.size - 1, status = 200;
  const m = /bytes=(\d+)-(\d*)/.exec(req.headers.range || '');
  if (m) { start = +m[1]; end = m[2] ? +m[2] : file.size - 1; status = 206; }
  end = Math.min(end, file.size - 1);
  const len = end - start + 1;

  const headers = { 'content-length': String(len), 'accept-ranges': 'bytes', etag: '"fixture-v1"', 'content-type': 'application/octet-stream' };
  if (status === 206) headers['content-range'] = `bytes ${start}-${end}/${file.size}`;
  res.writeHead(status, headers);
  if (!len) return res.end();
  if (!file.kbps) return res.end(chunkOf.subarray(0, len));

  let sent = 0;
  const per = Math.max(4096, Math.round((rateFor(file.kbps) * 1024) / 10));
  const tick = () => {
    if (res.writableEnded || !res.socket || res.socket.destroyed) return;
    const n = Math.min(per, len - sent);
    res.write(chunkOf.subarray(0, Math.min(n, chunkOf.length)));
    sent += Math.min(n, chunkOf.length);
    if (sent >= len) return res.end();
    setTimeout(tick, 100);
  };
  tick();
});

function proxy(name) {
  return http.createServer((req, res) => {
    let target;
    try { target = new URL(req.url); } catch { res.writeHead(400); return res.end(); }
    const up = http.request({ host: target.hostname, port: target.port || 80, path: target.pathname + target.search, method: req.method, headers: req.headers },
      (pr) => { res.writeHead(pr.statusCode, pr.headers); pr.pipe(res); });
    up.on('error', () => { try { res.writeHead(502); res.end(); } catch {} });
    req.pipe(up);
  });
}

const a = proxy('a'), b = proxy('b');
origin.listen(18080, '127.0.0.1');
a.listen(18081, '127.0.0.1');
b.listen(18082, '127.0.0.1');
console.log('fixture up: origin 18080, proxies 18081/18082');