From b9971282a474ff13c35c9959ddb6ac5e59c3050b Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Wed, 5 May 2021 23:22:00 -0500 Subject: [PATCH] Finish rewrite of torrent REST API service --- services/torrent-rest/package.json | 1 + .../services/WebServer/middleware/torrent.ts | 29 +++++++ .../src/services/WebServer/routes/api.ts | 77 +++++++++---------- 3 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 services/torrent-rest/src/services/WebServer/middleware/torrent.ts diff --git a/services/torrent-rest/package.json b/services/torrent-rest/package.json index fb16655..4112273 100644 --- a/services/torrent-rest/package.json +++ b/services/torrent-rest/package.json @@ -12,6 +12,7 @@ "dependencies": { "@autoplex-api/torrent": "^0.0.0", "@autoplex/database": "^0.0.0", + "@autoplex/ipc": "^0.0.0", "@autoplex/microservice": "^0.0.0", "@autoplex/utils": "^0.0.0", "@autoplex/webserver": "^0.0.0" diff --git a/services/torrent-rest/src/services/WebServer/middleware/torrent.ts b/services/torrent-rest/src/services/WebServer/middleware/torrent.ts new file mode 100644 index 0000000..0d38f41 --- /dev/null +++ b/services/torrent-rest/src/services/WebServer/middleware/torrent.ts @@ -0,0 +1,29 @@ +import { IteratorNext, MiddlewareRequest, FastifyReply, Status, respond } from "@autoplex/webserver"; +import { ISerializedTorrent } from "@autoplex-api/torrent"; +import Application from "../../../Application"; +import TorrentIpc from "../../TorrentIpc"; + +/** + * The parameter types for the auth middleware + */ +export interface ITorrentMiddleware { + torrent: ISerializedTorrent +} + +/** + * Ensure that a valid authentication token is provided + */ +export async function torrent(request: MiddlewareRequest, reply: FastifyReply, next: IteratorNext) { + let ipc = Application.instance().service("Torrent Client"); + let torrentId: string|undefined = (request.params)["torrentId"]; + if (torrentId === undefined) { + return respond(reply, Status.BadRequest); + } + if (!(await ipc.has(torrentId))) { + return respond(reply, Status.NotFound); + } + request.middlewareParams = Object.assign(request.middlewareParams ?? {}, { + torrent: (await ipc.details([torrentId]))[0] + }); + next(); +} diff --git a/services/torrent-rest/src/services/WebServer/routes/api.ts b/services/torrent-rest/src/services/WebServer/routes/api.ts index e7d50fb..c32521c 100644 --- a/services/torrent-rest/src/services/WebServer/routes/api.ts +++ b/services/torrent-rest/src/services/WebServer/routes/api.ts @@ -1,6 +1,8 @@ -import { MiddlewareMethod, RouteRegisterFactory } from "@autoplex/webserver"; +import { IpcConnectionError } from "@autoplex/ipc"; +import { MiddlewareMethod, RouteRegisterFactory, Status, respond, } from "@autoplex/webserver"; import Application from "../../../Application"; import TorrentIpc from "../../TorrentIpc"; +import { torrent } from "../middleware/torrent"; export default function register(factory: RouteRegisterFactory, Application>, app: Application) @@ -18,74 +20,67 @@ export default function register(factory: RouteRegisterFactory { + factory.get("/list", async (_, reply) => { let torrentList = await ipc.list(); - reply.send({ result: torrentList, status: "Success" }); + respond(reply, Status.Ok, torrentList); + }); + + /** + * Fetch the details of all torrents + */ + factory.get("/details", async (_, reply) => { + let details = await ipc.details(); + respond(reply, Status.Ok, details); }); /** * Fetch the details of a torrent */ - factory.get("/details/:infoHash", async (request, reply) => { - let infoHash: string = (request.params)["infoHash"]; - if (infoHash === undefined) { - reply.status(400); - reply.send({ status: "Bad request" }); - return; - } - try { - let details = await ipc.details(infoHash); - reply.send({ result: details, status: "Success" }); - } catch(e) { - reply.status(404); - reply.send({ status: "Not found" }); - } + factory.get("/details/:torrentId", [torrent], async (request, reply) => { + let details = request.middlewareParams.torrent; + respond(reply, Status.Ok, details); }); /** * Add a torrent to the client */ factory.post("/add", async (request, reply) => { + let downloadPath = (request.query)["downloadPath"] ?? undefined; let result: string[] = []; if (request.isMultipart()) { let files = request.files(); for await (let file of files) { let torrentFile = await file.toBuffer(); - let infoHash = await ipc.add(torrentFile); + let infoHash = await ipc.add(torrentFile, downloadPath); result.push(infoHash); } } else { let links = (request.body)?.link ?? null; if (links === null) { - reply.status(400); - reply.send({ status: "Bad request" }); - return; + return respond(reply, Status.BadRequest); } for (let link of (Array.isArray(links) ? links : [links])) { - let infoHash = await ipc.add(link); + let infoHash = await ipc.add(link, downloadPath); result.push(infoHash); } } - reply.send({ result: result, status: "Success" }); + respond(reply, Status.Ok, result); }); - }); - /** - * Remove a torrent from the client - */ - factory.delete("/remove/:infoHash", async (request, reply) => { - let infoHash: string = (request.params)["infoHash"]; - if (infoHash === undefined) { - reply.status(400); - reply.send({ status: "Bad request" }); - return; - } - try { - await ipc.remove(infoHash); - reply.send({ status: "Success" }); - } catch(e) { - reply.status(404); - reply.send({ status: "Not found" }); - } + /** + * Remove a torrent from the client + */ + factory.delete("/remove/:torrentId", [torrent], async (request, reply) => { + let torrent = request.middlewareParams.torrent; + try { + ipc.remove(torrent.infoHash); + } catch(e) { + if (e instanceof IpcConnectionError) { + return respond(reply, Status.InternalServerError); + } + return respond(reply, Status.Gone); + } + respond(reply, Status.Ok); + }); }); }