Decoding Django POST request body - python

I'm building an mapping app using cordova and making a post request sending the following JSON (feature)
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-6.6865857,
53.2906136
]
},
"properties": {
"amenity": "pub",
"name": "The Parade Ring"
}
}
This is the JQuery code sending the request
function savePub(feature){
$.ajax({
type: "POST",
headers: {"csrfmiddlewaretoken": csrftoken},
url: HOST + URLS["savePub"],
data: {
pub_feature: JSON.stringify(feature)
},
contentType:"application/json; charset=utf-8"
}).done(function (data, status, xhr) {
console.log(data + " " + status);
pubDialogAlert("Pub saved",feature);
}).fail(function (xhr, status, error) {
showOkAlert(error);
console.log(status + " " + error);
console.log(xhr);
}).always(function () {
$.mobile.navigate("#map-page");
});
}
When the request is received in the Django backend I am not sure why when I print the request body it looks like this,
b'pub_feature=%22%7B%5C%22type%5C%22%3A%5C%22Feature%5C%22%2C%5C%22geometry%5C%22%3A%7B%5C%22type%5C%22%3A%5C%22Point%5C%22%2C%5C%22coordinates%5C%22%3A%5B-6.6865857%2C53.2906136%5D%7D%2C%5C%22properties%5C%22%3A%7B%5C%22amenity%5C%22%3A%5C%22pub%5C%22%2C%5C%22name%5C%22%3A%5C%22The+Parade+Ring%5C%22%7D%7D%22'
and when I try to decode it and then use json.loads() it throws this error
#api_view(['POST'])
def save_pub(request):
if request.method == "POST":
data = request.body.decode('utf-8')
received_json_data = json.loads(data)
return Response(str(received_json_data) + " written to db", status=status.HTTP_200_OK)
JSONDecodeError at /savepub/
Expecting value: line 1 column 1 (char 0)
I am assuming because once it decodes the binary string it can't be converted to valid JSON because of those characters %22 etc, but I don't know what the solution is.
Any help would be appreciated.
Thanks

You're mixing up two things here, form-encoded and JSON format. What you have is a form-encoded post with one key, pub_feature, whose value is a JSON object.
Instead you should post the JSON directly:
data: JSON.stringify(feature),
and then you should be able to load it as you do already - although note that really you should let DRF deal with that for you

Related

Flutter PUT request

I'm trying to convert my python code to flutter, but unable to do so. Trying to perform put request to update data on the website. Here is my original put request written in python.
import requests
url = "https://my.website.com/api/request/12"
headers = {"user_key":"kfrrt-000234-as12321-1h58dm66a"}
input_data = '''{
"request": {
"comment": "New comment",
"status": {
"request_status": "Open"
}
}
}'''
data = {'input_data': input_data}
response = requests.put(url,headers=headers,data=data,verify=False)
What I have so far in flutter :
postTaskInfo()async{
var jsonMP= {'request": {"comment": "New comment","status": {"request_status": "Open"}}'};
String jsonString= jsonEncode(jsonMP);
var url = 'https://my.website.com/api/request/12';
await http.put(url, body: jsonString, headers: {"user_key":"kfrrt-000234-as12321-1h58dm66a"} ).then((response){
setState(() {
print(response.body);
});
});
}
I get an error " Unhandled Exception: Converting object to an encodable object failed: Instance of '_CompactLinkedHashSet
Thank you !
The problem occurs due to jsonEncoding failed to encode non-json data to string, so correct the jsonMP variable.
yours:
var jsonMP= {'request": {"comment": "New comment","status": {"request_status": "Open"}}'};
Should be in the form of
var jsonMP = {
"request": {
"comment": "New comment",
"status": {"request_status": "Open"}
}
};

Format body mapping templates in API Gateway

Need your help! I have the below Lambda function that will take inputs from the API Gateway (using RestAPI Post method) and pass the same as Payload to a second Lambda function.
def lambda_handler(event, context):
customerName = event['Name']
customerEmail = event['EmailAddress']
input = {"Name": customerName, "EmailAddress": customerEmail}
response = lambda_client.invoke(
FunctionName='arn_of_the_lambda_to_be_invoked',
InvocationType='Event',
Payload=json.dumps(input))
Below will be my input to the API Gateway in JSON format -
{
"Name": "TestUser",
"EmailAddress": "test#abc.com"
}
Have tried Lambda proxy integration and Generic Body Mapping templates (from here). In both occasions, API Gateway returns the below error -
Response Body:
{
"errorMessage": "'Name'",
"errorType": "KeyError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n customerName = event['Name']\n"
]
}
With the same JSON input when I directly invoke the Lambda from the Lambda console, it works. I know that API Gateway, along with the JSON body, pushes many other things. However, I'm unable to figure out.
How do I get this working?
In the lambda proxy integration, the event will be in the following format.
{
"resource": "Resource path",
"path": "Path parameter",
"httpMethod": "Incoming request's method name"
"headers": {String containing incoming request headers}
"multiValueHeaders": {List of strings containing incoming request headers}
"queryStringParameters": {query string parameters }
"multiValueQueryStringParameters": {List of query string parameters}
"pathParameters": {path parameters}
"stageVariables": {Applicable stage variables}
"requestContext": {Request context, including authorizer-returned key-value pairs}
"body": "A JSON string of the request payload."
"isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}
the values you posted will be inside body as a json string. you need to parse the json.
import json
def lambda_handler(event, context):
fullBody = json.loads(event['body'])
print('fullBody: ', fullBody)
body = fullBody['body']
customerName = body['Name']
customerEmail = body['EmailAddress']
input = {"Name": customerName, "EmailAddress": customerEmail}
response = lambda_client.invoke(
FunctionName='arn_of_the_lambda_to_be_invoked',
InvocationType='Event',
Payload=json.dumps(input))
Input format of a Lambda function for proxy integration
Please remember that the lambda is expected to return the output in the following format for Lambda Proxy integration.
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}

Feed string using slack webhook

So basically, I have a set of data (domain name, severity score) that is in string format as post, and I am trying to get it to post in slack and It keeps throwing errors out and I don't know why. I appreciate the help.
I have tried changing the JSON portion a bit to see if it was that as well as changing what is being sent to the function in general, and nothing helps.
def slackHook(post):
webhook_url = #Ommited
slack_content = {"channel": "#brian", "user": "Awesom-O", "attachment": [{
"type": "section",
"text": {
"text": "Random message before domains",
"type": "mrkdwn",
},
"fields": [
{
"type": "mrkdwn",
"text": "Domain Severity Score"
},
{
"type": "plain_text",
"text": post
}
]
}]}
string_payload = json.dumps(slack_content)
r = requests.post(webhook_url, data=string_payload)
if r.status_code != 200:
raise ValueError('Request to slack.com returned an error %s, the response is:\n%s' % (r.status_code, r.text))
domains = db_query()
domains = str(domains)
slackHook(domains)
Happy Path: I would just like to take my string and post it to my slack channel using the fields that I've given for context.
The current error:
raise ValueError('Request to slack.com returned an error %s, the response is:\n%s' % (r.status_code, r.text))
ValueError: Request to slack.com returned an error 400, the response is:
no_text
Your main issue is that you where mixing the syntax for attachments and blocks which are different concepts. attachments are outdated and should no longer be used.
Just replace "attachment" with "blocks" like so:
slack_content = {"channel": "#brian", "user": "Awesom-O", "blocks": [{

Script to send json using POST/REST and requests in python doesn't work

I'm trying to send a json in POST method using REST, but i got error:
"Could not parse JSON data: Expecting value: line 1 column 1
(char 0)", "status": 500, "type": "ValueError",
"request": {"client_addr": "127.0.0.1",
"user_agent": "python-requests/2.3.0 CPython/3.4.2 Linux/3.16.0-41-generic",
"method": "POST", "path": "/api/adley/doc"}}
)
I'm trying to fix, use a json.dumps or json.loads, but nothing seems to work.
I need to send one key and two values. Here is the base:
{
metadata: {
idx_exp: false,
idx_exp_time: 0,
file_ext: false,
password: "",
description: "base de teste",
idx_exp_url: "",
model: {
item: "Text"
},
dt_base: "29/06/2015 14:47:10",
name: "adley",
id_base: 5,
file_ext_time: 0,
},
content: [
{
field: {
required: false,
multivalued: false,
alias: "Texto",
datatype: "Text",
name: "item",
indices: [
"Ordenado"
],
description: "placeholder"
}
}
]
}
My to send a post script:
import requests, json
url = "http://127.0.0.1/api/adley/doc"
json_data = {'value':{'item':'test'}}
response = requests.post(url, params=json_data)
print(response.text)
I can't see what's wrong with my script
try passing the data parameter instead of the params parameter to the post method. requests wants to url encode params where you want the json data. So something like this:
requests.post(url, data=json.dumps(json_data))

Accessing nested objects in django POST request using python 3

I am having some trouble accessing nested objects from an ajax post call. Here is my js:
$.ajax({
url: "/api/locate/",
type: "POST",
data: {start:
{
latitude: position.coords.latitude,
longitude: position.coords.longitude
}
},
dataType: 'json',
contentType: "application/x-www-form-urlencoded",
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
console.log(start);
},
success: function(data) {
console.log(data);
}
})
in my views, the only way I can retrieve the data is by doing the following:
latitude = request.POST['start[latitude]']
longitude = request.POST['start[longitude]']
which is kinda bad considering that optimally I'd like to have start as the dictionary containing the latitude and longitude keys. I do realize this formatting is due to the content type being set to "application/x-www-form-urlencoded", but when I change it to "application/json", the data must be decoded from request.body:
decoded = request.body.decode('utf8')
data = json.loads(decoded)
which in turn raises the following ValueError:
Expecting value: line 1 column 1 (char 0)
The decoded string is:
start%5B0%5D%5Blatitude%5D=31.736784000000004&start%5B0%5D%5Blongitude%5D=-106.473027
Has any of you had any luck on properly loading nested objects or am I stuck with the first method?
EDIT: Using Django 1.6.2 and python 3.4
When you send json data, use the JSON stringifier on your object.
data: JSON.stringify({start:
{
latitude: position.coords.latitude,
longitude: position.coords.longitude
}
})
If you pass a plain Object as data, it is converted to a query string, no matter what you declare as Content-Type.

Categories

Resources