diff --git a/http/file_server.ts b/http/file_server.ts
index 903d99c21d92..6fc2d15a7f58 100755
--- a/http/file_server.ts
+++ b/http/file_server.ts
@@ -13,7 +13,7 @@ import {
setContentLength,
Response
} from "./server.ts";
-import { extname } from "../fs/path.ts";
+import { extname, posix } from "../fs/path.ts";
import { contentType } from "../media_types/mod.ts";
const dirViewerTemplate = `
@@ -53,11 +53,10 @@ for (let i = 0; i < serverArgs.length; i++) {
break;
}
}
-let currentDir = cwd();
-const target = serverArgs[1];
-if (target) {
- currentDir = `${currentDir}/${target}`;
-}
+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();
@@ -104,7 +103,7 @@ function fileLenToString(len: number): string {
function createDirEntryDisplay(
name: string,
- path: string,
+ url: string,
size: number | null,
mode: number | null,
isDir: boolean
@@ -114,7 +113,7 @@ function createDirEntryDisplay(
${modeToString(
isDir,
mode
- )} | ${sizeStr} | ${name}${
+ )} | ${sizeStr} | ${name}${
isDir ? "/" : ""
} |
@@ -123,13 +122,13 @@ function createDirEntryDisplay(
async function serveFile(
req: ServerRequest,
- filename: string
+ filePath: string
): Promise {
- const file = await open(filename);
- const fileInfo = await stat(filename);
+ 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(filename)) || "text/plain");
+ headers.set("content-type", contentType(extname(filePath)) || "text/plain");
const res = {
status: 200,
@@ -142,41 +141,42 @@ async function serveFile(
// TODO: simplify this after deno.stat and deno.readDir are fixed
async function serveDir(
req: ServerRequest,
- dirPath: string,
- dirName: string
+ dirPath: string
): Promise {
interface ListItem {
name: string;
template: string;
}
- // dirname has no prefix
+ const dirUrl = `/${posix.relative(target, dirPath)}`;
const listEntry: ListItem[] = [];
const fileInfos = await readDir(dirPath);
- for (const info of fileInfos) {
- let fn = dirPath + "/" + info.name;
- if (info.name === "index.html" && info.isFile()) {
+ 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, fn);
+ return await serveFile(req, filePath);
}
// Yuck!
let mode = null;
try {
- mode = (await stat(fn)).mode;
+ mode = (await stat(filePath)).mode;
} catch (e) {}
listEntry.push({
- name: info.name,
+ name: fileInfo.name,
template: createDirEntryDisplay(
- info.name,
- fn.replace(currentDir, ""),
- info.isFile() ? info.len : null,
+ fileInfo.name,
+ fileUrl,
+ fileInfo.isFile() ? fileInfo.len : null,
mode,
- info.isDirectory()
+ fileInfo.isDirectory()
)
});
}
+ const formattedDirUrl = `${dirUrl.replace(/\/$/, "")}/`;
const page = new TextEncoder().encode(
- dirViewerTemplate.replace("<%DIRNAME%>", dirName + "/").replace(
+ dirViewerTemplate.replace("<%DIRNAME%>", formattedDirUrl).replace(
"<%CONTENTS%>",
listEntry
.sort(
@@ -238,19 +238,17 @@ function setCORS(res: Response): void {
listenAndServe(
addr,
async (req): Promise => {
- const fileName = req.url.replace(/\/$/, "");
- const filePath = currentDir + fileName;
+ const normalizedUrl = posix.normalize(req.url);
+ const fsPath = posix.join(target, normalizedUrl);
let response: Response;
try {
- const fileInfo = await stat(filePath);
- if (fileInfo.isDirectory()) {
- // Bug with deno.stat: name and path not populated
- // Yuck!
- response = await serveDir(req, filePath, fileName);
+ const info = await stat(fsPath);
+ if (info.isDirectory()) {
+ response = await serveDir(req, fsPath);
} else {
- response = await serveFile(req, filePath);
+ response = await serveFile(req, fsPath);
}
} catch (e) {
response = await serveFallback(req, e);