mirror of
https://github.com/denoland/deno.git
synced 2025-02-08 15:21:26 -05:00
fix(file_server): use media_types for Content-Type header (#4555)
This commit is contained in:
parent
5ac2c4aa2e
commit
fa7929ad2c
3 changed files with 57 additions and 39 deletions
|
@ -7,7 +7,8 @@
|
||||||
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
|
// https://github.com/indexzero/http-server/blob/master/test/http-server-test.js
|
||||||
|
|
||||||
const { args, stat, readdir, open, exit } = Deno;
|
const { args, stat, readdir, open, exit } = Deno;
|
||||||
import { posix } from "../path/mod.ts";
|
import { contentType } from "../media_types/mod.ts";
|
||||||
|
import { posix, extname } from "../path/mod.ts";
|
||||||
import { listenAndServe, ServerRequest, Response } from "./server.ts";
|
import { listenAndServe, ServerRequest, Response } from "./server.ts";
|
||||||
import { parse } from "../flags/mod.ts";
|
import { parse } from "../flags/mod.ts";
|
||||||
import { assert } from "../testing/asserts.ts";
|
import { assert } from "../testing/asserts.ts";
|
||||||
|
@ -96,21 +97,22 @@ function fileLenToString(len: number): string {
|
||||||
return `${(len / base).toFixed(2)}${suffix[suffixIndex]}`;
|
return `${(len / base).toFixed(2)}${suffix[suffixIndex]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function serveFile(
|
export async function serveFile(
|
||||||
req: ServerRequest,
|
req: ServerRequest,
|
||||||
filePath: string
|
filePath: string
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const [file, fileInfo] = await Promise.all([open(filePath), stat(filePath)]);
|
const [file, fileInfo] = await Promise.all([open(filePath), stat(filePath)]);
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
headers.set("content-length", fileInfo.size.toString());
|
headers.set("content-length", fileInfo.size.toString());
|
||||||
headers.set("content-type", "text/plain; charset=utf-8");
|
const contentTypeValue = contentType(extname(filePath));
|
||||||
|
if (contentTypeValue) {
|
||||||
const res = {
|
headers.set("content-type", contentTypeValue);
|
||||||
|
}
|
||||||
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: file,
|
body: file,
|
||||||
headers,
|
headers,
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: simplify this after deno.stat and deno.readdir are fixed
|
// TODO: simplify this after deno.stat and deno.readdir are fixed
|
||||||
|
@ -296,39 +298,45 @@ function html(strings: TemplateStringsArray, ...values: unknown[]): string {
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
listenAndServe(
|
function main(): void {
|
||||||
addr,
|
listenAndServe(
|
||||||
async (req): Promise<void> => {
|
addr,
|
||||||
let normalizedUrl = posix.normalize(req.url);
|
async (req): Promise<void> => {
|
||||||
try {
|
let normalizedUrl = posix.normalize(req.url);
|
||||||
normalizedUrl = decodeURIComponent(normalizedUrl);
|
try {
|
||||||
} catch (e) {
|
normalizedUrl = decodeURIComponent(normalizedUrl);
|
||||||
if (!(e instanceof URIError)) {
|
} catch (e) {
|
||||||
throw e;
|
if (!(e instanceof URIError)) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fsPath = posix.join(target, normalizedUrl);
|
||||||
|
|
||||||
|
let response: Response | undefined;
|
||||||
|
try {
|
||||||
|
const info = await stat(fsPath);
|
||||||
|
if (info.isDirectory()) {
|
||||||
|
response = await serveDir(req, fsPath);
|
||||||
|
} else {
|
||||||
|
response = await serveFile(req, fsPath);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e.message);
|
||||||
|
response = await serveFallback(req, e);
|
||||||
|
} finally {
|
||||||
|
if (CORSEnabled) {
|
||||||
|
assert(response);
|
||||||
|
setCORS(response);
|
||||||
|
}
|
||||||
|
serverLog(req, response!);
|
||||||
|
req.respond(response!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const fsPath = posix.join(target, normalizedUrl);
|
);
|
||||||
|
|
||||||
let response: Response | undefined;
|
console.log(`HTTP server listening on http://${addr}/`);
|
||||||
try {
|
}
|
||||||
const info = await stat(fsPath);
|
|
||||||
if (info.isDirectory()) {
|
|
||||||
response = await serveDir(req, fsPath);
|
|
||||||
} else {
|
|
||||||
response = await serveFile(req, fsPath);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e.message);
|
|
||||||
response = await serveFallback(req, e);
|
|
||||||
} finally {
|
|
||||||
if (CORSEnabled) {
|
|
||||||
assert(response);
|
|
||||||
setCORS(response);
|
|
||||||
}
|
|
||||||
serverLog(req, response!);
|
|
||||||
req.respond(response!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(`HTTP server listening on http://${addr}/`);
|
if (import.meta.main) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import { assert, assertEquals, assertStrContains } from "../testing/asserts.ts";
|
import { assert, assertEquals, assertStrContains } from "../testing/asserts.ts";
|
||||||
import { BufReader } from "../io/bufio.ts";
|
import { BufReader } from "../io/bufio.ts";
|
||||||
import { TextProtoReader } from "../textproto/mod.ts";
|
import { TextProtoReader } from "../textproto/mod.ts";
|
||||||
|
import { ServerRequest } from "./server.ts";
|
||||||
|
import { serveFile } from "./file_server.ts";
|
||||||
const { test } = Deno;
|
const { test } = Deno;
|
||||||
let fileServer: Deno.Process;
|
let fileServer: Deno.Process;
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ function killFileServer(): void {
|
||||||
fileServer.stdout?.close();
|
fileServer.stdout?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
test(async function serveFile(): Promise<void> {
|
test("file_server serveFile", async (): Promise<void> => {
|
||||||
await startFileServer();
|
await startFileServer();
|
||||||
try {
|
try {
|
||||||
const res = await fetch("http://localhost:4500/README.md");
|
const res = await fetch("http://localhost:4500/README.md");
|
||||||
|
@ -141,3 +143,11 @@ test(async function printHelp(): Promise<void> {
|
||||||
helpProcess.close();
|
helpProcess.close();
|
||||||
helpProcess.stdout.close();
|
helpProcess.stdout.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("contentType", async () => {
|
||||||
|
const request = new ServerRequest();
|
||||||
|
const response = await serveFile(request, "http/testdata/hello.html");
|
||||||
|
const contentType = response.headers!.get("content-type");
|
||||||
|
assertEquals(contentType, "text/html; charset=utf-8");
|
||||||
|
(response.body as Deno.File).close();
|
||||||
|
});
|
||||||
|
|
0
std/http/testdata/hello.html
vendored
Normal file
0
std/http/testdata/hello.html
vendored
Normal file
Loading…
Add table
Reference in a new issue