-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsend.ts
38 lines (32 loc) · 1 KB
/
send.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
import { Stats } from 'fs'
import { stat, open } from 'fs/promises'
import { join, resolve, sep } from 'path'
import { Readable } from 'stream'
import error from './error'
interface ReadStreamAndStat {
path: string,
stat: Stats,
stream: Readable
}
const BAD_PATH_REGEX = /^[\.]{1,2}$/
export function normalize_path(root: string, path: string): string {
try {
path = decodeURIComponent(path)
if (~path.indexOf('\0'))
throw error(400)
} catch (e) {
throw error(400)
}
if (!path.split(sep).every(p => !BAD_PATH_REGEX.test(p)))
throw error(403)
return resolve(join(root, path ? '.' + sep + path : path))
}
export async function send(root: string, path: string): Promise<ReadStreamAndStat> {
path = normalize_path(root, path)
let info = await stat(path).catch(() => { throw error(404) })
if (info.isDirectory()) {
throw error(404)
}
const handle = await open(path, 'r').catch(() => { throw error(404) })
return { path, stat: info, stream: handle.createReadStream() }
}