All files / http / unstable_file_server.ts

100.00% Branches 0/0
100.00% Lines 24/24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
 
x1
x1
 
x1
 
x1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
x1
 
x3
x3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x1
x1
x1
x1
 
x2
 
x2
x2
x2
x2
x2
x2
x2
x2
 
x2
x2













































































































#!/usr/bin/env -S deno run --allow-net --allow-read
// Copyright 2018-2025 the Deno authors. MIT license.
import {
  serveDir as stableServeDir,
  type ServeDirOptions as StableServeDirOptions,
  serveFile as stableServeFile,
  type ServeFileOptions as StableServeFileOptions,
} from "./file_server.ts";

/**
 * Serves the files under the given directory root (opts.fsRoot).
 *
 * @experimental **UNSTABLE**: New API, yet to be vetted.
 *
 * @example Usage
 * ```ts ignore
 * import { serveDir } from "@std/http/file-server";
 *
 * Deno.serve((req) => {
 *   const pathname = new URL(req.url).pathname;
 *   if (pathname.startsWith("/static")) {
 *     return serveDir(req, {
 *       fsRoot: "path/to/static/files/dir",
 *     });
 *   }
 *   // Do dynamic responses
 *   return new Response();
 * });
 * ```
 *
 * @example Changing the URL root
 *
 * Requests to `/static/path/to/file` will be served from `./public/path/to/file`.
 *
 * ```ts ignore
 * import { serveDir } from "@std/http/file-server";
 *
 * Deno.serve((req) => serveDir(req, {
 *   fsRoot: "public",
 *   urlRoot: "static",
 * }));
 * ```
 *
 * @param req The request to handle
 * @param opts Additional options.
 * @returns A response for the request.
 */
export function serveDir(
  req: Request,
  opts: ServeDirOptions = {},
): Promise<Response> {
  return stableServeDir(req, opts);
}

/** Interface for serveDir options. */
export interface ServeDirOptions extends StableServeDirOptions {
  /**
   * Also serves `.html` files without the need for specifying the extension.
   * For example `foo.html` could be accessed through both `/foo` and `/foo.html`.
   *
   * @default {false}
   */
  cleanUrls?: boolean;
}

/** Interface for serveFile options. */
export interface ServeFileOptions extends StableServeFileOptions {
  /** Headers to add to each response
   *
   * @default {[]}
   */
  headers?: string[];
}

/**
 * Resolves a {@linkcode Response} with the requested file as the body.
 *
 * @experimental **UNSTABLE**: New API, yet to be vetted.
 *
 * @example Usage
 * ```ts ignore
 * import { serveFile } from "@std/http/file-server";
 *
 * Deno.serve((req) => {
 *   return serveFile(req, "README.md");
 * });
 * ```
 *
 * @param req The server request context used to cleanup the file handle.
 * @param filePath Path of the file to serve.
 * @param options Additional options.
 * @returns A response for the request.
 */
export async function serveFile(
  req: Request,
  filePath: string,
  options?: ServeFileOptions,
): Promise<Response> {
  const response = await stableServeFile(req, filePath, options);

  if (options?.headers) {
    for (const header of options.headers) {
      const headerSplit = header.split(":");
      const name = headerSplit[0]!;
      const value = headerSplit.slice(1).join(":");
      response.headers.append(name, value);
    }
  }

  return response;
}