How to make asynchronous HTTP POST requests - python

I have this program which runs in a loop with pythoncom.PumpMessages().
While this program runs, it takes input and stores it iternally.
When the input reaches a certain lenght, I'd like to send a HTTP POST request asynchronously to a database I have in the cloud so the program doesn't stop taking input while the request is sent. I do not need the request from the server, although it would be nice.
Is this possible? I'm having a hard time figuring this out. Right now it does it synchronously.
Thanks!

This can be done if you use python requests library to send post requests.
It has been answered here.
Asynchronous Requests with Python requests
The example is for "GET" request but you can easily do post request as well.

JavaScript works on any browser without added libraries.
This is great for loading parts of a page without stalling the UI, but use another method (e.g. server or NodeJS) if sending many requests (e.g. >100).
<p id="demo">Customer info will be listed here...</p>
<script>
function showCustomer(str) {
var xmlhttp;
if (str == "") {
document.getElementById("demo").innerHTML = "";
return;
}
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "yourFile.php?queryVariable="+str, true);
xmlhttp.send();
}
</script>
Source: http://www.w3schools.com/xml/tryit.asp?filename=try_dom_xmlhttprequest_database
GET: http://www.w3schools.com/xml/tryit.asp?filename=try_dom_xmlhttprequest_first
More here: http://www.w3schools.com/xml/dom_http.asp

Related

how to retrieve Python array in javascript (Flask to React communication)

I dumped Python array to a response with json.dumps and now I'm trying to retrieve the data as Javascript list.
#app.route('/get_scales')
#cross_origin()
def get_scales():
classes = inspect.getmembers(sys.modules['mingus.core.scales'], inspect.isclass)
scales = [class_[0] for class_ in classes if ('Error' not in class_[0] and class_[0] != '_Scale')]
return json.dumps(scales)
getScales() {
// create a new XMLHttpRequest
var xhr = new XMLHttpRequest();
// get a callback when the server responds
xhr.addEventListener("load", () => {
// update the state of the component with the result here
console.log(xhr.responseText);
});
// open the request with the verb and the url
xhr.open("GET", "http://127.0.0.1:5000/get_scales");
// send the request
xhr.send();
var formatted_response = JSON.stringify(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
return xhr.responseText;
}
When I made the function in getScales log to console type of xhr.responseText it shows String, but then when trying to parse it with JSON.parse it throws an error. Trying to stringify it first, like above doesn't help either.
I don't know what error it gave, but I think it was actually because xhr.response, wasn't there yet when you tried to use it. This is because XMLrequests function asynchronously, meaning that while the XMLrequest is still waiting for a response, the rest of your code continues executing. Try this instead:
xhr.open('GET', url, false);
the "false" parameter basically says you want your XMLrequest to function synchronously. So the rest of your code will wait for it to finish.
Do keep in mind that your performance may suffer because of this in a lot of situations.
So if you have multiple XMLrequests at a time or Sequentially, you could consider using HTML5 Workers for this.
Or If you don't want your requests to function synchronously (if you can avoid having your XMLrequest function synchronously, you definitely should) you could also try something like this (something like this is defentintely the best option for performance, so if you can use it):
getScales() {
// create a new XMLHttpRequest
var xhr = new XMLHttpRequest();
// get a callback when the server responds
xhr.addEventListener("load", () => {
// update the state of the component with the result here
console.log(xhr.responseText);
var formatted_response = JSON.stringify(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
return xhr.responseText;
});
// open the request with the verb and the url
xhr.open("GET", "http://127.0.0.1:5000/get_scales");
// send the request
xhr.send();
}

NodeJS streaming JSON from python

I'm creating an API with NodeJS. Every request returns a JSON. Some requests call to a python script and I want to send the JSON generated by python to the user. The code would look like:
child = child_process.spawn(cmd, args);
child.stdout.on('data', (chunk) => {
res.write(chunk);
});
child.on('error', function(err) {
res.status(500).json({...});
});
child.on('close', (code) => {
res.end();
});
The problem with this code is that I can't check if the python output is a JSON. Maybe python writes warnings, error...
What can I do to prevent the user will get something different to JSON?.
EDIT
Right now my code is:
var output = [];
command.stdout.on('data', (chunk) => {
output.push(chunk)
});
command.on('close', (code) => {
var stdout = output.join('');
json_cmd = tryParseJSON(stdout)
if (json_cmd)
res.send(json_cmd)...
});
But, I don't want to load all the stdout in a variable. But if I don't do that, I can check if the stdout is a JSON. Can I force python to print just json?. Using always json.dumps and a global try catch would be enough?
Thanks.
Instead of using spawn, you probably want to use exec, which will wait for the Python process to exit and provide you with its output (which you can subsequently try to parse as JSON):
const exec = require('child_process').exec;
...
exec(cmdline, (err, stdout, stderr) => {
if (err) return res.status(500).json({...});
// Try to parse stdout as JSON:
try {
res.json(JSON.parse(stdout));
} catch(e) {
res.status(500).json({...});
}
});
So you need a streaming JSON verifier in NodeJS. The problem is that if you start streaming the json data over the network, and find an error in the JSON halfways, you cannot rollback the traffic to the http headers and change 200 ok to 500 ise. If you want to check the output first you have to accumulate it in the server before sending.
Your current code would do the same. If an error event comes the client will receive a 200 ok with a half stdout and a json object at the end. (Or the response object throws an error if you try to set the status code after it has been sent, I don't know how is this case handled.)

Javascript long polling a json file - angularjs/jquery

Wishing you a Happy New year.!
I am having trouble when i am trying to load a json file from my web server. Actually i do not know java script. I just need this code to work. I am developing a website using Django. One of the django views, serves the client side java script and at the back end on a separate thread, it process some modules and generates a json output.
Now i am accessing this json using the below code.
<script type="text/javascript">
function addmsg(msg) {
document.getElementById("messages").innerHTML = msg;
}
function waitForMsg() {
$.ajax({
type: "GET",
url: "{% static ""%}tmp/{{url_hash}}/{{url_json}}",
cache: false,
timeout: 50000,
success: function (data) {
addmsg(data);
if (!data) {
setTimeout(
waitForMsg,
1500
);
};
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
addmsg("error");
setTimeout(waitForMsg, 15000);
}
});
};
$(document).ready(function () {
waitForMsg();
addmsg("loading");
});
</script>
When i run this, javascript gets served and then it queries for the json file every 1.5 sec.
What happens is, once the file is available on the server, this script loads the file and redirects the page to something like this ,
localhost:8000/+e+/
I dono from where this is getting redirected. I am not redirecting on any views or urls.py is clean.
Please help me with a code which will load this json from webserver when its available and then print the contents.
Thanks
===========update------------------
can anyone please suggest me angular js script for achieving the same ? thanks
==================== Update =====================================
Found the error, Actually the json dict has javascript, which has } { and quotes. Which breaks it.
I suggest looking beyond a lack of knowledge about JavaScript and stepping through all the parts of your problem. For example, use chrome and open the developer tools tab. Reload the page. Look at the url the JavaScript is testing to open. I suspect it is not the url you intend.
This code looks odd:
{% static ""%
Why is there the quote in the middle of the django directive? This isn't a JavaScript issue, just a quoting issue. It's also a warning sign because your JavaScript is using template directives - not an impossible or illegal thing, but a concern that some teams wouldn't allow.
In any case, track down the url that is actually bring invoked, see if it is the one you intend, and check the quoting issue in the httpcall.

Asynchronous Django using django-websocket-redis

I'm trying to use django-websocket-redis and I didn't understand how it works even reading the doc..
The part client (javascript/template) was easy to understand but I want to send data messages from one client to other and i'm blocking here..
Connecting each client :
var ws = new WebSocket('ws://localhost:8000/ws/foobar?subscribe-group');
ws.onopen = function(e) {
console.log("websocket connected");
};
ws.onclose = function(e) {
console.log("connection closed");
};
How manage my views.py to create a link between them ?
With NodeJS I was using this code to link the clients together :
io.sockets.on('connection', function (socket) {
var data={"action": "connexion", "session_id": socket.id,};
socket.emit('message',data);
socket.on('message', function(socket){
if (socket.action == "test")
{
io.sockets.socket(socket.code).emit('message',{"action": "move"});
//the socket.code is the session_id of the client one transmitted by a form
}
});
});
Thanks you.
The link between your Django view.py and the Websocket loop is the Redis message queue. Imagine to have two separate main loops on the server: One which handles HTTP-requests using the normal Django request handler. The other loop handles the Websockets, with their long living connections. Since you can't mix both loops within the normal Django request handler, you need message queuing, so that they can communicate to each other.
Therefore, in your Django view.py, send the data to the websocket using something like:
def __init__(self):
self.redis_publisher = RedisPublisher(facility='foo', broadcast=True)
def get(self, request):
data_for_websocket = json.dumps({'some': 'data'})
self.redis_publisher.publish_message(RedisMessage(data_for_websocket))
This will publish data_for_websocket on all Websockets subscribed (=listening) using the URL:
ws://example.com/ws/foo?subscribe-broadcast

Calling a python function using dojo/request

Firstly, I'm very new to the world of web development, so sorry if this question is overly simple. I'm trying to use python to handle AJAX requests. From reading the documentation it seems as though Dojo/request should be able to do this form me, however I've not found any examples to help get this working.
Assuming I've got a Python file (myFuncs.py) with some functions that return JSON data that I want to get from the server. For this call I'm interested in a particular function inside this file:
def sayhello():
return simplejson.dumps({'message':'Hello from python world'})
What is not clear to me is how to call this function using Dojo/request. The documentation suggests something like this:
require(["dojo/dom", "dojo/request", "dojo/json", "dojo/domReady!"],
function(dom, request, JSON){
// Results will be displayed in resultDiv
var resultDiv = dom.byId("resultDiv");
// Request the JSON data from the server
request.get("../myFuncs.py", {
// Parse data from JSON to a JavaScript object
handleAs: "json"
}).then(function(data){
// Display the data sent from the server
resultDiv.innerHTML = data.message
},
function(error){
// Display the error returned
resultDiv.innerHTML = error;
});
}
);
Is this even close to what I'm trying to achieve? I don't understand how to specify which function to call inside myFuncs.py?
What you could also do is to create a small jsonrpc server and use dojo to do a ajax call to that server and get the json data....
for python side you can follow this
jsonrpclib
for dojo you could try something like this..
<script>
require(['dojox/rpc/Service','dojox/rpc/JsonRPC'],
function(Service,JsonRpc)
{
function refreshContent(){
var methodParams = {
envelope: "JSON-RPC-2.0",
transport: "POST",
target: "/jsonrpc",
contentType: "application/json-rpc",
services:{}
};
methodParams.services['myfunction'] = { parameters: [] };
service = new Service(methodParams);
function getjson(){
dojo.xhrGet({
url: "/jsonrpc",
load : function(){
var data_list = [];
service.myfunction().then(
function(data){
dojo.forEach(data, function(dat){
data_list.push(dat);
});
console.log(data_list)
},
function(error) {
console.log(error);
}
);
}
});
}
getjson();
}
refreshContent();
});
});
</script>
I've used this approach with django where i am not creating a different server for the rpc calls but using django's url link to forward the call to my function.. But you can always create a small rpc server to do the same..

Categories