This repository has been archived on 2023-11-29. You can view files and clone it, but cannot push or open issues or pull requests.
Uloz.to-rychle/webserver.ts

111 lines
2.3 KiB
TypeScript

import express from "express";
import { UrlPoolStorage } from "./urlpool";
import { Readable } from 'stream';
let storage = new UrlPoolStorage;
export class Webserver {
constructor() {
const app = express();
app.use(express.static('public'));
app.get("/status/:id", async (req, res) => {
let p = await storage.get(req.params.id);
if(!p) {
res.status(404);
res.end();
return;
}
res.writeHead(200, {
"Content-Type": "application/json"
});
res.write(JSON.stringify({
file: {
name: p.file_name,
size: p.total_size
},
stream: {
total: p.urls.length,
available: p.available().length,
generating: p.generating,
downloaders: p.downloaders.length,
urls: p.urls
}
}));
res.end();
});
app.get("/u/:id", async (req, res) => {
let p = await storage.get(req.params.id);
if(!p) {
res.status(404);
res.end();
return;
}
let range: Range = {from: 0, to: null};
if(req.headers.range) range = this.parse_range(req.headers.range);
if(!range.from) range.from = 0;
let d = p.get_downloader(range.from);
let contentLength = p.total_size-range.from;
let headers = {
"Content-Range": `bytes ${range.from}-${p.total_size-1}/${p.total_size}`,
"Range": `bytes=${range.from}-${p.total_size-1}/${p.total_size}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "application/octet-stream",
};
res.writeHead(206, headers);
res.on("close", () => {
d.destroy();
});
const readable = new Readable();
readable._read = async () => {
let stream = await d.more();
readable.push(stream);
}
let stream = await d.more();
readable.push(stream);
readable.pipe(res);
});
app.listen(8000, function () {
console.log("Listening on port 8000!");
});
}
parse_range(input: string): Range {
let [from, to]: (number|null)[] = [null, null];
let parts = input.split("=");
if(parts[1]) [from, to] = parts[1].split("-").map(i => i ? parseInt(i) : null);
return {from, to};
}
from_to(range: [number, number], max: number) {
if(range[0] > max) range[0] = max;
if(range[1] > max) range[1] = max;
return range;
}
}
interface Range {
from: number | null;
to: number | null;
}