Skip to content

Commit

Permalink
fix(http/file_server): resolve empty subdir correctly on Windows (#3439)
Browse files Browse the repository at this point in the history
  • Loading branch information
Chocobo1 authored Jun 14, 2023
1 parent aea8515 commit 8bd34c3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 7 deletions.
24 changes: 18 additions & 6 deletions http/file_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@
* @module
*/

import { extname, posix, resolve } from "../path/mod.ts";
import {
extname,
join,
posix,
relative,
resolve,
SEP_PATTERN,
} from "../path/mod.ts";
import { contentType } from "../media_types/content_type.ts";
import { serve, serveTls } from "./server.ts";
import { calculate, ifNoneMatch } from "./etag.ts";
Expand Down Expand Up @@ -272,12 +279,17 @@ async function serveDirIndex(
},
): Promise<Response> {
const { showDotfiles } = options;
const dirUrl = `/${posix.relative(options.target, dirPath)}`;
const dirUrl = `/${
relative(options.target, dirPath).replaceAll(
new RegExp(SEP_PATTERN, "g"),
"/",
)
}`;
const listEntryPromise: Promise<EntryInfo>[] = [];

// if ".." makes sense
if (dirUrl !== "/") {
const prevPath = posix.join(dirPath, "..");
const prevPath = join(dirPath, "..");
const entryInfo = Deno.stat(prevPath).then((fileInfo): EntryInfo => ({
mode: modeToString(true, fileInfo.mode),
size: "",
Expand All @@ -292,7 +304,7 @@ async function serveDirIndex(
if (!showDotfiles && entry.name[0] === ".") {
continue;
}
const filePath = posix.join(dirPath, entry.name);
const filePath = join(dirPath, entry.name);
const fileUrl = encodeURIComponent(posix.join(dirUrl, entry.name))
.replaceAll("%2F", "/");

Expand Down Expand Up @@ -632,7 +644,7 @@ async function createServeDirResponse(
normalizedPath = normalizedPath.slice(0, -1);
}

const fsPath = posix.join(target, normalizedPath);
const fsPath = join(target, normalizedPath);
const fileInfo = await Deno.stat(fsPath);

// For files, remove the trailing slash from the path.
Expand Down Expand Up @@ -661,7 +673,7 @@ async function createServeDirResponse(

// if target is directory, serve index or dir listing.
if (showIndex) { // serve index.html
const indexPath = posix.join(fsPath, "index.html");
const indexPath = join(fsPath, "index.html");

let indexFileInfo: Deno.FileInfo | undefined;
try {
Expand Down
51 changes: 50 additions & 1 deletion http/file_server_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import { writeAll } from "../streams/write_all.ts";
import { TextLineStream } from "../streams/text_line_stream.ts";
import { serveDir, serveFile } from "./file_server.ts";
import { calculate } from "./etag.ts";
import { dirname, fromFileUrl, join, resolve, toFileUrl } from "../path/mod.ts";
import {
basename,
dirname,
fromFileUrl,
join,
resolve,
toFileUrl,
} from "../path/mod.ts";
import { isWindows } from "../_util/os.ts";
import { VERSION } from "../version.ts";
import { retry } from "../async/retry.ts";
Expand Down Expand Up @@ -1564,3 +1571,45 @@ Deno.test("file_server should resolve `path` correctly on Windows", {
await killFileServer();
}
});

Deno.test(
"file_server should resolve empty subdir correctly without asking for current directory read permission on Windows",
{
ignore: Deno.build.os !== "windows",
},
async () => {
const tempDir = Deno.makeTempDirSync({ dir: `${moduleDir}/testdata` });
const fileServer = new Deno.Command(Deno.execPath(), {
// specifying a path for `--allow-read` this is essential for this test
// otherwise it won't trigger the edge case
args: [
"run",
"--no-check",
"--no-prompt",
"--quiet",
`--allow-read=${moduleDir}/testdata`,
"--allow-net",
"file_server.ts",
moduleDir,
"--host",
"localhost",
"--port",
"4507",
],
cwd: moduleDir,
stdout: "null",
stderr: "null",
});
child = fileServer.spawn();
try {
const resp = await fetch(
`http://localhost:4507/testdata/${basename(tempDir)}`,
);
assertEquals(resp.status, 200);
await resp.text(); // Consuming the body so that the test doesn't leak resources
} finally {
await killFileServer();
Deno.removeSync(tempDir);
}
},
);

0 comments on commit 8bd34c3

Please sign in to comment.