Sending a POST request from Python to Wix? - python

I'm currently trying to send a POST request from a python tkinter GUI to a wix free website. I already sent several GET requests and were successful. But regardless of anything I do, the POST request yields a 500 internal server error. Here are the code of the http-functions.js in the backend of my wix.
export function post_posFunc(request) {
let options = {
"headers":{
"Content-Type":"application/json"
}
};
return request.body.text()
.then((body) =>{
return wixData.insert("vidinfo", JSON.parse(body));
})
.then((results)=> {
options.body={
"inserted":results
};
return created(options)
})
.catch((error) =>{
options.body = {
"error":error
};
return serverError(options)
});
}
and on my tkinter app, I pass a video's name, size, and class alongside a userId and the code is as follows
def runPost(a,b,c,d,e,f):
url = 'https://###.wixsite.com/###/_functions/posFunc/'
myobj = {
"vidUserId":a,
"videoName":b,
"videoSize":c,
"videoClass":d
}
z = requests.post(url, data=myobj)
print(json.dumps(data, indent=2, sort_keys=True))
print("done with post")
I have already tried it with postman and It worked successfully. The fields that are in vidinfo are displayed above as you can see. I have censored the website's name as someone told me it's against the rules to release private information but If I am allowed to post it please do let me know. What is wrong with my code?
UPDATE
managed to catch and print the error. Updated the code above and adding the error below
{
"error": {
"errorGroup": "User",
"name": "JsonSyntaxError"
}
}
UPDATE#2
Using json.dumps did the trick!

It might be helpful to find out what the actual error message is. In your python script, you are only printing the status code. Knowing the error response which is caught with .catch((error) => { ... }) and is sent with options.body = { error: error }
might give you (and us) some more clues as to what is going on.
Also note that it doesn't always make sense to send a 'server error', namely when the issue is really with the request and not server side. Knowing the error message (and thus, potentially what is causing the error) will help you send the appropriate response and status code.
Without knowing any further error message information, I wonder if how you are handling the request is causing the issue. Are you sure that you can parse the request by using request.body.text() and/or JSON.parse from the python-sent request? It's possible that the python requests module does not serialize data in the same way that Postman does.
Hopefully what I've said can be helpful. I will keep following if you happen to make any updates to what you've posted above. Good luck!!
UPDATE:
After seeing your response error, it looks to me like you might be handling the request incorrectly. As I stated above, Postman may serialize the object differently from python requests.
Try using request.post(url, data=json.dumps(data)).
Again, are you sure that the data can be retrieved from the request.body.text() method? I am not sure what http framework is being used server-side, but if request.body.text() isn't actually able to return any data, it is likely passing undefined to your first promise handler .then((body) => { ... }). Since your error is a JsonSyntaxError, it is likely that JSON.parse cannot actually parse what it is trying to parse, whether that be undefined or an invalid JSON string.

Related

How to do pass a Request Body while doing a 307 Redirect with a( POST Method and body ) from AWS Lambda , in python

I need to redirect to an another end point from my AWS Lambda function.
I have implemented below code in AWS Lambda function and trying to Redirect to an End Point implement in external system as a POST end point. I am not sure how to pass the Request Body.
Python code is trying to redirect, but I am not sure how to pass a "new" Request Body as it is a POST Endpoint, I don't want the original body to get transmitted.
Please see the Java error at the destination where it got redirected.
def lambda_handler(event, context):
# Create Dictionary
value = {
"language": "python33",
"greetings" : "Greetings... Hope you have been redirected"
}
# Dictionary to JSON Object using dumps() method
# Return JSON Object
return {
"headers": {"Location": "http://localhost:8080/urlcallback",'Content-Type':'application/json' ,},
'statusCode': 307,
'body': json.dumps(value)
}
The Redirected End Point is getting invoked, but with the below error in the JAVA Spring boot logs:
{
"timestamp": 1671820676750,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Required request body is missing: public java.util.Map<java.lang.String, java.lang.String> my.sample.service.controller.PingController.urlcallback(java.lang.String)",
"path": "/urlcallback"
}
I will greatly appreciate any suggestions or pointers. I could not find any when I checked on StackOverFlow
Note:
I tried first with basic redirect of 301 and 302, that works for a GET call, but now I get an error while doing a Redirect with POST end point and a request body as I have some sensitive data to transmit
I am not sure how to pass a "new" Request Body as it is a POST Endpoint, I don't want the original body to get transmitted.
Based on HTTP 307 docs this is not possible: "307 guarantees that the method and the body will not be changed when the redirected request is made"
You can try HTTP 303 and change the request type to GET to remove the body from the request.

how to get json object from a webservice

i have the below posted json response.as shown below in json section, the parametersobject is emitted in this line (this is an angular application)
this._FromInsToSiteDataService.emitOnSubmitButtonClikedBroadcast(parameters)
and it is received in
this.subscriptionBroadcastEmitterOnSubmitButtonClicked = this._FromInsecticidesToSiteMapDataService.getBroascastEmitterOnSubmitButtonClicked().subscribe((response:Object)=>{
response['siteGeometry'] = this.selectedSite.geometry
console.log("response: ", response)
this.sSProvider.startWebServiceFor(response)
});
in the latter code i want to pass the response which is in json format to the webservice and receive it as show in the websrvicepostedbelow`
when i run the code, i expected to see the contents of the json object which is
{
"dist1": d1,
"dist2": d2,
"date1": date1,
"date2": date2,
"ingredient": activeIngredient
}
but i get NONE
please let me know how can i correctly get a json object from a webservice
json
private submit() {
let parameters = {
"dist1": d1,
"dist2": d2,
"date1": date1,
"date2": date2,
"ingredient": activeIngredient
}
this._FromInsToSiteDataService.emitOnSubmitButtonClikedBroadcast(parameters)
receiving the json object
this.subscriptionBroadcastEmitterOnSubmitButtonClicked = this._FromInsecticidesToSiteMapDataService.getBroascastEmitterOnSubmitButtonClicked().subscribe((response:Object)=>{
response['siteGeometry'] = this.selectedSite.geometry
console.log("response: ", response)
this.sSProvider.startWebServiceFor(response)
});
webservice:
#app.route("/insSpecifications/<parameters>", methods=['GET'] )
def insSpecifications(parameters):
# print(request.json())
print(request.get_json())//returns NONE
return "OK"
Intro
There are two parts to your question -
Making a request from JS
Creating a Flask API to handle the request
Both these have extensively answered on SO hence I will only summarize it here, please follow the links for more information
Answer
REST Method:
When sending JSON data from the front end to the backend, you need to make a POST request or PUT depending on the need. Please read up on REST API concepts to understand the methods and purposes.
https://www.w3schools.in/restful-web-services/rest-methods/
Making a request
Depending on which library you use in the front end, the request might look different, but essentially you need to send a request with JSON in the body and HEADERS set appropriately i.e. Content-Type: application/json
Using FETCH this can be achieved by (auto-generated from postman)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({
"username": "Sample1",
"email": "test2#test.com"
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("localhost:5000/sample", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
But most libraries would have wrappers around this, please look into making a POST request for your respective JS library
Creating Flask API
Finally, you need a Flask API to consume this request. Assuming it's a POST request. You need to create a route with method as POST and get the JSON data using get_json() : https://stackoverflow.com/a/20001283/5236575
So once the HEADERS are correctly set and a post request is made, your code should work fine by changing GET to POST
Note: The parameters field is captured correctly hence I'm leaving it as is, but that is not where your JSON body comes from
#app.route("/insSpecifications/<parameters>", methods=['POST'] )
def insSpecifications(parameters):
# print(request.json())
print(request.get_json())
return "OK"
Testing
You can test your API using Postman or any other API testing tool to see how the API behaves and validate if the issue you have is in the API or in the front-end code.

How to delete all items from a Sharepoint List using Python REST?

I am trying to delete all the items from a Sharepoint List using Python. However, there is no official documentation of Sharepoint REST that supports Python. I have gone through many StackOverflow articles and have built up the python code to delete a single item. However, I am unable to understand how to delete all items at once. Also, iteration over all would be quite complex, since GET request returns a JSON with a lot of unnecessary metadata as well, hence parsing is a challenge. Hence, I am unable to go about deleting all the items at once. Currently I am using requests.post(https://{site_url}/_api/web/lists/getbytitle('List Name')/items(id), auth, headers) and specifying the following headers: X-RequestDigest: digestValue, X-HTTP-Method: DELETE, and IF-MATCH: *. This is working perfectly well and I am able to delete an item by its id but unable to delete all items of the list.
Any help is appreciated, especially involving using python requests as I am using that to perform CRUD operations. Also, the same code gives Bad Request error if I use https://{site_url}/_api/web/lists/getbytitle('List Name')/items/getitembyid(id) instead of https://{site_url}/_api/web/lists/getbytitle('List Name')/items(id). Besides, I am also unable to delete by using requests.post(https://{site_url}/_api/web/lists/getbytitle('List Name')/items?filter=Title eq 'title1'. It gives Bad Request once again. In both cases, apart from the Bad Request error, when I try to log it, it gives the following exception: Microsoft.Sharepoint.Client.InvalidClientQueryException with the error content saying The type SP.ListItemEntityCollection does not support HTTP DELETE method. Any insights into this are also welcome.
It's not possible to delete all list items at once. SharePoint Rest API has not exposed such an endpoint. We suggest you delete item one by one, put the delete request in a loop like below:
function deleteItem(url) {
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + url,
type: "DELETE",
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"If-Match": "*"
},
success: function (data) {
},
error: function (error) {
alert(JSON.stringify(error));
}
});
}
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('MyList')/items",
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
success: function (data) {
var items = data.d.results;
for(var item in items){
var url = "/_api/Web/Lists/getByTitle('MyList')/getItemById(item.ID)"
deleteItem(url);
}
},
error: function (error) {
alert(JSON.stringify(error));
}
});
More references:
Delete all items from SharePoint

HTTP Triggering Cloud Function with Cloud Scheduler

I have a problem with a job in the Cloud Scheduler for my cloud function. I created the job with next parameters:
Target: HTTP
URL: my trigger url for cloud function
HTTP method: POST
Body:
{
"expertsender": {
"apiKey": "ExprtSender API key",
"apiAddress": "ExpertSender APIv2 address",
"date": "YYYY-MM-DD",
"entities": [
{
"entity": "Messages"
},
{
"entity": "Activities",
"types":[
"Subscriptions"
]
}
]
},
"bq": {
"project_id": "YOUR GCP PROJECT",
"dataset_id": "YOUR DATASET NAME",
"location": "US"
}
}
The real values has been changed in this body.
When I run this job I got an error. The reason is caused by processing body from POST request.
However, when I take this body and use it as Triggering event in Testing I don't get any errors. So I think, that problem in body representation for my job but I havn't any idea how fix it. I'll be very happy for any idea.
Disclaimer:
I have tried to solve the same issue using NodeJS and I'm able to get a solution
I understand that this is an old question. But I felt like its worth to answer this question as I have spent almost 2 hours figuring out the answer for this issue.
Scenario - 1: Trigger the Cloud Function via Cloud Scheduler
Function fails to read the message in request body.
Scenario - 2: Trigger the Cloud Function via Test tab in Cloud Function interface
Function call always executes fine with no errors.
What did I find?
When the GCF routine is executed via Cloud Scheduler, it sends the header content-type as application/octet-stream. This makes express js unable to parse the data in request body when Cloud scheduler POSTs the data.
But when the exact same request body is used to test the function via the Cloud Function interface, everything works fine because the Testing feature on the interface sends the header content-type as application/json and express js is able to read the request body and parses the data as a JSON object.
Solution
I had to manually parse the request body as JSON (explicitly using if condition based on the content-type header) to get hold of data in the request body.
/**
* Responds to any HTTP request.
*
* #param {!express:Request} req HTTP request context.
* #param {!express:Response} res HTTP response context.
*/
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
console.log('Headers from request: ' + JSON.stringify(req.headers));
let parsedBody;
if(req.header('content-type') === 'application/json') {
console.log('request header content-type is application/json and auto parsing the req body as json');
parsedBody = req.body;
} else {
console.log('request header content-type is NOT application/json and MANUALLY parsing the req body as json');
parsedBody = JSON.parse(req.body);
}
console.log('Message from parsed json body is:' + parsedBody.message);
res.status(200).send(message);
};
It is truly a feature issue which Google has to address and hopefully Google fixes it soon.
Cloud Scheduler - Content Type header issue
Another way to solve the problem is this:
request.get_json(force=True)
It forces the parser to treat the payload as json, ingoring the Mimetype.
Reference to the flask documentation is here
I think this is a bit more concise then the other solutions proposed.
Thank you #Dinesh for pointing towards the request headers as a solution! For all those who still wander and are lost, the code in python 3.7.4:
import json
raw_request_data = request.data
# Luckily it's at least UTF-8 encoded...
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
Totally agree, this is sub-par from a usability perspective. Having the testing utility pass a JSON and the cloud scheduler posting an "application/octet-stream" is incredibly irresponsibly designed.
You should, however, create a request handler, if you want to invoke the function in a different way:
def request_handler(request):
# This works if the request comes in from
# requests.post("cloud-function-etc", json={"key":"value"})
# or if the Cloud Function test was used
request_json = request.get_json()
if request_json:
return request_json
# That's the hard way, i.e. Google Cloud Scheduler sending its JSON payload as octet-stream
if not request_json and request.headers.get("Content-Type") == "application/octet-stream":
raw_request_data = request.data
string_request_data = raw_request_data.decode("utf-8")
request_json: dict = json.loads(string_request_data)
if request_json:
return request_json
# Error code is obviously up to you
else:
return "500"
One of the workarounds that you can use is to provide a header "Content-Type" set to "application/json". You can see a setup here.

AngularJS $http.post and Python CGI FieldStorage

I have a problem with $https.post parameters on AngularJS. I read that AngularJS is creating a JSON for the params.
So I applied the solution found here:
AngularJS - Any way for $http.post to send request parameters instead of JSON?
http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
But I still have problem with Python CGI.
[Edit]
Output of the console.log for objData:
Object {hostname: "test", id_venue: 20}
inspecting Request Payload:
action: "insert",
objData: { first: "test", second:"test2" }
[/Edit]
Website call
angular.module('myApp.services', [])
.service('MyService', ['$http', '$q', function ($http, $q) {
this.insert = function (objData){
console.log(objData);
var deferred = $q.defer();
$http.post('api/api.py', { action: 'insert', objData: objData }).success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function (response) {
deferred.reject("error");
});
return deferred.promise;
};
}])
Server side code is made with Python and CGI. It is unfortunately a constraint that I cannot use web frameworks.
api/api.py
import cgi
params = cgi.FieldStorage()
print 'Content-type: application/json'
print
print params
print params['objData'].value
Inspective the request headers and response, and I have obviously a KeyError:
FieldStorage(None, None, [MiniFieldStorage('action', 'insert'), MiniFieldStorage('objData[first]', 'test'), MiniFieldStorage('objData[second]', 'test2')])
KeyError: 'objData'
Any solution on how to correctly read params on Python CGI FieldStorage.
Or any way to send them correctly with AngularJS?
With $http.get I don't have any problem.
Maybe one solution could be to handle POST request directly in Python without using cgi.FieldStorage.
As far as I can see, on the js side, objData seems to contain {"first": "test", "second": "test2"}.
As a 1st recommendation, I would recommend to make your life easier by using objData keys as POST keys by doing sth like this on the js client side (I'm assuming objData keys don't start with a underscore so that on the server side, you can make a difference between action and obj keys) :
params = {_action:'insert'};
_.extend(params, objData); // using underscore or lodash
[...]
$http.post('api/api.py', params)
The potential problem is that your insert function is quite generic, objData could be anything (so sth else than a js dictionnary), my second recommendation would be to first serialize your objData as a json string (you can find js libs for this), then send {action: 'insert', 'jsondata': json_string}.
On the python side, you will have to deserialize the json_string which is quite easy with json module.
Thus, you can both use a classical POST (<-> not full json encoded form data) and some json stuff.
HTH

Categories