server/plugins/formdata.py (59 lines of code) (raw):

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