Skip to content

Instantly share code, notes, and snippets.

@webjay
Created December 13, 2022 19:03
Show Gist options
  • Save webjay/31eb7cc7d81ae0adbf67901edac7c6d7 to your computer and use it in GitHub Desktop.
Save webjay/31eb7cc7d81ae0adbf67901edac7c6d7 to your computer and use it in GitHub Desktop.
multi parse
import { NextApiRequest } from 'next';
// Inspired by https://github.com/myshenin/aws-lambda-multipart-parser
export interface FilePart {
type: string
filename: string
contentType: string
content: unknown
}
interface Part {
[name: string]: FilePart | string
}
function getBoundary({ headers: { 'content-type': contentType } }: NextApiRequest) {
return contentType?.toLowerCase().split('boundary=')[1].trim()
}
function itemMatch(item: string, re: RegExp) {
const match = re.exec(item)
if (match === null) {
return ''
}
return match[1]
}
function getContent(item: string) {
if (/filename=".+"/g.test(item)) {
const key = itemMatch(item, /name="(.+)";/g)
const value = {
type: 'file',
filename: itemMatch(item, /filename="(.+)"/g),
contentType: itemMatch(item, /Content-Type:\s(.+)/g),
content: item.slice(
item.search(/Content-Type:\s.+/g) +
itemMatch(item, /(Content-Type:\s.+)/g).length + 4,
-4
),
}
return { [key]: value }
} else if (/name=".+"/g.test(item)) {
const key = itemMatch(item, /name="(.+)"/g)
const value = item.slice(
item.search(/name=".+"/g) + itemMatch(item, /(name=".+")/g).length + 4,
-4
)
return { [key]: value }
}
}
export function multiParse(req: NextApiRequest) {
const boundary = getBoundary(req)
if (!boundary) {
return null
}
const fields: string[] = req.body?.split(boundary)
if (!fields) {
return null
}
return fields.reduce((result, item) => ({
...result,
...getContent(item)
}), {} as Part)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment