Need a help on to write test automation for API which has a multipart form data

curl --location --request POST ‘BASE_URL’
–header ‘Authorization: Bearer ’
–form ‘meta=“{JSON_DATA}”;type=application/json’
–form ‘payload=“{JSON_DATA}”;type=application/json’
–form ‘zipPayload=@“ZIP_FILE”’

Hi,

Welcome to the forum!

Could you provide some context, like: What is the problem you are facing?

Regards,
Markus

This is what I tried but getting status=415, reason=Unsupported Media Type ${files}= Create Dictionary meta=(${meta_json}, “application/json”) payload=(${payload_json}, “application/json”) zipPayload=(${file_dict}, “multipart/form-data”)
Log ${files}
${response}= POST On Session my_session ${ENDPOINT} headers=&{header} files=${files}

*** Settings ***
Library JSONLibrary
Library Collections
Library OperatingSystem
Library RequestsLibrary
Library XML
Resource …/…/Resources/NWC/Configure_workload.resource
Resource …/…/Resources/Common/General/beforeAndAfterTest.resource
Resource …/…/Resources/NWC/Store_Config_Model.resource

Suite Setup Before Suite
Suite Teardown After Suite
Test Setup Before Test

*** Variables ***
${BASE_URL}
${ENDPOINT} /<end_point>
${META} {“version”: “1.0”, “date”: “2025-01-27 10:43:46”, “traceID”: “12345-6789-3456”, “originator”: “Workload designer”}
${PAYLOAD} {“command”: “store_config_model”, “target”: “4f9ff4a3-21d0-499f-a62a-e4fdcbb3069d”, “commandPayload”: {“modelUuid”: “50b27321-b984-4fac-998b-926f2b01e597”, “modelName”: “Device”}}
${ZIP_FILE_PATH} <zip_file_path>

*** Test Cases ***
Store Config Model
[Tags] API
&{header}= Create Dictionary Authorization=Bearer ${token} X-Tenant=${TENANT} Accept-Encoding=gzip, deflate, br
Create Session my_session ${BASE_URL}
${file}= Evaluate open(‘${ZIP_FILE_PATH}’, ‘rb’)
${file_dict}= Create Dictionary zipPayload=${file}
${meta_json}= Evaluate json.dumps(${META})
${payload_json}= Evaluate json.dumps(${PAYLOAD})
${files}= Create Dictionary meta=(${meta_json}, “application/json”) payload=(${payload_json}, “application/json”) zipPayload=(${file_dict}, “multipart/form-data”)
Log ${files}
${response}= POST On Session my_session ${ENDPOINT} headers=&{header} files=${files}
Log ${response.status_code}
Log ${response.text}
Should Be Equal As Strings ${response.status_code} 200

You’re getting a 415 Unsupported Media Type. What you’re sending is either not properly formatted or the server does not support what you’re trying to send. I expect the former; from the looks of it, the files dict that you create does not adhere to the requests API interface as found here:
Developer Interface — Requests 2.32.3 documentation

It seems you want to use the {"name": file-tuple} format, but to include the encoding, you need to use the ("filename", fileobj, content_type) tuple, which your code does not do.

Thanks for response : But still I am getting same FAIL] HTTPError: 415 Client Error: Unsupported Media Type.
I am using below robot test file :
${files}= Create Dictionary meta={“meta.json”, json.dumps${META}, application/json} payload={“payload.json”, json.dumps${PAYLOAD}, application/json} zipPayload={“config.zip”, open(${zipplayload_file}, “rb”)}
${response}= POST On Session mysession / files=${files}

When I am using Postman API request working fine :
curl --location --request POST ‘BASE_URL’
–header ‘Authorization: Bearer ’
–form ‘meta=“{JSON_DATA}”;type=application/json’
–form ‘payload=“{JSON_DATA}”;type=application/json’
–form ‘zipPayload=@“ZIP_FILE”’

I would try to break down the request to see which parts work and which parts do not. You currently have 4-5 places in your code that might cause a problem so try to build it up step by step.

Also see Quickstart — Requests 2.32.3 documentation

First try to get the upload to work with a single json file. Then all of the json files. Than the zip in isolation. Then all of them.

Also note that you may have to create actual tuple variables (using Evaluate or creating a simple Python library).

There’s a tool called netcat. On linux machines, its nc. Start netcat at some random port and point the url in postman to http://localhost:your_random_port_here.

Run postman, see output in the window netcat is running and copy paste to safety.

Restart netcat again, run your robot/requests code again towards that netcat port.

Compare the differences and 99% the time its very easy to see why postman request passes but your robot/python/requests req does not.

4 Likes

Still get the for single json data request
status=415, reason=Unsupported Media Type
headers={‘Date’: ‘Mon, 30 Dec 2024 06:10:30 GMT’, ‘Content-Length’: ‘0’, ‘Connection’: ‘keep-alive’, ‘Accept’: ‘application/json, application/*+json’, ‘Cache-Control’: ‘no-cache, no-store, max-age=0, must-revalidate’, ‘Pragma’: ‘no-cache’, ‘Expires’: ‘0’, ‘X-Content-Type-Options’: ‘nosniff’, ‘Strict-Transport-Security’: ‘max-age=31536000; includeSubDomains’, ‘X-Frame-Options’: ‘DENY’, ‘X-XSS-Protection’: ‘0’, ‘Referrer-Policy’: ‘no-referrer’}
body=None API request
Create Session api_session ${URL}
${headers}= Create Dictionary Authorization=Bearer ${token} X-Tenant=Test Accept-Encoding=gzip, deflate, br
${META}= Create Dictionary version=XX date=2025-01-27 10:43:46 traceID=12345-6789-3456 originator=RobotTest
${meta_json}= Evaluate json.dumps(${META}) json
${files}= Create Dictionary meta=(“meta.json”, ${meta_json}, “application/json”)
${response}= POST On Session api_session ${URL} headers=${headers} files=${files}
Should Be Equal As Numbers ${response.status_code} 200
Log ${response.json()}

I’d definitely give rasjani’s suggestion a try.

You may also want to try the approach found here:

You’re currently passing JSON-serialized data into a files upload instead of passing a file stream. So instead of using json.dumps, use the Get File For Streaming Upload keyword.
For further details, see the RequestsLibrary documentation:
RequestsLibrary (search for POST a Multipart-Encoded File).

Thank you for support and help. After below changes it is working fine for me.
${meta_data}= Get File For Streaming Upload ${META_FILE}
${meta_file_tuple}= Create List meta.json ${meta_data} application/json
${payload_data}= Get File For Streaming Upload ${PAYLOAD_FILE}
${payload_file_tuple}= Create List meta.json ${payload_data} application/json
${zipPayload_file}= Evaluate open(‘${ZIP_FILE_PATH}’, ‘rb’)
${files}= Create Dictionary meta=${meta_file_tuple} payload=${payload_file_tuple} zipPayload=${zipPayload_file}