MrSmiley
MrSmiley

Reputation: 357

Python multipart/form-data Post Request

So I've been trying to send a multipart/form-data request, unsuccessfully. At the current moment I get the error back that the Required part of the request is missing.

{'message': "Required request part 'registrationMetadata' is not present", 'httpStatus': '500 INTERNAL_SERVER_ERROR'}

I know it's unwise to specify the headers in a request as Requests takes care of that. But if I don't I get the following error:

'''{'message': "Content type '' not supported", 'httpStatus': '500 INTERNAL_SERVER_ERROR'}'''

The disable warning and verify=false are unimportant in the case of this application as it is not reachable for the outside world.

This is my python script:

import requests
from requests_toolbelt.utils import dump

import json
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = "<ValidUrl>"
data = {"registrationMetadata": '{"firstName":"<name>","lastName":"<lastName>","mobileNumber":"<mobilenumber>","serialNumber":"1234","country":"BE","signingProfile":"sms","externalId":"<externalId>","email": "<email>","language": "nl"}'}
headers = {'Content-Type': 'multipart/form-data; boundary=ebf9f03029db4c2799ae16b5428b06bd'}
auth = ('<username>', '<password>')

session = requests.session()
response = session.post(url, data=str(data), auth=auth, verify=False)

req_dump = dump.dump_all(response)
print(req_dump.decode('utf-8'))

print(response.request.body)
print(response.json())

I'll add the headers of the request:

< POST <valid url> HTTP/1.1
< Host: <valid host>
< User-Agent: python-requests/2.22.0
< Accept-Encoding: gzip, deflate
< Accept: */*
< Connection: keep-alive
< Content-Type: multipart/form-data; boundary=ebf9f03029db4c2799ae16b5428b06bd
< Content-Length: 237
< Authorization: Basic <valid auth key>==

The request works in our java framework and postman. So I'm at wits end. In the meantime I've searched for an applicable solution. Including the MultipartEncoder. Neither seems to have worked. I'm assuming the difficulty lies in the nested values of the formData. And that I'm missing something obvious.

Upvotes: 0

Views: 1279

Answers (1)

Michael
Michael

Reputation: 153

This is very specific to this endpoint and registrationMetadata is not part of the standard. So my suggestion below may have an impact or it may not, it really depends on the server-side which without seeing we can't provide much assistance at all I'm afraid.

However, it would appear in your registrationMetadata data field you are including single quotes around your inner-dict as part of the string. What I think you might be after is this:

data = {
   "registrationMetadata": {"firstName":"<name>","lastName":"<lastName>","mobileNumber":"<mobilenumber>","serialNumber":"1234","country":"BE","signingProfile":"sms","externalId":"<externalId>","email": "<email>","language": "nl"},
}

rather than what you're doing, which is this:

data = {
       "registrationMetadata": '{"firstName":"<name>","lastName":"<lastName>","mobileNumber":"<mobilenumber>","serialNumber":"1234","country":"BE","signingProfile":"sms","externalId":"<externalId>","email": "<email>","language": "nl"}',
    }

You should also use the 'json' library instead of casting to a string type in your request. Just changing it to a string might not be enough.

session = requests.session()
response = session.post(url, data=json.dumps(data), auth=auth, verify=False)

EDIT: What I find really helps eliminate this sort of issue is to define my dict's across multiple lines, example below:

data = {
    "registrationMetadata": {
        "firstName": "<name>",
        "lastName": "<lastName>",
        "mobileNumber": "<mobilenumber>",
        "serialNumber": "1234", 
        "country": "BE", 
        "signingProfile": "sms", 
        "externalId": "<externalId>", 
        "email": "<email>", 
        "language": "nl",
    },
}

Upvotes: 1

Related Questions