Strange behaviour of request.POST in Django - python

I'm sending a POST request to a Django server through Postman. This is what the body of my request looks like
POST /update/ HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: multipart/form-data; boundary=----
WebKitFormBoundary7MA4YWxkTrZu0gW
Cache-Control: no-cache
Postman-Token: 0764e56c-0fd8-fcce-5248-34f7d05f2748
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="UploadDownloadSettings"
dssssss
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="settings";
filename="settings.zip"
Content-Type: application/zip
When I try to access request.POST['UploadDownloadSettings'], the program says the key is not valid.
When I loop through the keys in request.POST I get a bunch of keys from the zip file and the key name.
According to the docs, this should parse out form-data. This seems like standard form data as far as I understand.
https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.HttpRequest.POST
Am I misunderstanding the way the django post request works?
Output of request.POST
Key:
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition
Value:
form-data
Key:
name
Value:
"UploadDownloadSettings"
Key:
//actual filenames from the zip with their value
Value:
Blank
Output of request.FILES: blank map
Output of request.content_type: application/x-www-form-urlencoded

Related

How to use WebKitFormBoundary data as your payload when posting to the server with python?

Hopefully, my question makes sense, but I'll try to explain it better here.
So, this is the post request data that was sent to the server when I analyzed the post request headers:
------WebKitFormBoundaryq4q6NLNtlzAsbRBY
Content-Disposition: form-data; name="form_type"
product
------WebKitFormBoundaryq4q6NLNtlzAsbRBY
Content-Disposition: form-data; name="utf8"
✓
------WebKitFormBoundaryq4q6NLNtlzAsbRBY
Content-Disposition: form-data; name="id"
36110014939287
------WebKitFormBoundaryq4q6NLNtlzAsbRBY
Content-Disposition: form-data; name="add"
I have two issues here. I am trying to use this data to send as my payload in a post request like a dictionary, but I'm not really sure how I would do this as I've never seen anything like this before.
Second, I see there is a hidden value for the "utf8" name, so how would I go about decoding that value and converting it back to a string.
Again, hopefully this makes sense and I'm sorry if it doesn't - I will do my best to respond to any follow up questions.
Thanks!
if you are using ajax use contentType: false;
or
use enctype="application/x-www-form-urlencoded" in form
<form enctype="application/x-www-form-urlencoded">

POST request with sent form data does not return correct response

I´m trying to log in to a website using my account. In python code, I use:
login_response = session.post('mysite.com', login_data, cookies=session.cookies)
where session is a requests session object, the cookies are exactly the cookies that are also sent when I try the same in a browser (it´s two specific cookies that are sent by the browser as part of the request when I log in), and login_data is a dictionary of form data that is sent in the post request.
However, the expected response is: code 303, a redirect link is sent, and two new cookies (that are the use login session). This is what happens in the browser.
When I want to do this with the code above, I get instead code 200, no redirect link, and no cookies. It´s as if the site just 'reloads'. The form data itself (password + user) is correct.
I read the request content from my browser:
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="login__standard_submitted"
1
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="csrfKey"
2fcc7af2aa54f0e3ab85a6bdeca26f98
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="ref"
aHR0cHM6Ly9jcmltZW1hcmtldC53by8=
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="MAX_FILE_SIZE"
20971520
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="plupload"
92ee7fd8f0a2249c2327184c5b95d6c9
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="auth"
myusername
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="password"
password
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="remember_me"
0
-----------------------------366521339228594542373308740035
Content-Disposition: form-data; name="remember_me_checkbox"
1
-----------------------------366521339228594542373308740035--
The data I get from this, I just wrote into a dictionary of key: values, e.g.
'auth': 'myusername'
Again a tl;dr:
I send the right cookies and what I observed as seemingly correct data when performing the POST request in code. However, I get an entirely different result than in the browser, and fail to log in.
Did I misunderstand something? What do I need to change to log in by code?
EDIT: In the headers, I also set 'Content-Type' to 'multipart/form-data', just as in the browser.
EDIT 2: Instead if I set login_data with files=, it still doesn´t work.
From what I have seen you have to use files= to send a multipart/form-data request using request.post however you have to use tuples and set the filename to NOne so they are not sent as files.
login_data = (
('login__standard_submitted', (None, '1')),
('csrfKey', (None, '2fcc7af2aa54f0e3ab85a6bdeca26f98')),
('ref', (None, 'aHR0cHM6Ly9jcmltZW1hcmtldC53by8')),
...
)
login_response = session.post('mysite.com', files=login_data, cookies=session.cookies)
I wonder if your session object is sending an http: request and should instead send a https: request. This could lead to a redirect with 303 response. The "requests" package seems to handle this type of response.
import requests
res = requests.get('http://google.com')
print(res.url)
res = requests.get('http://stackoverflow.com')
print(res.url)
The output to those above are
http://www.google.com/
https://stackoverflow.com/

How can I change header in request and pass it to another IP

I want to change header of request and change destination IP and pass it to the correct destination.
How can I do it by flask and python.
This is my header
Host: 10.1.3.127:5000
Accept-Encoding: identity
X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Content-Length: 0
X-Amz-Date: 20191110T122830Z
Authorization: AWS4-HMAC-SHA256 Credential=yasin1/20191110/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=08610e134c60ffdfe3b4d8159d740b398b38565d0d38481cb405739bc401adea
User-Agent: Boto3/1.10.2 Python/2.7.12 Linux/4.4.0-142-generic Botocore/1.13.2 Resource
I want to change Host to 10.1.3.41:8080 and make requset to this destination.

"TypeError: must be str, not bytes" when trying to access request.POST field

I have this webservice, based on the Pyramid framework, that accepts a multipart/form-data request.
Everything works when I send the request from cURL;
however from the Android application, it fails with the following error
TypeError: must be str, not bytes
when I try to access any field : e.g. request.POST.get('smartphoneId', None)
The difference is that the Android library adds a few headers to the fields, notably the Content-Transfer-Encoding. From cURL each value is sent as follows :
--------------------------5f28b737bc4e4813
Content-Disposition: form-data; name="smartphoneId"
2
whereas from Android (with retrofit) :
--0e0a43aa-3156-48ee-a949-931dcc4eb8be
Content-Disposition: form-data; name="smartphoneId"
Content-Type: text/plain; charset=UTF-8
Content-Length: 3
Content-Transfer-Encoding: 8BIT
999
Initially the Content-Transfer-Encoding was binary ; I manually changed it to 8BIT, but I get the same error. Seems that Python can't parse / handle the content of each field.
Any idea ?
I had the same problem (with Python 3.4). To solve the problem, I created a patch for the following module "webob/compat.py" : replace the existing patch of multi_read by the current version from python cgi 3.5. And now, it works. I will create a pr on the github repository.
See https://bugs.python.org/issue27777.
I created a pull request for webob : https://github.com/Pylons/webob/pull/281

return text/html content-type when using flask-restful

In a specific case I'd like to respond with a text/html content-type for an error as follows:
class MyResource(Resource):
def get(self):
if some_condition:
return 'bad argument', 400
The code above returns an application/json content-type: '"bad argument"'
instead of a text/html content-type: 'bad argument'
How can I force flask-restful to respond with text/html content-type?
You'll have to use flask.make_response() to return a 'pre-baked' response object:
return flask.make_response('bad argument', 400)
Flask-Restful will pass full-on Response objects unaltered, rather than try and convert them to a specific requested mime type.

Categories

Resources