-
Notifications
You must be signed in to change notification settings - Fork 0
/
static.ts
82 lines (73 loc) · 2.77 KB
/
static.ts
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
// Copyright 2023-2024 the Sequoia authors. All rights reserved. MIT license.
import { stdPath } from './deps.ts'
import { HTTPError, InternalError, NotFoundError } from './error.ts'
import { HTTPResponse } from './httpresponse.ts'
import { ContentType } from './media.ts'
import { HTTPStatus } from './status.ts'
import { defineContentType, normalizePath } from './util.ts'
export const INDEX_FILENAME = 'index.html'
export async function fileExists(src: string): Promise<boolean> {
try {
return (await Deno.stat(src)).isFile
} catch {
return false
}
}
export async function serveFile(src: string): Promise<HTTPResponse> {
try {
const fileInfo = await Deno.stat(src)
if (fileInfo.isDirectory) {
throw new HTTPError(HTTPStatus.FORBIDDEN, 'The requested file is a directory')
}
const file = await Deno.open(src, { read: true })
const size = fileInfo.size
const contentType = defineContentType(stdPath.basename(src))
const headers = new Headers()
headers.set('Content-Length', size.toString())
const response = new HTTPResponse({
status: HTTPStatus.SUCCESS,
type: contentType || ContentType.PLAIN,
body: file.readable,
headers,
})
return response
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
throw new NotFoundError('The page you are looking for is not found')
} else throw error
}
}
export async function serveStatic(
url: URL,
path: string,
dir: string,
): Promise<HTTPResponse> {
const filename = url.pathname.endsWith('/') ? '/' : stdPath.basename(url.pathname)
const relativePath = url.pathname.replace(normalizePath(path), '')
if (filename) {
const filepath = stdPath.join(stdPath.normalize(dir), relativePath)
let response: HTTPResponse | undefined = undefined
try {
if (await fileExists(filepath)) {
response = await serveFile(filepath)
} else if (await fileExists(stdPath.join(filepath, `${INDEX_FILENAME}`))) {
response = await serveFile(stdPath.join(filepath, `${INDEX_FILENAME}`))
}
if (!response) {
throw new HTTPError(
HTTPStatus.NOT_FOUND,
'The page you are looking for is not found',
)
}
return response
} catch (error) {
if (error instanceof HTTPError) {
throw error
}
throw new InternalError(
error instanceof Error ? error.message : 'Internal server error',
)
}
}
throw new HTTPError(HTTPStatus.NOT_FOUND, 'The page you are looking for is not found')
}