blob: 31a4ffbfd0210e1a4dc1052acd7e8fa74f45809b [file] [log] [blame]
import io
import json
import urllib.parse
import aiohttp.web
import multipart
BOXER_MAX_PAYLOAD = 256 * 1024
async def parse_formdata(body_type, request: aiohttp.web.BaseRequest) -> dict:
indata = {}
for key, val in urllib.parse.parse_qsl(request.query_string):
indata[key] = val
# PUT/POST form data?
if request.method in ["PUT", "POST"]:
if request.can_read_body:
try:
if (
request.content_length
and request.content_length > BOXER_MAX_PAYLOAD
):
raise ValueError("Form data payload too large, max 256kb allowed")
body = await request.text()
if body_type == "json":
try:
js = json.loads(body)
assert isinstance(
js, dict
) # json data MUST be an dictionary object, {...}
indata.update(js)
except ValueError:
raise ValueError("Erroneous payload received")
elif body_type == "form":
if (
request.headers.get("content-type", "").lower()
== "application/x-www-form-urlencoded"
):
try:
for key, val in urllib.parse.parse_qsl(body):
indata[key] = val
except ValueError:
raise ValueError("Erroneous payload received")
# If multipart, turn our body into a BytesIO object and use multipart on it
elif (
"multipart/form-data"
in request.headers.get("content-type", "").lower()
):
fh = request.headers.get("content-type")
fb = fh.find("boundary=")
if fb > 0:
boundary = fh[fb + 9 :]
if boundary:
try:
for part in multipart.MultipartParser(
io.BytesIO(body.encode("utf-8")),
boundary,
len(body),
):
indata[part.name] = part.value
except ValueError:
raise ValueError("Erroneous payload received")
finally:
pass
return indata