diff --git a/package-lock.json b/package-lock.json index 98f7c22..2e02001 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20231016.0.tgz", - "integrity": "sha512-rPAnF8Q25+eHEsAopihWeftPW/P0QapY9d7qaUmtOXztWdd6YPQ7JuiWVj4Nvjphge1BleehxAbo4I3Z4L2H1g==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20231025.0.tgz", + "integrity": "sha512-MYRYTbSl+tjGg6su7savlLIb8cOcKJfdGpA+WdtgqT2OF7O+89Lag0l1SA/iyVlUkT31Jc6OLHqvzsXgmg+niQ==", "cpu": [ "x64" ], @@ -37,9 +37,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20231016.0.tgz", - "integrity": "sha512-MvydDdiLXt+jy57vrVZ2lU6EQwCdpieyZoN8uBXSWzfG3zR/6dxU1+okvPQPlHN0jtlufqPeHrpJyAqqgLHUKA==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20231025.0.tgz", + "integrity": "sha512-BszjtBDR84TVa6oWe74dePJSAukWlTmLw9zR4KeWuwZLJGV7RMm6AmwGStetjnwZrecZaaOFELfBCAHtsebV0Q==", "cpu": [ "arm64" ], @@ -53,9 +53,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20231016.0.tgz", - "integrity": "sha512-y6Sj37yTzM8QbAghG9LRqoSBrsREnQz8NkcmpjSxeK6KMc2g0L5A/OemCdugNlIiv+zRv9BYX1aosaoxY5JbeQ==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20231025.0.tgz", + "integrity": "sha512-AT9dxgKXOa9xZxZ3k2a432axPJJ58KpoNWnPiPYGpuAuLoWnfcYwwh6mr9sZVcTdAdTAK9Xu9c81tp0YABanUw==", "cpu": [ "x64" ], @@ -69,9 +69,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20231016.0.tgz", - "integrity": "sha512-LqMIRUHD1YeRg2TPIfIQEhapSKMFSq561RypvJoXZvTwSbaROxGdW6Ku+PvButqTkEvuAtfzN/kGje7fvfQMHg==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20231025.0.tgz", + "integrity": "sha512-EIjex5o2k80YZWPix1btGybL/vNZ3o6vqKX9ptS0JcFkHV5aFX5/kcMwSBRjiIC+w04zVjmGQx3N1Vh3njuncg==", "cpu": [ "arm64" ], @@ -85,9 +85,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20231016.0.tgz", - "integrity": "sha512-96ojBwIHyiUAbsWlzBqo9P/cvH8xUh8SuBboFXtwAeXcJ6/urwKN2AqPa/QzOGUTCdsurWYiieARHT5WWWPhKw==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20231025.0.tgz", + "integrity": "sha512-7vtq0mO22A2v0OOsKXa760r9a84Gg8CK0gDu5uNWlj6hojmt011iz7jJt76I7oo/XrVwVlVfu69GnA3ljx6U8w==", "cpu": [ "x64" ], @@ -483,10 +483,28 @@ "node": ">=14" } }, + "node_modules/@types/node": { + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.9.tgz", + "integrity": "sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -496,9 +514,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -813,9 +831,9 @@ } }, "node_modules/miniflare": { - "version": "3.20231016.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20231016.0.tgz", - "integrity": "sha512-AmlqI89zsnBJfC+nKKZdCB/fuu0q/br24Kqt9NZwcT6yJEpO5NytNKfjl6nJROHROwuJSRQR1T3yopCtG1/0DA==", + "version": "3.20231025.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20231025.0.tgz", + "integrity": "sha512-pFcr2BRaGIQ26UfdDo8BMJ6kkd/Jo/FkQ/4K7UG/eORlDepsLrR/sTJddcSSIGl07MA+MGjhzopFTPpFskkS+g==", "dev": true, "dependencies": { "acorn": "^8.8.0", @@ -826,7 +844,7 @@ "source-map-support": "0.5.21", "stoppable": "^1.1.0", "undici": "^5.22.1", - "workerd": "1.20231016.0", + "workerd": "1.20231025.0", "ws": "^8.11.0", "youch": "^3.2.2", "zod": "^3.20.6" @@ -851,9 +869,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -922,6 +940,15 @@ "node": ">=8.10.0" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/rollup-plugin-inject": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", @@ -953,11 +980,12 @@ } }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -1029,9 +1057,9 @@ "dev": true }, "node_modules/undici": { - "version": "5.26.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.4.tgz", - "integrity": "sha512-OG+QOf0fTLtazL9P9X7yqWxQ+Z0395Wk6DSkyTxtaq3wQEjIroVe7Y4asCX/vcCxYpNGMnwz8F0qbRYUoaQVMw==", + "version": "5.27.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.27.2.tgz", + "integrity": "sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==", "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" @@ -1040,10 +1068,16 @@ "node": ">=14.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/workerd": { - "version": "1.20231016.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20231016.0.tgz", - "integrity": "sha512-v2GDb5XitSqgub/xm7EWHVAlAK4snxQu3itdMQxXstGtUG9hl79fQbXS/8fNFbmms2R2bAxUwSv47q8k5T5Erw==", + "version": "1.20231025.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20231025.0.tgz", + "integrity": "sha512-W1PFtpMFfvmm+ozBf+u70TE3Pviv7WA4qzDeejHDC4z+PFDq4+3KJCkgffaGBO86h+akWO0hSsc0uXL2zAqofQ==", "dev": true, "hasInstallScript": true, "bin": { @@ -1053,17 +1087,17 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20231016.0", - "@cloudflare/workerd-darwin-arm64": "1.20231016.0", - "@cloudflare/workerd-linux-64": "1.20231016.0", - "@cloudflare/workerd-linux-arm64": "1.20231016.0", - "@cloudflare/workerd-windows-64": "1.20231016.0" + "@cloudflare/workerd-darwin-64": "1.20231025.0", + "@cloudflare/workerd-darwin-arm64": "1.20231025.0", + "@cloudflare/workerd-linux-64": "1.20231025.0", + "@cloudflare/workerd-linux-arm64": "1.20231025.0", + "@cloudflare/workerd-windows-64": "1.20231025.0" } }, "node_modules/wrangler": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.14.0.tgz", - "integrity": "sha512-4vzw11yG1/KXpYKbumvRJ61Iyhm/yKXb/ayOw/2xiIRdKdpsfN9/796d2l525+CDaGwZWswpLENe6ZMS0p/Ghg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.15.0.tgz", + "integrity": "sha512-kxzK62rD+LRrDeZZzw8cP6FBub71vJCbfAAb594XobXajgXYh3pFjv18Vm8YLxHzoGMhmAOJPA5b4DHq4HEUCw==", "dev": true, "dependencies": { "@cloudflare/kv-asset-handler": "^0.2.0", @@ -1072,9 +1106,10 @@ "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", "esbuild": "0.17.19", - "miniflare": "3.20231016.0", + "miniflare": "3.20231025.0", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", + "resolve.exports": "^2.0.2", "selfsigned": "^2.0.1", "source-map": "0.6.1", "source-map-support": "0.5.21", @@ -1085,7 +1120,7 @@ "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=16.13.0" + "node": ">=16.17.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -1119,9 +1154,9 @@ "dev": true }, "node_modules/youch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.2.tgz", - "integrity": "sha512-9cwz/z7abtcHOIuH45nzmUFCZbyJA1nLqlirKvyNRx4wDMhqsBaifAJzBej7L4fsVPjFxYq3NK3GAcfvZsydFw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.3.tgz", + "integrity": "sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==", "dev": true, "dependencies": { "cookie": "^0.5.0", diff --git a/src/index.js b/src/index.js index de66b62..ae191d1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,15 +1,19 @@ -/** - * Welcome to Cloudflare Workers! This is your first worker. - * - * - Run `npm run dev` in your terminal to start a development server - * - Open a browser tab at http://localhost:8787/ to see your worker in action - * - Run `npm run deploy` to publish your worker - * - * Learn more at https://developers.cloudflare.com/workers/ - */ +import { handleV1Requests } from "./v1/v1RequestHandler.js"; +import { notFoundError } from "./stdErrorResponses.js"; -export default { - async fetch(request, env, ctx) { - return new Response('Hello World!'); - }, -}; +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +function stripUrl(url) { + const port = url.port; + const domain = url.hostname; + return url.toString().replace(domain, "").replace("https://", "").replace("http://", "").replace(":" + port, ""); +} +async function handleRequest(request) { + let pathname = stripUrl(new URL(request.url)); + if (pathname.startsWith("/v1/")) { + return handleV1Requests(pathname, request); + } else { + return notFoundError(); + } +} diff --git a/src/stdErrorResponses.js b/src/stdErrorResponses.js new file mode 100644 index 0000000..e94c3b1 --- /dev/null +++ b/src/stdErrorResponses.js @@ -0,0 +1,31 @@ +export function internalServerError() { + return new Response("Internal Server Error", { + status: 500, + statusText: "Internal Server Error", + message: "The server encountered an internal error and was unable to complete your request." + }); +} + +export function notFoundError() { + return new Response("Not Found", { + status: 404, + statusText: "Not Found", + message: "The requested resource was not found on this server." + }); +} + +export function methodNotAllowedError() { + return new Response("Method Not Allowed", { + status: 405, + statusText: "Method Not Allowed", + message: "The method specified in the request is not allowed for this resource." + }); +} + +export function badRequestError() { + return new Response("Bad Request", { + status: 400, + statusText: "Bad Request", + message: "The server could not understand the request due to invalid syntax." + }); +} \ No newline at end of file diff --git a/src/v1/builtInRequests.js b/src/v1/builtInRequests.js new file mode 100644 index 0000000..5e33868 --- /dev/null +++ b/src/v1/builtInRequests.js @@ -0,0 +1,29 @@ +import { internalServerError } from '../stdErrorResponses.js'; +import { version } from '../../package.json'; + +export const builtinRequests = ["ping", "version", "help"]; + +export function isBuiltinRequest(request) { + return builtinRequests.includes(request); +} + +export function returnVersion() { + return new Response(JSON.stringify([version]), { + headers: { + "Content-Type": "application/json" + } + }); +} + +export function handleBuiltinRequest(request) { + switch (request) { + case "ping": + return new Response("pong"); + case "version": + return returnVersion(); + case "help": + return new Response("Please refer to the wiki at https://wiki.jonasjones.dev/Api/"); + default: + return internalServerError(); + } +} \ No newline at end of file diff --git a/src/v1/lastfm/Requests.js b/src/v1/lastfm/Requests.js new file mode 100644 index 0000000..b78fa43 --- /dev/null +++ b/src/v1/lastfm/Requests.js @@ -0,0 +1,40 @@ +const lastfmRequests = ['gettrackinfo', 'getrecent'] + +export function isLastfmRequest(pathname) { + return pathname.startsWith("lastfm/") +} + +export function handleLastfmRequest(pathname) { + requestUrl = new URL(pathname, "https://api.jonasjones.dev/v1/" + pathname) + requestType = pathname.replace("lastfm/", "").split("?")[0]; + switch (requestType) { + case "gettrackinfo": + return getTrackInfoRequestHandler(requestUrl); + case "getrecent": + return getRecentRequestHandler(requestUrl); + default: + return notFoundError(); + } +} + +function getRecentRequestHandler(requestUrl) { + const urlParams = new URLSearchParams(requestUrl.search); + const offset = urlParams.get("offset"); + const limit = urlParams.get("limit"); + return new Response(JSON.stringify([offset, limit]), { + headers: { + "Content-Type": "application/json" + } + }); +} + +function getTrackInfoRequestHandler(requestUrl) { + const urlParams = new URLSearchParams(requestUrl.search); + const track = urlParams.get("track"); + const artist = urlParams.get("artist"); + return new Response(JSON.stringify([track, artist]), { + headers: { + "Content-Type": "application/json" + } + }); +} \ No newline at end of file diff --git a/src/v1/v1RequestHandler.js b/src/v1/v1RequestHandler.js new file mode 100644 index 0000000..f4b7ee0 --- /dev/null +++ b/src/v1/v1RequestHandler.js @@ -0,0 +1,18 @@ +import { isBuiltinRequest, handleBuiltinRequest } from './builtInRequests.js'; +import { methodNotAllowedError, notFoundError } from '../stdErrorResponses.js'; +import { handleLastfmRequest, isLastfmRequest } from './lastfm/Requests.js'; + +export async function handleV1Requests(pathname, request) { + if (request.method !== "GET") { + return methodNotAllowedError(); + } else { + const requestPath = pathname.replace("/v1/", ""); + if (isBuiltinRequest(requestPath)) { + return handleBuiltinRequest(requestPath); + } else if (isLastfmRequest(requestPath)) { + return handleLastfmRequest(requestPath); + } else { + return notFoundError(); + } + } +} \ No newline at end of file