1

I am trying to upload an image attachment through an API, the something can be achieved through a web interface. Both make requests to the same url, same headers, everything. But the issue is that the mimetype of the png image is not detected by the server when I make the python request. When retrieving the image again, the content-Type is 'application/octet-stream' rather than 'image/png' (which is what I get when I retrieve the interface-uploaded one). this causes further problems down the road in my pipeline.

Here's a detailed view of the correct (webinterface) request: (via Wireshark) correct request analysis

and the python request: wrong request analysis

The main difference I see here is that in the correct one, the file is detected as 'Portable Network Image' rather than 'Media Type'. I can't find anything related to how it decides that, so to know that would be great.

I have tried using the exact same header set with the correct tokens, still the same problem.

Here's my code for making the request:

headers2 = { \
    'IUCLID6-USER' : headers['USER'] ,
    'IUCLID6-PASS' : headers['PASS'] ,
    'Accept' : 'application/json, text/plain, */*' ,
    'Accept-Encoding': 'gzip, deflate',
    'Connection' : 'keep-alive',
    'Content-Disposition' : "attachment;name="+fname+";filename*=utf-8''" + fname,
    'Content-Length' : str(os.path.getsize(os.path.join(sys.path[0], fname))),
    'Content-Type': 'image/png'
    }

    files = {'attachment': (fname, open(os.path.join(sys.path[0], fname), 'rb'), 'image/png'),}
    data= {'filetype' : 'image/png'}
    # files = {'attachment': open(os.path.join(sys.path[0], fname), 'rb')}
    response = requests.post(base_url + "raw/attachment", headers=headers2, files=files)

Note: when using the data arg rather than files, I noticed that the retrieved 'Content-Type' became 'text/plain'. This is the only case where it changed.

Another Note: I'm not sure if the key in 'files' has to do anything with it but I have tried 'files', 'file', 'media', 'image', and 'data' to no avail. Would be also good to know based on what should the files object be structured.

I don't know why the python request doesn't match the interface request, and its driving me crazy. So any help would be appreciated.

EDIT: the proper request's curl command:

curl 'http://url.com:8080/iuclid6-ext/api/ext/v1/raw/attachment' \
  -X 'POST' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Language: en' \
  -H 'Authorization: Token eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhNDIzOWI3My1kZDQ0LTRmZGEtOTRkOS1lM2NlZGMyZDZiZjMiLCJpc3MiOiJpdWNsaWQ2LXRva2VuLXNlcnZlciIsInN1YiI6IlN1cGVyVXNlciIsImlhdCI6MTY5MTQwNDQ3MSwiZXhwIjoxNjkxNDA1MDcxLCJzY29wZXMiOlsiYWNjZXNzIl19.VWkb6XYEOKulICaXgLN9gkq4qvdKFDFwwx5b_zeVSlU' \
  -H 'Connection: keep-alive' \
  -H $'Content-Disposition: attachment;filename*=utf-8\'\'Logo-for-a-brand-named-Petrol--style-is-a-mix-of-vintage--retro--sci-fi-space--diesel--motorsport--and-mad-max-styles--The-logo-consists-of-the-name-Petrol-and-a-gas-canister-in-a-stylish-and-pretty-l%20%281%29%20%281%29.png' \
  -H 'Content-Length: 1058156' \
  -H 'Content-Type: image/png' \
  -H 'Origin: http://url.com:8080' \
  -H 'Referer: http://url.com:8080/iuclid6-web/raw/REFERENCE_SUBSTANCE/261bbd71-d826-43ef-9227-93403e892422/(main-content:content/iuclid6:%2F0%2FREFERENCE_SUBSTANCE%2F261bbd71-d826-43ef-9227-93403e892422/)?node=261bbd71-d826-43ef-9227-93403e892422' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.44' \
  --compressed \
  --insecure
spospider
  • 21
  • 5

2 Answers2

1

It's challenging to provide a precise solution without examining the file/original request.

A way for troubleshooting this would be to:

  1. Obtain the CURL command from Wireshark. Use a tool to convert the pcap to Curl: pcap2curl .

Or: convert the actual request in the browser:

enter image description here

  1. Once you have the CURL command, you can then convert it into Python code using a tool like curlconverter.com.

By comparing the converted Python code with your existing Python code, you should be able to pinpoint the problem

See also

Similar to my answer: Post request works in postman but not in python code

MendelG
  • 14,885
  • 4
  • 25
  • 52
  • Highly thankful for your response, I tried that but the curl and the python code does not contain anything about the file itself. which is where I think the issue is. Added the curl command to the question. – spospider Aug 07 '23 at 13:05
  • @spospider interesting... how about testing it in Postman and then converting it again to Curl? – MendelG Aug 07 '23 at 13:12
  • Thanks for your suggestion, I had never heard of this tool before. Upon playing around with it I managed to make the correct request! It even directly exports the python code! Thanks to you I have this awesome tool in my arsenal. Cheers! – spospider Aug 07 '23 at 13:46
0

Upon the suggestion of the awesome @MendelG. I managed to replicate the correct request in Postman. after exporting to python it turns out that the payload should be just the binary file assigned to the data arg as such‍♂️

data= open(os.path.join(sys.path[0], fname), 'rb')
response = requests.post(base_url + "raw/attachment", headers=headers2, data=data)

Here's to spending hours debugging a tiny issue that could've been resolved with proper documentation.

spospider
  • 21
  • 5