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
Raw Permalink Normal View History

2022-02-23 19:50:47 +01:00
import express from "express";
2022-03-14 20:18:08 +01:00
import { UrlPoolStorage } from "./urlpool";
2022-02-23 23:26:12 +01:00
import { Readable } from 'stream';
2022-03-14 20:18:08 +01:00
let storage = new UrlPoolStorage;
2022-02-23 19:50:47 +01:00
export class Webserver {
constructor() {
const app = express();
2022-11-13 11:37:30 +01:00
app.use(express.static('public'));
2022-03-14 20:18:08 +01:00
app.get("/status/:id", async (req, res) => {
2022-04-23 01:37:41 +02:00
let p = await storage.get(req.params.id);
if(!p) {
res.status(404);
res.end();
return;
}
2022-03-14 20:18:08 +01:00
2022-04-23 14:49:12 +02:00
res.writeHead(200, {
"Content-Type": "application/json"
});
2022-03-14 20:18:08 +01:00
res.write(JSON.stringify({
2023-02-06 22:18:56 +01:00
file: {
name: p.file_name,
size: p.total_size
},
stream: {
2022-03-14 20:18:08 +01:00
total: p.urls.length,
available: p.available().length,
2022-04-23 14:49:12 +02:00
generating: p.generating,
2023-02-06 21:43:07 +01:00
downloaders: p.downloaders.length,
urls: p.urls
2022-03-14 20:18:08 +01:00
}
}));
res.end();
});
2022-11-13 11:37:30 +01:00
app.get("/u/:id", async (req, res) => {
2022-03-14 20:18:08 +01:00
2022-04-23 01:37:41 +02:00
let p = await storage.get(req.params.id);
if(!p) {
res.status(404);
res.end();
return;
}
2022-02-23 19:50:47 +01:00
let range: Range = {from: 0, to: null};
if(req.headers.range) range = this.parse_range(req.headers.range);
if(!range.from) range.from = 0;
2022-04-23 14:49:12 +02:00
let d = p.get_downloader(range.from);
2022-02-23 19:50:47 +01:00
let contentLength = p.total_size-range.from;
2022-02-23 23:26:12 +01:00
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}`,
2022-02-23 19:50:47 +01:00
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
2022-02-23 20:50:10 +01:00
"Content-Type": "application/octet-stream",
2022-02-23 19:50:47 +01:00
};
res.writeHead(206, headers);
2022-04-23 14:49:12 +02:00
res.on("close", () => {
d.destroy();
});
2022-02-23 19:50:47 +01:00
2022-04-23 14:49:12 +02:00
const readable = new Readable();
2022-02-23 23:26:12 +01:00
readable._read = async () => {
2022-04-23 14:49:12 +02:00
let stream = await d.more();
readable.push(stream);
2022-02-23 23:26:12 +01:00
}
2022-04-23 14:49:12 +02:00
let stream = await d.more();
2022-02-23 23:26:12 +01:00
readable.push(stream);
readable.pipe(res);
2022-02-23 19:50:47 +01:00
});
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};
}
2022-02-23 23:26:12 +01:00
from_to(range: [number, number], max: number) {
if(range[0] > max) range[0] = max;
if(range[1] > max) range[1] = max;
return range;
}
2022-02-23 19:50:47 +01:00
}
interface Range {
from: number | null;
to: number | null;
}