1 | import http from 'http'
|
2 | import { parse as parseUrl } from 'url'
|
3 | import { parse as parseQuery } from 'query-string'
|
4 | import rawBody from 'raw-body'
|
5 | import mime from 'mime-types'
|
6 | import { AWS } from './types'
|
7 |
|
8 |
|
9 | const BASE_64_MIME_REGEXP = /image|audio|video|application\/pdf|application\/zip|applicaton\/octet-stream/i
|
10 | function shouldBase64Encode(contentType: string) {
|
11 | return Boolean(contentType) && BASE_64_MIME_REGEXP.test(contentType)
|
12 | }
|
13 |
|
14 | export async function requestToEvent(req: http.IncomingMessage): Promise<AWS['HandlerEvent']> {
|
15 |
|
16 | const remoteAddress = String(req.headers['x-forwarded-for']) || req.connection.remoteAddress || ''
|
17 | const ip = remoteAddress
|
18 | .split(remoteAddress.includes('.') ? ':' : ',')
|
19 | .pop()
|
20 | ?.trim()
|
21 | const isBase64Encoded = shouldBase64Encode(req.headers['content-type'] || '')
|
22 | const body = req.headers['content-length']
|
23 | ? await rawBody(req, {
|
24 | limit: '1mb',
|
25 | encoding: mime.charset(req.headers['content-type'] || '') || undefined,
|
26 | })
|
27 | : undefined
|
28 |
|
29 | return {
|
30 | path: req.url as string,
|
31 | httpMethod: req.method as string,
|
32 |
|
33 | headers: {
|
34 | ...req.headers,
|
35 | 'client-ip': ip,
|
36 | },
|
37 |
|
38 | multiValueHeaders: Object.keys(req.headers).reduce((headers, key) => {
|
39 | if (req.headers[key] && !(req.headers[key] as string).includes(',')) return headers
|
40 |
|
41 | return {
|
42 | ...headers,
|
43 |
|
44 | [key]: req.headers[key].split(','),
|
45 | }
|
46 | }, {}),
|
47 |
|
48 | queryStringParameters: parseQuery(parseUrl(req.url).query),
|
49 | body: body ? new Buffer(body).toString(isBase64Encoded ? 'base64' : 'utf8') : null,
|
50 | isBase64Encoded,
|
51 | }
|
52 | }
|