forked from vercel/micro
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbody.ts
75 lines (61 loc) · 1.78 KB
/
body.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
// Native
import { IncomingMessage } from 'http';
// Packages
import contentType from 'content-type';
import getRawBody from 'raw-body';
// Utilities
import { IncomingOpts } from './types';
import { MicriError, MicriBodyError } from './errors';
// Maps requests to buffered raw bodies so that
// multiple calls to `json` work as expected
const rawBodyMap = new WeakMap();
export async function buffer(
req: IncomingMessage,
{ limit = '1mb' }: IncomingOpts = { limit: '1mb' }
): Promise<Buffer> {
const length = req.headers['content-length'];
const body = rawBodyMap.get(req);
if (body) {
return body;
}
try {
const buf = await getRawBody(req, { limit, length });
rawBodyMap.set(req, buf);
return buf;
} catch (err: any) {
throw new MicriBodyError(err, limit);
}
}
export async function text(
req: IncomingMessage,
{ limit = '1mb', encoding }: IncomingOpts = { limit: '1mb' }
): Promise<string> {
const type = req.headers['content-type'] || 'text/plain';
const length = req.headers['content-length'];
const body = rawBodyMap.get(req);
if (body) {
return body;
}
// eslint-disable-next-line no-undefined
if (encoding === undefined) {
encoding = contentType.parse(type).parameters.charset;
}
try {
const buf = await getRawBody(req, { limit, length, encoding });
rawBodyMap.set(req, buf);
// toString() shouldn't be needed here but it doesn't hurt
return buf.toString();
} catch (err: any) {
throw new MicriBodyError(err, limit);
}
}
function parseJSON(str: string): ReturnType<typeof JSON.parse> {
try {
return JSON.parse(str);
} catch (err: any) {
throw new MicriError(400, 'invalid_json', 'Invalid JSON', err);
}
}
export function json(req: IncomingMessage, opts?: IncomingOpts): Promise<any> {
return text(req, opts).then((body) => parseJSON(body));
}