Handling form data with flask request - python

I am using flask-restful as an api server and am constructing the first PUT method. Using request imported from flask, I am able to access request.form data without issue with the following cURL command:
curl http://127.0.0.1:5000/api/v1/system/account -X PUT -d username=asdas -d email=asdasd#test.com
My PUT method logs out both the username and email without issue:
def put(self):
print 'SystemAccountPut'
print request.form['username']
print request.form['email']
return
Output:
SystemAccountPut
asdas
asdasd#test.com
I have an app using the axios project to make api calls. When axios attempts to PUT form data, request.form no longer works. Here is the call axios is making converted to cURL command from Chrome Dev Console:
curl 'http://127.0.0.1:5000/api/v1/system/account' -X PUT -H 'Pragma: no-cache' -H 'Origin: http://127.0.0.1:5000' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36' -H 'Content-Type: application/json;charset=UTF-8' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: http://127.0.0.1:5000/settings' -H 'Connection: keep-alive' --data-binary '{"username":"asdas","email":"asdasd#test.com"}' --compressed
With the same method above request.form['username'] and request.form['email'] are empty. request.data however has the form data in it, and request.get_json() also will output the form data in JSON format.
My question is what should I be using in this case to retrieve the form data? The first curl command is clean with request.form having the data I need, but request.data is empty. The second cURL command leaves request.form broken but does populate request.data. Is there a best practice on how I should retrieve form data in both cURL cases?

I figured out the issue after further learning more about incoming forms and some insight from davidism. The first cURL example has the following Content-Type: application/x-www-form-urlencoded. The second cURL command has the following Content-Type: application/json;charset=UTF-8. Unsurprisingly, the first cURL command sends form data to request.form and the second cURL command is interpreted as data and can retrieved at request.data or request.get_json(). For my needs I want to get the form data either way, so in my put method I have the following:
data = request.get_json() or request.form
print data['email']
print data['username']
This gives me the email and password in both cURL examples.

Related

How to consume this API in Python? I just can't

So i'm trying to consume this API, I got this URL http://www.ventamovil.com.mx:9092/service.asmx?op=Check_Balance
There you can write this {"User":"6144135400","Password":"Prueba$$"} on the input field and you get a response.
https://i.stack.imgur.com/RTEii.png
Response
But when i try to consume this api on python i just can't, i don't exactly know how to consume correctly:
My Code
As you can see i got a different response with my code, i should be getting the same response as the "Response" image.
To save yourself some time, you can use their request to build python code automatically, all you have to do is:
Just as you did at first, enter the json in the input field and invoke.
open the network tab, copy the post request they made as curl
curl 'http://www.ventamovil.com.mx:9092/service.asmx/Check_Balance' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36' -H 'Origin: http://www.ventamovil.com.mx:9092' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' -H 'Referer: http://www.ventamovil.com.mx:9092/service.asmx?op=Check_Balance' -H 'Accept-Language: en-US,en;q=0.9,ar;q=0.8,pt;q=0.7' --data 'jrquest=%7B%22User%22%3A6144135400%2C+%22Password%22%3A+%22Prueba%24%24%22%7D' --compressed --insecure
Go to postman and import the curl, then click code and select python, and here you go you have all the right headers needed
import requests
url = "http://www.ventamovil.com.mx:9092/service.asmx/Check_Balance"
payload = 'jrquest=%7B%22User%22%3A6144135400%2C+%22Password%22%3A+%22Prueba%24%24%22%7D'
headers = {
'Upgrade-Insecure-Requests': '1',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
}
response = requests.request("POST", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
As you can see, they accept their input as form encoded payload.
You need to modify this request to be parameterized with user/password you want each time you use.
Btw, the output of this python code is:
b'<?xml version="1.0" encoding="utf-8"?>\r\n<string xmlns="http://www.ventamovil.com.mx/ws/">{"Confirmation":"00","Saldo_Inicial":"10000","Compras":"9360","Ventas":"8416","Comision":"469","Balance":"10345.92"}</string>'

Translating Python HTTP request to curl

I have the code below in Python which is making a POST request for an OAuth2 token. It uses basic authentication.
The code works fine, but I would like to "translate it" to curl.
The code:
#Authorization: Basic c29tZV91c2VyOnBhc3M=
#some_user:pass = base64decode('c29tZV91c2VyOnBhc3M=')
def get_access_token():
burp0_url = "https://myurl:443/api/oauth/token"
burp0_headers = {"Accept": "application/json", "Authorization": "Basic c29tZV91c2VyOnBhc3M=", "Content-Type": "application/x-www-form-urlencoded", "Connection": "close", "Accept-Encoding": "gzip, deflate", "User-Agent": "okhttp/3.0.1"}
burp0_data={"grant_type": "client_credentials"}
return json.loads(requests.post(burp0_url, headers=burp0_headers,
data=burp0_data).text)['access_token']
My guess was be that it would look something like this:
curl -v -XPOST -H 'Authorization: Basic c29tZV91c2VyOnBhc3M=' --header 'Accept: application/json' --header 'Connection: close' --header 'Accept-Encoding: gzip, deflate' --header 'User-Agent: okhttp/3.0.1' --data '{"grant_type": "client_credentials"}' https://myurl:443/api/oauth/token
However I keep getting a HTTP/1.1 400 and the following
* Failed writing body (0 != 10)
* Failed writing data
* stopped the pause stream!
* Closing connection 0
Can you help me?
Looks like you forgot to copy the "Content-Type": "application/x-www-form-urlencoded" header into your curl command.
This would also suggest the data is not submitted as a JSON string as you're currently doing, but as regular form data. You can probably use -F 'grant_type=client_credentials' for that and drop the --data argument.

Azure and signing keys issues. Works with cure but not completely in python

Very puzzled here - in python using requests I can use GET/POST to do a few different things: POST to request a token, and GET to get public signing key x/y coordinates. And in curl I can sign. But in python it errors.
This works in CURL:
curl -vs -d '{"alg":"ES256", "value":"***"}' -H "Authorization: Bearer REDACTED" -H "Content-Type: application/json" -X POST https://REDACTED.vault.azure.net/keys/REDACTED/REDACTED/sign?api-version=7.0
but in python this fails:
post_payload = {'alg':'ES256', 'value':'***'}
post_headers = {'Authorization': 'Bearer REDACTED', 'Content-Type': 'application/json',}
response = post('https://REDACTED.vault.azure.net/keys/REDACTED/REDACTED/sign?api-version=7.0', data=post_payload, headers=post_headers)
print(response.text)
{"error":{"code":"BadParameter","message":"Property has invalid value\r\n"}}

Sending a csv file via curl POST to Django REST Framework endpoint

I have a csv file that I want to send via curl to a Django Rest Framework API View I have developed. The csv file itself contains only foo,bar and this is the curl command I'm using:
curl URL -H 'Accept:
application/json' -H 'Referer: http://localhost:5011/ost:5011' -H
'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94
Safari/537.36' -H 'Authorization: JWT TOKEN -H 'Content-Type:
multipart/form-data' -F upload=#testcsv.csv
When it hits my API View in Django, and I run
request.data.get('file').read()
the output is some metadata around the file and not the file contents itself:
(Pdb) b'--------------------------001ec735bfc1a929\r\nContent-
Disposition: form-data; name="upload";
filename="testcsv.csv"\r\nContent-Type: application/octet-
stream\r\n\r\n\r\n--------------------------001ec735bfc1a929--\r\n'
How can I access the actual file itself through this method? My APIview is using
class FileUploadView(APIView):
parser_classes = (MultiPartParser,)
Thanks!
f = request.FILES["filefield_name"]

Incorrect input parameters when using the Python Requests library

I have a Python script using the Requests library that is of this form:
uhash = '1234567abcdefg'
cookies = {
'uhash':uhash
}
payload = {
'action':'trade.bump',
'hash':uhash,
'tradeid':'12345678'
}
r = requests.post(
'http://www.target_url.com/api/core',
cookies=cookies,
params=payload
)
Above is my Python attempt at creating the following cURL request (written with bash):
HASH="1234567abcdefg"
TRADEID="12345678"
curl 'http://www.target_url.com/api/core' -H "Cookie: uhash=$HASH" --data "action=trade.bump&hash=$HASH&tradeid=$TRADEID"
In summary, both scripts contain:
The cookie - uhash
Three data parameters called action, hash, and tradeid
My issue currently is, the bash script works - the server response for when I use the bash script is this:
{"meta":{"code":200},"data":{"bumped":true,"count":15}}
However, if I use the Python script, with the SAME cookie and parameter values as the bash script, I get:
{"meta":{"code":301},"data":{"message":"You can't bump a trade that doesn't exist ;_;"}}
The above error tells me the trade doesn't exist, despite that tradeid existing and the exact same one as my bash script's parameters.
I tried to debug using Firefox' convenient copy-as-curl tool to copy that curl command, which was how I made the bash script. However, once I tried to translate it to the Python script, it will tell me the aforementioned error. Maybe I am using the Requests library incorrectly, and I am missing something.
Attached is the full cURL request taken from Firefox (don't worry, the parameters were sanitized, meaning, they're not the real values):
curl 'http://www.tf2outpost.com/api/core' -H 'Host: www.tf2outpost.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: http://www.tf2outpost.com/trades' -H 'Cookie: __qca=P0-6517545-1420724809746; __utma=5135382.11011755.14224810.14331180.14180489.7; __utmz=51353782.1420724810.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); uhash=abcdefg12345678; mb_uid2=3211475230616776; CTag61=14338638870; __utmb=513532.9.10.14180489; __utmc=513782; __utmt=1; __utmt_b=1; __utmt_c=1; OX_plg=sl|qt|pm; HIRO_COOKIE=data=&newSession=true&id=2237524293&timestamp=1433506185; HIRO_CLIENT_ID=67751187' -H 'Connection: keep-alive' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' --data 'action=trade.bump&hash=abcdefg12345678&tradeid=12345678'
Not quite sure why that is happening.
Try using data or json key instead of params, use json.dumps(payload) if data is your preferred method.

Categories

Resources