Skip to content

Instantly share code, notes, and snippets.

@empjustine
Last active February 1, 2025 03:02
Show Gist options
  • Save empjustine/20addba5f8310c14f67e22517854835f to your computer and use it in GitHub Desktop.
Save empjustine/20addba5f8310c14f67e22517854835f to your computer and use it in GitHub Desktop.
-- toy multipart/form-data parser for https://redbean.dev/
-- if you want something that actually works, check fullmoon:
-- https://github.com/pkulchenko/fullmoon/blob/9d62cff189b106ddb540c98539861e27c418055f/fullmoon.lua#L267
Write('<!DOCTYPE html>')
-- boundary --
local content_type = GetHeader('Content-Type')
local boundary = content_type:match("boundary=(.+)")
Write('<p>boundary')
Write(EscapeHtml(boundary))
-- boundary --
Write('<form method="post" enctype="multipart/form-data">')
Write('<p>text1<input type="text" name="text1" value="lolcats">')
Write('<p>file1<input type="file" name="file1">')
Write('<p>file2<input type="file" name="file2">')
Write('<p><input type="submit">')
-- Content-Type multipart/form-data; boundary=---------------------------125536326932407176451145831590
-- -----------------------------125536326932407176451145831590
-- Content-Disposition: form-data; name="text1"
--
-- lolcats
-- -----------------------------125536326932407176451145831590
-- Content-Disposition: form-data; name="file1"; filename=""
-- Content-Type: application/octet-stream
--
--
-- -----------------------------125536326932407176451145831590
-- Content-Disposition: form-data; name="file2"; filename=""
-- Content-Type: application/octet-stream
--
--
-- -----------------------------125536326932407176451145831590--
local function parse_multipart(data, boundary)
local fields = {}
local files = {}
for part in data:gmatch("--" .. boundary .. "\r\n(.-)\r\n--" .. boundary) do
local name = part:match('Content%-Disposition: form%-data; name="(.-)"')
local filename = part:match('filename="(.-)"')
local content_type = part:match('Content%-Type: ([%w/-]+)') or "application/octet-stream"
local value = part:match('\r\n\r\n(.*)')
if name then
if filename and filename ~= "" then
files[name] = { filename = filename, content_type = content_type , data = value }
else
fields[name] = value
end
end
end
return fields, files
end
local fields, files = parse_multipart(GetBody(), boundary)
for k, v in pairs(fields) do
Write('<p>k=')
Write(k)
Write('<p>v=')
Write(v)
end
for k, v in pairs(files) do
Write('<p>k=')
Write(k)
Write('<p>v.filename=')
Write(v.filename)
Write('<p>v.content_type=')
Write(v.content_type)
Write('<p>v.data=')
Write(v.data)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment