Search code examples
javascriptpythonsocketshttpmultipart

Trying to understand the multipart response error "TypeError: Could not parse content as FormData."


I have a simple python server that is sending a multipart response to a javascript client, but I get this error TypeError: Could not parse content as FormData.

python server

import time
import socket
import socketserver
import ssl
import numpy as np
from io import BytesIO
from PIL import Image

transfer_bytes = BytesIO()


s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
## the reusaddr part means you don't have to wait to restart
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

s.bind(("localhost",58886))
s.listen(1)
def handle_request(conn):
    print("handling!!")
    response_header = f"""
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type:multipart/form-data;boundary=xxx  

--xxx
Content-Type: text/plain ;
Content-Disposition: form-data; name="first"

hello world
--xxx
Content-Type: text/plain ;
Content-Disposition: form-data; name="second"

end
--xxx--
    """.strip()
    ## prepare the multipart response

    conn.send(f"{response_header}".encode())
    

while True:
    print("waiting for next request")
    conn,addr = s.accept()
    #conn, addr = ssock.accept()
    handle_request(conn)
    conn.shutdown(socket.SHUT_RDWR)
    conn.close()
    print("fulfilled request")
    time.sleep(1)

javascript client

window.onload = async ()=> {
  fetch("http://localhost:58886").then(res=>res.formData()).then(t=> console.log(t)).catch(err => console.log(err))
}

In the network console on firefox I see that the client recognizes the type as multipart, but for some reason the error still happens. enter image description here enter image description here

similar questions that aren't exactly the same: fetch response on client with form-data from server, Constructing multipart response


Solution

  • There are two problems with the response

    • The line ending should be \r\n not \n. This is true both for the header as the multipart boundaries and MIME headers in the body. While the browser seems to accept \n for the header (even though this is not standard compliant) it is less forgiving for the multipart MIME body.
    • The end of the multipart MIME body is --boundary--\r\n, not --boundary, i.e. the line ending is essential.

    This fixes these problems:

    response_header = str.replace(response_header, "\n", "\r\n") + "\r\n"