-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
body_parser.ts
103 lines (101 loc) 路 2.93 KB
/
body_parser.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { MultipartReader } from "./vendor/https/deno.land/std/mime/multipart.ts";
import {
FormFile,
isFormFile
} from "./vendor/https/deno.land/std/multipart/formfile.ts";
import Reader = Deno.Reader;
export interface FormBody {
field(field: string): string | undefined;
file(field: string): FormFile | undefined;
removeAllTempFiles(): Promise<void>;
}
/**
* Parse multipart/form-data request
* @param req ServerRequest
* @param maxMemory maximum memory size for file part.
* Small file will be stored in memory, Big file in tempfile
*/
export async function parserMultipartRequest(
req: { headers: Headers; body?: Reader },
maxMemory?: number
): Promise<FormBody> {
//Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryO5quBRiT4G7Vm3R7
const contentType = req.headers.get("content-type");
if (!req.body) {
throw new Error("request has no body");
}
if (!contentType || !contentType.match("multipart/form-data")) {
throw new Error("is not multipart request");
}
let m = contentType.match(/boundary=([^ ]+?)$/);
if (!m) {
throw new Error("doesn't have boundary");
}
const boundary = m[1];
const reader = new MultipartReader(req.body, boundary);
const form = await reader.readForm(maxMemory);
return {
field(field: string): string | undefined {
const v = form[field];
if (typeof v === "string") {
return v;
}
},
file(field: string): FormFile | undefined {
const v = form[field];
if (isFormFile(v)) {
return v;
}
},
async removeAllTempFiles(): Promise<void> {
const arr = Object.values(form).filter(isFormFile) as FormFile[];
const promises: Promise<void>[] = [];
for (const v of arr) {
if (v.tempfile) {
promises.push(
(async () => {
try {
const stat = await Deno.stat(v.tempfile);
if (stat.isFile()) {
await Deno.remove(v.tempfile);
}
} catch (e) {}
})()
);
}
}
await Promise.all(promises);
}
};
}
/**
* Parse application/x-www-form-urlencoded request
* @param req part of ServerRequest
*/
export async function parseUrlEncodedForm(req: {
headers: Headers;
body?: Reader;
}): Promise<FormBody> {
const contentType = req.headers.get("content-type");
if (!req.body) {
throw new Error("request has no body");
}
if (
!contentType ||
!contentType.match(/^application\/x-www-form-urlencoded/)
) {
throw new Error("is not form urlencoded request");
}
const buf = new Deno.Buffer();
await Deno.copy(buf, req.body);
const params = new URLSearchParams(decodeURIComponent(buf.toString()));
return {
field(field: string): string | undefined {
return params.get(field) || undefined;
},
file(field: string): FormFile | undefined {
return undefined;
},
async removeAllTempFiles(): Promise<void> {}
};
}