https://deno.land/std /http/file_server.ts

This file has been compiled to JS. View the original version here.

This file couldn’t be annotated due to an error.
TypeError: Cannot read property 'kind' of undefined
    at Object.isSourceFile (.../node_modules/typescript/lib/typescript.js:14132:21)
    at getStatement (.../analyze_code.js:277:10)
    at id (.../analyze_code.js:247:26)
    at idFor (.../analyze_code.js:263:5)
    at id (.../analyze_code.js:262:12)
    at idFor (.../analyze_code.js:263:5)
    at node (.../analyze_code.js:142:39)
    at walkAST (.../utils.js:19:3)
    at require.forEachChild.n (.../utils.js:20:49)
    at visitNode (.../node_modules/typescript/lib/typescript.js:16622:24)
#!/usr/bin/env -S deno --allow-net
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// This program serves files in the current directory over HTTP.
// TODO Stream responses instead of reading them into memory.
// TODO Add tests like these:
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
const { ErrorKind, cwd, args, stat, readDir, open } = Deno;
import { listenAndServe, setContentLength } from "./server.ts?js";
import { extname, posix } from "../fs/path.ts?js";
import { contentType } from "../media_types/mod.ts?js";
const dirViewerTemplate = `
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Deno File Server</title>
  <style>
    td {
      padding: 0 1rem;
    }
    td.mode {
      font-family: Courier;
    }
  </style>
</head>
<body>
  <h1>Index of <%DIRNAME%></h1>
  <table>
    <tr><th>Mode</th><th>Size</th><th>Name</th></tr>
    <%CONTENTS%>
  </table>
</body>
</html>
`;
const serverArgs = args.slice();
let CORSEnabled = false;
// TODO: switch to flags if we later want to add more options
for (let i = 0; i < serverArgs.length; i++) {
    if (serverArgs[i] === "--cors") {
        CORSEnabled = true;
        serverArgs.splice(i, 1);
        break;
    }
}
const targetArg = serverArgs[1] || "";
const target = posix.isAbsolute(targetArg)
    ? posix.normalize(targetArg)
    : posix.join(cwd(), targetArg);
const addr = `0.0.0.0:${serverArgs[2] || 4500}`;
const encoder = new TextEncoder();
function modeToString(isDir, maybeMode) {
    const modeMap = ["---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"];
    if (maybeMode === null) {
        return "(unknown mode)";
    }
    const mode = maybeMode.toString(8);
    if (mode.length < 3) {
        return "(unknown mode)";
    }
    let output = "";
    mode
        .split("")
        .reverse()
        .slice(0, 3)
        .forEach((v) => {
        output = modeMap[+v] + output;
    });
    output = `(${isDir ? "d" : "-"}${output})`;
    return output;
}
function fileLenToString(len) {
    const multiplier = 1024;
    let base = 1;
    const suffix = ["B", "K", "M", "G", "T"];
    let suffixIndex = 0;
    while (base * multiplier < len) {
        if (suffixIndex >= suffix.length - 1) {
            break;
        }
        base *= multiplier;
        suffixIndex++;
    }
    return `${(len / base).toFixed(2)}${suffix[suffixIndex]}`;
}
function createDirEntryDisplay(name, url, size, mode, isDir) {
    const sizeStr = size === null ? "" : "" + fileLenToString(size);
    return `
  <tr><td class="mode">${modeToString(isDir, mode)}</td><td>${sizeStr}</td><td><a href="${url}">${name}${isDir ? "/" : ""}</a></td>
  </tr>
  `;
}
async function serveFile(req, filePath) {
    const file = await open(filePath);
    const fileInfo = await stat(filePath);
    const headers = new Headers();
    headers.set("content-length", fileInfo.len.toString());
    headers.set("content-type", contentType(extname(filePath)) || "text/plain");
    const res = {
        status: 200,
        body: file,
        headers
    };
    return res;
}
// TODO: simplify this after deno.stat and deno.readDir are fixed
async function serveDir(req, dirPath) {
    const dirUrl = `/${posix.relative(target, dirPath)}`;
    const listEntry = [];
    const fileInfos = await readDir(dirPath);
    for (const fileInfo of fileInfos) {
        const filePath = posix.join(dirPath, fileInfo.name);
        let fileUrl = posix.join(dirUrl, fileInfo.name);
        if (fileInfo.name === "index.html" && fileInfo.isFile()) {
            // in case index.html as dir...
            return await serveFile(req, filePath);
        }
        // Yuck!
        let mode = null;
        try {
            mode = (await stat(filePath)).mode;
        }
        catch (e) { }
        listEntry.push({
            name: fileInfo.name,
            template: createDirEntryDisplay(fileInfo.name, fileUrl, fileInfo.isFile() ? fileInfo.len : null, mode, fileInfo.isDirectory())
        });
    }
    const formattedDirUrl = `${dirUrl.replace(/\/$/, "")}/`;
    const page = new TextEncoder().encode(dirViewerTemplate.replace("<%DIRNAME%>", formattedDirUrl).replace("<%CONTENTS%>", listEntry
        .sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1)
        .map((v) => v.template)
        .join("")));
    const headers = new Headers();
    headers.set("content-type", "text/html");
    const res = {
        status: 200,
        body: page,
        headers
    };
    setContentLength(res);
    return res;
}
async function serveFallback(req, e) {
    if (e instanceof Deno.DenoError &&
        e.kind === ErrorKind.NotFound) {
        return {
            status: 404,
            body: encoder.encode("Not found")
        };
    }
    else {
        return {
            status: 500,
            body: encoder.encode("Internal server error")
        };
    }
}
function serverLog(req, res) {
    const d = new Date().toISOString();
    const dateFmt = `[${d.slice(0, 10)} ${d.slice(11, 19)}]`;
    const s = `${dateFmt} "${req.method} ${req.url} ${req.proto}" ${res.status}`;
    console.log(s);
}
function setCORS(res) {
    if (!res.headers) {
        res.headers = new Headers();
    }
    res.headers.append("access-control-allow-origin", "*");
    res.headers.append("access-control-allow-headers", "Origin, X-Requested-With, Content-Type, Accept, Range");
}
listenAndServe(addr, async (req) => {
    const normalizedUrl = posix.normalize(req.url);
    const fsPath = posix.join(target, normalizedUrl);
    let response;
    try {
        const info = await stat(fsPath);
        if (info.isDirectory()) {
            response = await serveDir(req, fsPath);
        }
        else {
            response = await serveFile(req, fsPath);
        }
    }
    catch (e) {
        response = await serveFallback(req, e);
    }
    finally {
        if (CORSEnabled) {
            setCORS(response);
        }
        serverLog(req, response);
        req.respond(response);
    }
});
console.log(`HTTP server listening on http://${addr}/`);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSwwRUFBMEU7QUFFMUUsZ0VBQWdFO0FBQ2hFLDZEQUE2RDtBQUM3RCw2QkFBNkI7QUFDN0IsZ0ZBQWdGO0FBRWhGLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQztBQUMzRCxPQUFPLEVBQ0wsY0FBYyxFQUVkLGdCQUFnQixFQUVqQix1QkFBb0I7QUFDckIsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUseUJBQXNCO0FBQy9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsaUNBQThCO0FBRXBELE1BQU0saUJBQWlCLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0F5QnpCLENBQUM7QUFFRixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDaEMsSUFBSSxXQUFXLEdBQUcsS0FBSyxDQUFDO0FBQ3hCLDZEQUE2RDtBQUM3RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUMxQyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDOUIsV0FBVyxHQUFHLElBQUksQ0FBQztRQUNuQixVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4QixNQUFNO0tBQ1A7Q0FDRjtBQUNELE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDdEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7SUFDeEMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDO0lB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