Django request.body format - django

When I try to print request.body,
the below is printed
b'----------------------------914826831994362856243559\r\nContent-Disposition: form-data; name="release_date"\r\n\r\n2003-06-01\r\n----------------------------914826831994362856243559\r\nContent-Disposition: form-data; name="fanmodel"\r\n\r\nfan234code\r\n----------------------------914826831994362856243559\r\nContent-Disposition: form-data; name="country_code"\r\n\r\nAO\r\n----------------------------914826831994362856243559--\r\n'
My post request data is available here but along with a lot other data.
I want to understand what is that other data and how can I format it ?

If you are using django, you can access the POST data with request.POST.get('variable_name')
Read more:
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
https://docs.djangoproject.com/en/4.0/ref/request-response/

What you see is bytestring of the raw HTTP request body - see docs. To retrieve data try to use request.POST or request.GET attribute.

Related

POSTMAN: Post method using raw body returns 500

I tried to POST a query in json in postman's raw body like below:
and I got 500 internal error server and HTML results like below
Otherwise, I'm able to POST using form-data and from a script ran from the terminal using the same json format.
I use Django 1.5.12 to serve the API and python 2.7.
Can anyone help?
When you submit form data the content-type header will be
Content-Type: multipart/form-data
and in your Django view, you will do something like below to read the posted data:
name = request.POST.get('name')
However, when you post data using the way you did now with the postman, the header will be:
Content-Type: application/json
and to grab this json data, you can do something like:
import json
mydata = json.loads(request.body)
name = mydata.get('name')
Status 500, must be because you have not handled the case for json request in your view.
If you are using request.POST in your code to access the HTTP POST body values, then take note that as stated in https://www.django-rest-framework.org/tutorial/2-requests-and-responses/
request.POST # Only handles form data. Only works for 'POST' method.
If you would like your view to be able to read HTTP POST body values both from form-data (or x-www-form-urlencoded) and raw (JSON format) at the same time, then you cannot use request.POST alone. You could either:
Read from request.body
Read from request.data (only available if the logic is under rest_framework)
Example
urls.py
path('printpostedvalues/', printpostedvalues_view),
views.py
#csrf_exempt
def printpostedvalues_view(request):
print("request.body", request.body)
try:
print("json.loads(request.body)", json.loads(request.body))
for k, v in json.loads(request.body).items():
print("json.loads(request.body)", k, "-->", v)
except Exception:
print("request.body's string value is not in the format of JSON key:value pairs")
print("request.POST", request.POST)
for k, v in request.POST.items():
print("request.POST", k, "-->", v)
return HttpResponse("Printed values in console...")
Perform an HTTP POST http://127.0.0.1:8000/printpostedvalues/ using Postman.
Case 1: form-data
HTTP Body
KEY - VALUE
athlete - LeBron James
status - GOAT!
quote - Strive for greatness
Console Output
request.GET <QueryDict: {}>
request.body b'----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="athlete"\r\n\r\nLeBron James\r\n----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="status"\r\n\r\nGOAT!\r\n----------------------------269460357877673035654590\r\nContent-Disposition: form-data; name="quote"\r\n\r\nStrive for greatness\r\n----------------------------269460357877673035654590--\r\n'
request.body's string value is not in the format of JSON key:value pairs
request.POST <QueryDict: {'athlete': ['LeBron James'], 'status': ['GOAT!'], 'quote': ['Strive for greatness']}>
request.POST athlete --> LeBron James
request.POST status --> GOAT!
request.POST quote --> Strive for greatness
[11/Mar/2020 04:57:43] "POST /printpostedvalues/ HTTP/1.1" 200 28
Conclusion:
The request.body contains the HTTP POST information from the form-data but is clearly not in the JSON format and thus cannot be parsed through json.loads(). The request.POST also contains the values.
Case 2: x-www-form-urlencoded
HTTP Body
same as Case 1
Console Output
same as Case 1 except for line 2 - request.body b'athlete=LeBron%20James&status=GOAT%21&quote=Strive%20for%20greatness'
Conclusion:
same as Case 1
Case 3: raw (JSON)
HTTP Body
{
"athlete" : "LeBron James",
"status" : "GOAT!",
"quote" : "Strive for greatness"
}
Console Output
request.GET <QueryDict: {}>
request.body b'{\n "athlete" : "LeBron James",\n "status" : "GOAT!",\n "quote" : "Strive for greatness"\n}'
json.loads(request.body) {'athlete': 'LeBron James', 'status': 'GOAT!', 'quote': 'Strive for greatness'}
json.loads(request.body) athlete --> LeBron James
json.loads(request.body) status --> GOAT!
json.loads(request.body) quote --> Strive for greatness
request.POST <QueryDict: {}>
Conclusion:
The request.body contains the HTTP POST information from the raw JSON data and is in the JSON format and thus possible to be parsed through json.loads(). The request.POST does not contain any values.
SUMMARY
Long story short, do not rely on request.POST if you expect HTTP POST body values to come not just as form-data but also as raw JSON format. If you are using rest_framework for this, your best option is to use request.data because it will be able to catch all information coming from an HTTP POST regardless of format.

AWS Signature: Canonical Request, what is the payload for POST application/json?

What's the payload for POST application/json request? There's no example for POST application/json on their docs, and also I've look onto their test suites, but their POST examples are only form-url-encoded.
Can anyone give an example of POST application/json (with body of course) with its hashed payload?
I guess this question is not about AWS, I'm just dumb not to know that the payload was a term on API, and it was the JSON body.
Example:
Body (This is the payload):
{
"first_name": "Tenten"
}
Just convert to JSON string and hash it. That's it.

Using postman to test POST request, how do I access the form-data inside the request?

I've been googling for a few hours, and I need help. I dont think I'm using the correct words. Anyhow, I'm using Claudia.JS to set up a POST request to my AWS Lambda function. Here's the basics of the function:
api.post('/leads', function (request) {
console.log(request);
return request;
});
When I use postman to test the post request, I'm returned the request object. Awesome. Then I try to pass form-data through. I set the key to 'username' and the value to 'this is the username'. This is what request.body is:
"body": "---------------------------
-019178618034620042564575\r\nContent-Disposition: form-data;
name=\"username\"\r\n\r\nthis is the username\r\n----------------------
------019178618034620042564575--\r\n",`
I thought I could return request.body.username... to key the value of username...but I'm missing something.
How do I access the form data in the request?
update: okay. The website is taking the form data, making a post request...this function is receiving the post request? still-- in postman...if I were to put my own JSON in...why can I not access request.body like... request.body.username?
You should try console.log(request.data) to see your request object, ie. in my own case I can see the content of my request's body.
Have a look at https://www.getpostman.com/docs/postman/scripts/postman_sandbox to see all the relevant information about your request.
I solved this by looking at the header set in postman. It was set to form-data instead of application/JSON. All gravy now.

Missing form data in request

I have following code
class MyClass(restful.Resource):
def get(self):
headers = {'Content-Type': 'text/html'}
return make_response(render_template('myfile.html'),200,headers)
def post(self):
session['CONSUMER_KEY']=request.form.get('consumer_key')
session['CONSUMER_SECRET']=request.form.get('consumer_secret')
render_template('myfile.html')
api.add_resource(MyClass,"/mag/",endpoint="mag")
I have written following test:
def mytest(self):
content_type={"Content-Type": "application / x - www - form - urlencoded","Content-Disposition": "form-data"}
response = self.client.post(
api.url_for(MyClass), data = json.dumps({'consumer_key':'testconsumerkey',
'consumer_secret':'testconsumersecret'}),
headers=content_type
)
The issue is form data is blank and thats the values are not getting set in session. When i debug i see that request.data is populated but request.form is an empty dictionary. Can someone suggest how I can send form data in a post request from a test
EDIT: Environment details
Python 2.7, Flask web framework, self.client is . I am using flask.ext.testing
You seem to be confused as to what the expected format for the post body should be. Should it be JSON data (which is what you send in the test case), or should it be in the application/x-www-form-urlencoded format (which is what you claim to send in the test case, and what the endpoint will read)?
If you wish to receive JSON data, you'll need to change the endpoint to read the data from request.get_json(). You'll also need to use application/json as the Content-Type header in the test case.
If you wish to receive urlencoded post data, then just simplify the test case by removing the Content-Type header and the json.dumps. Just pass the data dict to the data argument.

How to use Backbone collection's create method correctly

I found that when I use the collection.create to create a new model, backbone will send a post request, but the post data is incorrect
for example
collection.create({name:'test'})
backbone will send POST data using "{name:'test'}" as key, and "" as value,
but I want the POST data by using name as key, 'test' as value,
can anybody no how to setting it,
I use django as the server
thanks in advance
Unless you change it backbone's collections use Backbone.sync to communicate with your backend.
In the docs they say:
With the default implementation, when Backbone.sync sends up a
request to save a model, its attributes will be passed, serialized as
JSON, and sent in the HTTP body with content-type application/json
So I guess you need to do something like this in your django view
json.load(request.POST)
or use a custom sync function that does not serialize the data to json
You'll need to parse the raw post data string and parse it into a python dict.
import json
data = json.loads(request.raw_post_data)
You can also set
Backbone.emulateJSON = true;
as per http://backbonejs.org/#Sync-emulateJSON