POST file upload causes HTTP 400 error response - python

I am trying to upload a file using POST requests in Python (requests library).
I get HTTP 400 error as a response. I think it is because my POST request is not in the format it should be. Any ideas how to convert POST request 1 into 2?
Code:
files = {"file": ("test-file.txt", open("c:/users/johndoe/desktop/test-file.txt", "rb"), "text/plain")}
response = webdriver.request("POST", "https://something.com/attachments", files = files)
What I currently have (1):
--d9bd23df892242a489b0f638d62502a6
Content-Disposition: form-data; name="file"; filename="test-file.txt"
Content-Type: text/plain
This is a test file.
Regards,
John Doe
--d9bd23df892242a489b0f638d62502a6--
What I should have (2):
-----------------------------26789175756830
Content-Disposition: form-data; name="fileName"
test-file.txt
-----------------------------26789175756830
Content-Disposition: form-data; name="fileSize"
45
-----------------------------26789175756830
Content-Disposition: form-data; name="description"
undefined
-----------------------------26789175756830
Content-Disposition: form-data; name="file"; filename="test-file.txt"
Content-Type: text/plain
This is a test file.
Regards,
John Doe
-----------------------------26789175756830--
What I think I need to add (3):
-----------------------------26789175756830
Content-Disposition: form-data; name="fileName"
test-file.txt
-----------------------------26789175756830
Content-Disposition: form-data; name="fileSize"
45
-----------------------------26789175756830
Content-Disposition: form-data; name="description"
undefined
-----------------------------26789175756830

You have to explicitly specify the fields fileName, fileSize, and description, since requests won't generate them for you automatically:
import os
import requests
filepath = 'foo'
files = {'file': open(filepath, 'rb')}
data = {
'fileName': filepath,
'fileSize': os.path.getsize(filepath),
'description': 'undefined'
}
response = requests.post('http://www.example.com/', data=data, files=files);
This generates a request like:
POST / HTTP/1.1
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate
Host: www.example.com
User-Agent: python-requests/2.13.0
Content-Length: 439
Content-Type: multipart/form-data; boundary=75a7213b6b4f493fabe26feeafb8551c
Http.Entity.Parser.Multipart.Tempdir: /tmp/pZjDE
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="description"
undefined
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="fileSize"
16
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="fileName"
foo
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="file"; filename="foo"
contents of foo
--75a7213b6b4f493fabe26feeafb8551c--

Related

Reading raw http request by name value

Given the data below, I am trying the get the value of each of the content-disposition by name. For example get the subject, or to values. For example, I would like to be able to look for "html" and it will give me:
<html><body><strong>Hello SendGrid!</body></html>
Im not sure how I should do this? Had something like this in mind:
subject = full_msg[full_msg.find('Content-Disposition: form-data;
name="subject"')+len('Content-Disposition: form-data;
name="subject"'):full_msg.rfind('--xYzZY')].strip()
--xYzZY
Content-Disposition: form-data; name="headers"
MIME-Version: 1.0
Received: by 0.0.0.0 with HTTP; Wed, 10 Aug 2016 18:10:13 -0700 (PDT)
From: Example User <test#example.com>
Date: Wed, 10 Aug 2016 18:10:13 -0700
Subject: Inbound Parse Test Data
To: inbound#inbound.example.com
Content-Type: multipart/alternative; boundary=001a113df448cad2d00539c16e89
--xYzZY
Content-Disposition: form-data; name="dkim"
{#sendgrid.com : pass}
--xYzZY
Content-Disposition: form-data; name="to"
inbound#inbound.example.com
--xYzZY
Content-Disposition: form-data; name="html"
<html><body><strong>Hello SendGrid!</body></html>
--xYzZY
Content-Disposition: form-data; name="from"
Example User <test#example.com>
--xYzZY
Content-Disposition: form-data; name="text"
Hello SendGrid!
--xYzZY
Content-Disposition: form-data; name="sender_ip"
0.0.0.0
--xYzZY
Content-Disposition: form-data; name="envelope"
{"to":["inbound#inbound.example.com"],"from":"test#example.com"}
--xYzZY
Content-Disposition: form-data; name="attachments"
0
--xYzZY
Content-Disposition: form-data; name="subject"
Testing non-raw
--xYzZY
Content-Disposition: form-data; name="charsets"
{"to":"UTF-8","html":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"UTF-8"}
--xYzZY
Content-Disposition: form-data; name="SPF"
pass
--xYzZY--
import email
full_msg = request.POST['email']
msg = email.message_from_string(full_msg)
from_address = msg["from"]

Missing header information using Python's requests library

I am using Python's (3.5.2) requests library (2.12.4) to post a query to the Primer-BLAST website. Below is the script I've written for this task:
#!/usr/bin/env python
import requests
# BaseURL being accessed
url = 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi'
# Dictionary of query parameters
data = {
'INPUT_SEQUENCE' : 'TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA',
'ORGANISM' : 'Mus musculus'
}
# Make a POST request and read the response
with requests.session() as session:
poster = session.post(url, data=data)
for key, value in poster.headers.items():
print(key, ':', value)
I need to retrieve the NCBI-RCGI-RetryURL field from the response's header information. However, I can only see this field when I use the HTTP trace extension in Google Chrome. Below is the full trace of the POST and response using Google Chrome:
POST https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi
Origin: https://www.ncbi.nlm.nih.gov
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://www.ncbi.nlm.nih.gov/tools/primer-blast/index.cgi?LINK_LOC=reset
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: sv-userdata-key-www.ncbi.nlm.nih.gov=G5KxXzyQ81U_vs1aHK_7XDWciF1B8AjjDUmDunVbhIZhZ4p4t_SVK4ASpbTT8iDSJVcxBH9oUAB3K2xNWjp3G0koYCloBlYuSxdoIGIkYzl2; ncbi_sid=0751457F9A561D01_0000SID; _ga=GA1.2.567134514.1503994317; _gid=GA1.2.654339584.1503994317; _gat=1; starnext=MYGwlsDWB2CmAeAXAXAbgK7RAewIYBM4lkAmAXgAcAnMAW1ioCMRcBnRAMgBYzm3FWsXFWAALDgEZymHAUkBOMgAYA7AFYpXFQDF5AQTUA2ACIBRFRKVXrN2xI4klygMJcSltQA59R0wGY/S1tg63t3Shp6JhZ2AFI/PQA5AHlE03i9PnZBYTEMlLSHcgB3UoA6aGBGMAqQWgqwUTKAc2wANwceajoGLMR81NMHQwie6P4BtIy+nJFxEhVRqL7J9ISZoTnVh08l3pj+lWcC9KON3NFYo5OHRQkuLiUOPyd5K2eJMnvH5/JPDWefjIADNcCBBM8eIgqOhYM81F83GpniMJH4SPJnosSFxnrtAoZ5Li/IoXp5DCpuE50RIpNxPlIAtxyNBcIgwG04Q8yDI8IQEJwuAiSBw1EDvk81DxPEo/KKEfIRUYyCRDIZRYtJbtaT81HcOIYnE9DAycUA=
HTTP/1.1 200 OK
Date: Tue, 29 Aug 2017 13:38:27 GMT
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Referrer-Policy: origin-when-cross-origin
Content-Security-Policy: upgrade-insecure-requests
Cache-Control: no-cache, no-store, max-age=0, private, must-revalidate
Expires: 0
NCBI-PHID: 0C421A7A9A56E5310000000000000001.m_2
NCBI-RCGI-RetryURL: https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi?ctg_time=1504013907&job_key=aWO2H68Wor6FhLSBueGQs8P6gYHu6Zqc7w
NCBI-SID: 0751457F9A561D01_0000SID
Pragma: no-cache
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, PATCH, DELETE
Access-Control-Allow-Origin: https://www.ncbi.nlm.nih.gov
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,X-Accept-Charset,X-Accept,Content-Type,X-Requested-With,NCBI-SID,NCBI-PHID
Content-Type: text/html
Set-Cookie: ncbi_sid=0751457F9A561D01_0000SID; domain=.nih.gov; path=/; expires=Wed, 29 Aug 2018 13:38:27 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
X-UA-Compatible: IE=Edge
X-XSS-Protection: 1; mode=block
Keep-Alive: timeout=1, max=9
Connection: Keep-Alive
Transfer-Encoding: chunked
And here is all the header information I get from my script:
Date : Tue, 29 Aug 2017 14:41:08 GMT
Server : Apache
Strict-Transport-Security : max-age=31536000; includeSubDomains; preload
Referrer-Policy : origin-when-cross-origin
Content-Security-Policy : upgrade-insecure-requests
Accept-Ranges : bytes
Vary : Accept-Encoding
Content-Encoding : gzip
X-UA-Compatible : IE=Edge
X-XSS-Protection : 1; mode=block
Content-Length : 2516
Keep-Alive : timeout=1, max=10
Connection : Keep-Alive
Content-Type : text/html
The NCBI-RCGI-RetryURL field is important because it contains the URL I need to execute a GET request on in order to retrieve the results.
EDIT:
Updated script as per Maurice Meyer's suggestion:
#!/usr/bin/env python
import requests
# BaseURL being accessed
url = 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi'
# Dictionary of query parameters
data = {
'INPUT_SEQUENCE' : 'TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA',
'ORGANISM' : 'Mus musculus'
}
# Extra headers
headers = {
'Origin' : 'https://www.ncbi.nlm.nih.gov',
'Upgrade-Insecure-Requests' : '1',
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36',
'Content-Type' : 'multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9',
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Referer' : 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/index.cgi?LINK_LOC=reset',
'Accept-Encoding' : 'gzip, deflate, br',
'Accept-Language' : 'en-US,en;q=0.8',
'Cookie' : 'sv-userdata-key-www.ncbi.nlm.nih.gov=G5KxXzyQ81U_vs1aHK_7XDWciF1B8AjjDUmDunVbhIZhZ4p4t_SVK4ASpbTT8iDSJVcxBH9oUAB3K2xNWjp3G0koYCloBlYuSxdoIGIkYzl2; ncbi_sid=0751457F9A561D01_0000SID; _ga=GA1.2.567134514.1503994317; _gid=GA1.2.654339584.1503994317; _gat=1; starnext=MYGwlsDWB2CmAeAXAXAbgK7RAewIYBM4lkAmAXgAcAnMAW1ioCMRcBnRAMgBYzm3FWsXFWAALDgEZymHAUkBOMgAYA7AFYpXFQDF5AQTUA2ACIBRFRKVXrN2xI4klygMJcSltQA59R0wGY/S1tg63t3Shp6JhZ2AFI/PQA5AHlE03i9PnZBYTEMlLSHcgB3UoA6aGBGMAqQWgqwUTKAc2wANwceajoGLMR81NMHQwie6P4BtIy+nJFxEhVRqL7J9ISZoTnVh08l3pj+lWcC9KON3NFYo5OHRQkuLiUOPyd5K2eJMnvH5/JPDWefjIADNcCBBM8eIgqOhYM81F83GpniMJH4SPJnosSFxnrtAoZ5Li/IoXp5DCpuE50RIpNxPlIAtxyNBcIgwG04Q8yDI8IQEJwuAiSBw1EDvk81DxPEo/KKEfIRUYyCRDIZRYtJbtaT81HcOIYnE9DAycUA='
}
# Make a POST request and read the response
with requests.session() as session:
poster = session.post(url, data=data, headers=headers)
for key, value in poster.headers.items():
print(key, ':', value)
Updated output, still no difference:
Date : Tue, 29 Aug 2017 15:05:27 GMT
Server : Apache
Strict-Transport-Security : max-age=31536000; includeSubDomains; preload
Referrer-Policy : origin-when-cross-origin
Content-Security-Policy : upgrade-insecure-requests
Accept-Ranges : bytes
Vary : Accept-Encoding
Content-Encoding : gzip
X-UA-Compatible : IE=Edge
X-XSS-Protection : 1; mode=block
Content-Length : 2517
Keep-Alive : timeout=1, max=10
Connection : Keep-Alive
Content-Type : text/html
The request data between the two is totally different.
Specifically the request body data. So it really isn't missing header information using Python's requests library - it is missing information the in POST request to server.
You can't simply copy and paste the header
'Content-Type' : 'multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9',
Or just post the data INPUT_SEQUENCE and ORGANISM like that - also in any case the data you do have for ORGANISM is clearly wrong - a cursory glance shows it would be Mus musculus (taxid:10090) not Mus musculus.
So - you need to look at the whole request - headers and body, then craft a request that includes the required data by the server. Looking at it you are missing loads and loads of data that the server will need to respond.
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="INPUT_SEQUENCE"
TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEQFILE"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER5_START"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER5_END"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER3_START"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER3_END"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_LEFT_INPUT"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_RIGHT_INPUT"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_PRODUCT_MIN"
70
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_PRODUCT_MAX"
1000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_NUM_RETURN"
10
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MIN_TM"
57.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_OPT_TM"
60.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MAX_TM"
63.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MAX_DIFF_TM"
3
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_ON_SPLICE_SITE"
0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SPLICE_SITE_OVERLAP_5END"
7
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SPLICE_SITE_OVERLAP_3END"
4
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="MIN_INTRON_SIZE"
1000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="MAX_INTRON_SIZE"
1000000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEARCH_SPECIFIC_PRIMER"
on
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEARCHMODE"
0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_SPECIFICITY_DATABASE"
refseq_mrna
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="CUSTOM_DB"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="CUSTOMSEQFILE"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="ORGANISM"
Mus musculus (taxid:10090)
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
etc...

Python requests, unable to upload image to multipart/form-data

I am using python requests to upload a jpeg image file to a multipart form.
This is what I see if I inspect the request made by normally uploading the image using the browser:
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="uploadphotos"
true
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="deletephoto"
0
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_0"; filename="1 KIN
GRD.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path0"
C:\fakepath\1 KIN GRD.jpg
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="e$phMain$UploadButton0"
Upload photo
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_1"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path1"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_2"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path2"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_3"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path3"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_4"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path4"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_5"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path5"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_6"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path6"
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_input_7"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryKGkGxMtaz943aFXQ
Content-Disposition: form-data; name="upload_path7"
------WebKitFormBoundaryKGkGxMtaz943aFXQ--
This is the python code I am using to upload the first image in the form (it is possible to upload up to 8 images), but first I should be able to upload at least the first one:
files = {'upload_input_0': ("test_image.jpg", open('test_image.jpg', 'rb'),'image/jpg')}
r = requests.post(upload_image_url, headers = headers, files=files)
but I am not able to upload the image.
EDIT: this is not the same question. My question is related to this single specific case: what is the correct request in this specific situation? do I have to send the multipart request with ALL the fields inside (as I would publish all the images)?
EDIT2: I have found the solution:
multipart_form_data = {
'uploadphotos': (None, 'true', None),
'deletephoto': (None, '0', None),
'upload_input_0': ("test2.jpg", open('test2.jpg', 'rb'),'image/jpeg'),
'upload_path0': (None, 'C:\fakepath\test2.jpg', None),
'e$phMain$UploadButton0': (None, 'Upload photo', None),
'upload_input_1': ('', ''),
'upload_path1': (None, '', None),
'upload_input_2': ('', ''),
'upload_path2': (None, '', None),
'upload_input_3': ('', ''),
'upload_path3': (None, '', None),
'upload_input4': ('', ''),
'upload_path4': (None, '', None),
'upload_input_5': ('', ''),
'upload_path5': (None, '', None),
'upload_input_6': ('', ''),
'upload_path6': (None, '', None),
'upload_input_7': ('', ''),
'upload_path7': (None, '', None),
}
r = s.post(upload_image_url, headers = headers_s, files=multipart_form_data)
Which is a perfectly working solution!

python requests login with "multipart/form-data"

Today I tried to login on a website using python requests. That website is using multipart/form-data to login.
I tried to get the http request going through the web.
This is what I got:
1
-----------------------------25373143914744
Content-Disposition: form-data; name="csrfKey"
c720e331f5ba76c1ca5d389adfecbf7f
-----------------------------25373143914744
Content-Disposition: form-data; name="ref"
aHR0cHM6Ly93d3cuY3JhY2tpbmdvZXouY29tLz9fZnJvbUxvZ291dD0x
-----------------------------25373143914744
Content-Disposition: form-data; name="MAX_FILE_SIZE"
7340032
-----------------------------25373143914744
Content-Disposition: form-data; name="plupload"
b8f090b305d37f4f77bbf7966aa6e932
-----------------------------25373143914744
Content-Disposition: form-data; name="auth"
deewfwef
-----------------------------25373143914744
Content-Disposition: form-data; name="password"
wefwefwef
-----------------------------25373143914744
Content-Disposition: form-data; name="remember_me"
0
-----------------------------25373143914744
Content-Disposition: form-data; name="remember_me_checkbox"
1
-----------------------------25373143914744
Content-Disposition: form-data; name="signin_anonymous"
0
-----------------------------25373143914744--
Is there any way to login a website that using "multipart/form-data" with python requests?
How can I send this details to the server and get back the response?

415 error when uploading to API

I am trying to write an automatic subtitle finder in Python 3.x using The SubDB (http://thesubdb.com/api/). I'm now working on an upload feature. However, I cannot get it to work. I keep getting a 415 error (Unsupported Media Type). On the SubDB website, a 'request sample' is given:
POST /?action=upload HTTP/1.1
Host: api.thesubdb.com
User-Agent: SubDB/1.0 (Pyrrot/0.1; http://github.com/jrhames/pyrrot-cli)
Content-Length: 60047
Content-Type: multipart/form-data; boundary=xYzZY
- - --xYzZY
Content-Disposition: form-data; name="hash"
edc1981d6459c6111fe36205b4aff6c2
- - --xYzZY
Content-Disposition: form-data; name="file"; filename="subtitle.srt"
Content-Type: application/octet-stream
[PAYLOAD]
But I do not know how to interpret this and I couldn't find an answer online. This is my current code:
def uploadSubtitle(hash, path):
params = {'action': "upload", 'hash': hash}
response = requests.post(
url=base_url.format(urllib.parse.urlencode(params)),
data=open(path,'r').read(),
headers = {
'User-Agent': user_agent,
'Content-Length': 51200,
'Content-Type': "multipart/form-data; boundary=xYzZY",
'Host': "api.thesubdb.com"
}
)
return response.status_code
Any advice would be greatly appreciated!
I was having the same issues.
You may want to see this https://github.com/ivandrofly/SubDBSharp
Try following:
POST /?action=upload HTTP/1.1
Host: api.thesubdb.com
User-Agent: SubDB/1.0 (Pyrrot/0.1; http://github.com/jrhames/pyrrot-cli)
Content-Length: [Subtitle content length including boundary length]
Content-Type: multipart/form-data; boundary=xYzZY
--xYzZY
Content-Disposition: form-data; name="hash"
edc1981d6459c6111fe36205b4aff6c2
--xYzZY
Content-Disposition: form-data; name="file"; filename="subtitle.srt"
Content-Type: application/octet-stream
[SUBTITLE CONTENT]
--xYzZY
# Content-Length:
Content length should be from --xYzZY to last --xYzZY see above.
Note: Boundary started --xYzZY and ends after [SUBTITLE CONTENT]

Categories

Resources