Search code examples
pythonflask

Getting wrong fields in Flask server from message from another Python script


I have flaks server with that part of code:

@app.route("/calculate", methods=['POST', 'OPTIONS'])
def calculate():
    process_data = request.form
    uploaded_file = request.files.get('file')
    data_type = process_data.get("data_type")
    sample_rate = process_data.get("sample_rate")
    sample_rate = int(sample_rate)
... The rest of the function

And I'am sending then request using that script:

 headers = {'Content-Type': 'multipart/form-data'}

    files = {
        'file': open("some file path", 'rb'),
    }

    data = {
        'data_type': 'XYZ',
        'sample_rate': '64',
    }

    response = requests.post('http://127.0.0.1:8444/calculate', headers=headers, files=files, data=data)

And while debugging the server there is no request.form neither request.files. All parameters are then in strange format in request.data.

What am I missing? It works correctly usign postman or curl


Solution

  • Remove the headers from your requests.post() and it should work as expected, requests will make sure to add the corresponding headers for you.

    Without manually adding a header

    >>> r = requests.post(url, data={"data_type":"Hello, World!", "foo":"bar"}, files={'file': open('README.md', 'rb')})
    >>> vars(r.request)
    {'method': 'POST', 'url': 'http://localhost:5000/', 'headers': {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '380', 'Content-Type': 'multipart/form-data; boundary=5610d214668da3ae3665b2fed56811b3'}, '_cookies': <RequestsCookieJar[]>, 'body': b'--5610d214668da3ae3665b2fed56811b3\r\nContent-Disposition: form-data; name="data_type"\r\n\r\nHello, World!\r\n--5610d214668da3ae3665b2fed56811b3\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--5610d214668da3ae3665b2fed56811b3\r\nContent-Disposition: form-data; name="file"; filename="README.md"\r\n\r\n# Test\r\n\r\nProject to test StackOverflow code.\r\n--5610d214668da3ae3665b2fed56811b3--\r\n', 'hooks': {'response': []}, '_body_position': None}
    

    Adding the header {'Content-Type': 'multipart/form-data'}

    >>> r = requests.post(url, data={"data_type":"Hello, World!", "foo":"bar"}, files={'file': open('README.md', 'rb')}, headers={'Content-Type': 'multipart/form-data'})
    >>> vars(r.request) 
    {'method': 'POST', 'url': 'http://localhost:5000/', 'headers': {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'multipart/form-data', 'Content-Length': '380'}, '_cookies': <RequestsCookieJar[]>, 'body': b'--1c5ae5e3112ce929fcdd66b68e2bfc0e\r\nContent-Disposition: form-data; name="data_type"\r\n\r\nHello, World!\r\n--1c5ae5e3112ce929fcdd66b68e2bfc0e\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--1c5ae5e3112ce929fcdd66b68e2bfc0e\r\nContent-Disposition: form-data; name="file"; filename="README.md"\r\n\r\n# Test\r\n\r\nProject to test StackOverflow code.\r\n--1c5ae5e3112ce929fcdd66b68e2bfc0e--\r\n', 'hooks': {'response': []}, '_body_position': None}
    

    They look similar, the difference is that when you don't overwrite requests header, it defines and sets a boundary in the header to separate paramaters in the request ('Content-Type': 'multipart/form-data; boundary=5610d214668da3ae3665b2fed56811b3'). When you overwrite it, although requests does set a boundary for the data, you are overwriting the header that tells the server what is the boundary, so the server won't be able to read the data sent properly.