Last active
January 3, 2022 07:23
-
-
Save mayankchoubey/b87e5180e85116660a2084c16d2e4fad to your computer and use it in GitHub Desktop.
Deno content server - Medium course - section 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { API_KEYS_PATH } from "./consts.ts"; | |
| let apiKeys: Array<string> = []; | |
| try { | |
| apiKeys = JSON.parse(Deno.readTextFileSync(API_KEYS_PATH)); | |
| } catch (_e) { | |
| console.info("No API keys found, authentication is disabled"); | |
| } | |
| export function authorize(headers: Headers) { | |
| const authorized = true, notAuthorized = false; | |
| if (!apiKeys.length) { | |
| return authorized; | |
| } | |
| const authHeader = headers.get("Authorization"); | |
| if (!authHeader) { | |
| return notAuthorized; | |
| } | |
| const apiKey = authHeader.split(" ")[1]; | |
| if (!apiKey) { | |
| return notAuthorized; | |
| } | |
| return apiKeys.includes(apiKey); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "apiKeysPath": "./test/unit/data/apiKeys.json", | |
| "servePath": "./test/unit/" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const cfg = JSON.parse(Deno.readTextFileSync("./cfg.json")); | |
| export const API_KEYS_PATH = cfg.apiKeysPath; | |
| export const SERVE_PATH = cfg.servePath; | |
| export const CONTENT_TYPE_RAW = "application/octet-stream"; | |
| export const EXTENSION_TO_CONTENT_TYPE: Record<string, string> = { | |
| ".bin": "application/octet-stream", | |
| ".csv": "text/csv", | |
| ".doc": "application/msword", | |
| ".docx": | |
| "application/vnd.openxmlformats-officedocument.wordprocessingml.document", | |
| ".gz": "application/gzip", | |
| ".gif": "image/gif", | |
| ".htm": "text/html", | |
| ".html": "text/html", | |
| ".jpeg": "image/jpeg", | |
| ".jpg": "image/jpeg", | |
| ".js": "text/javascript", | |
| ".json": "application/json", | |
| ".mp3": "audio/mpeg", | |
| ".mp4": "video/mp4", | |
| ".mpeg": "video/mpeg", | |
| ".png": "image/png", | |
| ".pdf": "application/pdf", | |
| ".ppt": "application/vnd.ms-powerpoint", | |
| ".pptx": | |
| "application/vnd.openxmlformats-officedocument.presentationml.presentation", | |
| ".rar": "application/vnd.rar", | |
| ".svg": "image/svg+xml", | |
| ".tar": "application/x-tar", | |
| ".txt": "text/plain", | |
| ".wav": "audio/wav", | |
| ".xls": "application/vnd.ms-excel", | |
| ".xlsx": | |
| "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", | |
| ".xml": "application/xml", | |
| ".zip": "application/zip", | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { authorize } from "./authService.ts"; | |
| import { getContent } from "./fileService.ts"; | |
| import { Status } from "https://deno.land/std/http/http_status.ts"; | |
| import { | |
| CONTENT_TYPE_RAW as rawCT, | |
| EXTENSION_TO_CONTENT_TYPE as getCT, | |
| } from "./consts.ts"; | |
| import { extname as ext } from "https://deno.land/std/path/mod.ts"; | |
| export async function handleRequest(req: Request): Promise<Response> { | |
| const relativePath = (new URL(req.url)).pathname; | |
| if (!authorize(req.headers)) { | |
| return new Response(null, { status: Status.Unauthorized }); | |
| } | |
| try { | |
| const { len, content } = await getContent(relativePath); | |
| return new Response(content, { | |
| status: 200, | |
| headers: { | |
| "content-length": len.toString(), | |
| "content-type": getCT[ext(relativePath)] || rawCT, | |
| }, | |
| }); | |
| } catch (err) { | |
| if (err instanceof Deno.errors.NotFound) { | |
| return new Response(null, { status: Status.NotFound }); | |
| } | |
| if (err instanceof Deno.errors.BadResource) { | |
| return new Response(null, { status: Status.UnprocessableEntity }); | |
| } | |
| } | |
| return new Response(null, { status: Status.InternalServerError }); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { readableStreamFromReader as makeStream } from "https://deno.land/std/streams/mod.ts"; | |
| import { SERVE_PATH } from "./consts.ts"; | |
| export async function getContent(relativePath: string) { | |
| const filePath = SERVE_PATH + relativePath; | |
| const fileData = await Deno.stat(filePath); | |
| if (!fileData.isFile) { | |
| throw new Deno.errors.BadResource("Directories cannot be served"); | |
| } | |
| const r = await Deno.open(filePath); | |
| return { | |
| len: fileData.size, | |
| content: makeStream(r), | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { API_KEYS_PATH, SERVE_PATH } from "./consts.ts"; | |
| import { route } from "./router.ts"; | |
| import { serve } from "https://deno.land/std/http/mod.ts"; | |
| async function checkAccess() { | |
| const servePath = Deno.args[0] || SERVE_PATH || ""; | |
| if (!servePath) { | |
| console.error( | |
| "Error: Serve path not specified in command line or config file", | |
| ); | |
| Deno.exit(1); | |
| } | |
| if ( | |
| (await Deno.permissions.query({ name: "read", path: servePath })) | |
| .state !== "granted" | |
| ) { | |
| console.error("Error: Missing read permission to", servePath); | |
| Deno.exit(1); | |
| } | |
| if ( | |
| (await Deno.permissions.query({ name: "read", path: API_KEYS_PATH })) | |
| .state !== "granted" | |
| ) { | |
| console.error("Error: Missing read permission to", API_KEYS_PATH); | |
| Deno.exit(1); | |
| } | |
| } | |
| await checkAccess(); | |
| console.log("Content server started..."); | |
| serve(route, { port: 8080 }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Status } from "https://deno.land/std/http/http_status.ts"; | |
| import { handleRequest } from "./controller.ts"; | |
| export async function route(req: Request): Promise<Response> { | |
| if (req.method !== "GET") { | |
| return new Response(null, { status: Status.MethodNotAllowed }); | |
| } | |
| return await handleRequest(req); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment