How to send data originally from backend flask to frontend - python

I have a flask backend and react front end. I am trying to send data to react every time something specific happens from a third party in backend. I have tried using socketio however data only gets sent to front end if I first sent something from react and used #socket.on for example:
#socketio.on('randomevent')
def handle():
emit("test")
print('x')
So this code works but when i try to do it without:
def handle():
socketio.emit("test")
It doesn't get received in frontend. The flask socketio documentation says that this should work however it doesn't work for me. Any help would be appreciated thanks

I think the best solution for this type of problem where you want to receive information from the backend on a backend event would be
make the backend write in a file (json if you want to match it only for some sessions)
let your frontend make periodic async request (e.g. via ajax) and let the backend check per request if there is something in the file for the session
delete the information from the file where the event was listed
if there is something for the session you make what you want
process / part that writes the event
# everytime this program is executed the session '1' will have an event
with open('events.json', 'w') as f:
f.write('{"1": ["my_event_1", "my_event_2"]}')
backend check
# you need to set somewhere a unique id in the session ...
#app.route('/backend_request', methods=['POST'])
def backend_request():
with open('events.json', 'r') as f:
events = json.load(f)
if session['id'] in events:
return {'events': events[session['id']]}
else:
return {'events': []}
frontend function
$.ajax({
type: "POST",
url: "/backend_request",
data: {},
success: function(data) {
if (data != {'events': []}) {
alert('there are some events ...');
}
}
});

Related

Send file from express to flask

I have a NestJS api (uses express) that gets a file (pdf or image) and sends it to a Flask api to further analize.
When sent through Postman, the files are available in Flask through request.files but I've found no way to not send it to request.form when sending it from the node server:
formData.append(
"file",
file.buffer,
)
formData.append(
"filename",
file.originalname
)
const res = await fetch('http://flask_api', {
method: 'POST',
body: formData.getBuffer(),
headers: formData.getHeaders()
});
Then in the Flask api, the value is available through: request.form["file"] but it is a str and therefore can't be used as a file to be saved, etc.
Will somehow sending files to request.files in Flask from Node fix this? If so, can this be done all from memory i.e. not saving a temp file when I get it in the Node server?
Thank you!

Flask returns a response without even checking files

I am trying to understand more precisely how Http connections work with Flask, so I tried writing a very simple app and another simple connection with requests:
app = Flask('file-streamer')
#app.route("/uploadDumb", methods=["POST"])
def upload_dumb():
print("Hello")
return Response(status=200)
Then I am sending a big file (1.5 GB) to the endpoint with requests :
url = "http://localhost:5000/uploadDumb"
values = {"file": open(file, "rb")}
r = requests.post(url=url, data={}, files=values)
I expected Flask to wait for the whole file to be sent, even if the file is useless. However this is not what's happening, instead Flask returns a 200 response very quickly, which causes a BrokenPipeError with my second script.
Can someone explain to me what is happening here ?
I suppose that happens because Flask body-parsing is lazy (which is a good thing, actually). So when request comes, Flask only reads headers until body is accessed somehow (through request.data, request.files, request.json(), etc.). So to trigger a full body (and file) upload, try accessing request body to make Flask parse a file, like:
_ = request.data

Using return vales from flask in ios application

I was trying to use flask as a backend for my iOs application. Currently it seems to be working, and the backend is hosted on heroku. The flask backend looks a little like this:
#app.route('/get_token', methods=['POST'])
def create_token():
token = make_token()
return token
I can run this function and confirm that it runs using a snippet like this with swift (using alamofire):
let url = "https://my-backend.herokuapp.com/get_token"
Alamofire.request(url, method: .post, parameters: nil, encoding: JSONEncoding.default)
And that runs fine. But now I want to do something (specifically save the token from flask) with the return value from flask. But I am confused as to how to do this. Any suggestions?
I would return a JSON response from Flask, and then you can easily parse that JSON object however you choose in your iOS app. Flask has a built in method, jsonify, which makes it easy to create a JSON responses.
You response would look like return jsonify(token=token)
Parse JSON with Alamofire:
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
//to get status code
if let status = response.response?.statusCode {
switch(status){
case 201:
print("example success")
default:
print("error with response status: \(status)")
}
}
//to get JSON return value
if let result = response.result.value {
let JSON = result as! NSDictionary
print(JSON)
}
}
Source: https://stackoverflow.com/a/33022923/6685140

To implement a web socket feature with Flask-Restful (REST Api) on the server side

WORK DONE: I have implemented a REST API with Mongo DB (PyMongo driver) using Flask-Restful having one endpoint named “Users” consisting of GET, POST, PUT, DELETE
My PUT method:
def put(self, short_name ):
coll = db.users
user_info = request.get_json()
print user_info #for debugging
coll.update({'short_name': short_name'}, {"$set": user _info})
return Response(json_util.dumps(user _info), mimetype='application/json')
The above PUT method accepts a short_name, updates the User database and returns a response.
Work to be done: I need to implement a server side web socket feature where after coll.update({'short_name': short_name'}, {"$set": user _info}) is executed, a message to the client (i.e frontend which is built completely on angular) has to be sent stating “Data updated successfully”.
I saw a couple of snippets online but couldn’t find one with REST Api. For now I only require the server side implementation. I will try to figure out the client side implementation later.
Any help on how to accomplish this is appreciated. Can it be done with simple python or is socket.io needed. All solutions are welcome.
EDIT: My modified server code
def put(self, short_name ):
coll = db.users
user_info = request.get_json()
print user_info #for debugging
coll.update({'short_name': short_name'}, {"$set": user _info})
emit('my response', {'data': 'update successful'})
return Response(json_util.dumps(user _info), mimetype='application/json')
Added this on the client side:
namespace = '/';
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
socket.on('my response', function(msg) {
console.log(msg.data)
});
Now when I run my application, the console on the client side does not print my data sent from the server. Can anyone explain where am I going wrong.
This should be interesting... Flask or Django or similar frameworks are built to serve HTTP request based method.
Imagine
user click the button
Your framework take the request
do the needs
and finally return the response
This is the actual flow of web server. but in your case you may want to update the frontend when DB updated or Any event changes.. In this case you need Socket to communicate with frontend.
Features of web sockets
Communicate with your website whenever you need.
Just put the javascript in the html page like this
$(document).ready(function(){
var socket = io.connect('http://localhost:8000/test');
});
And now you are connected with Website so next in your python code..
#socketio.on('my event', namespace='/test')
def test_message(message):
emit('my response', {'data': message['data']})
just like this import emit and put your message and you are good to go. For more detail please look here http://flask-socketio.readthedocs.org/en/latest/

Responding to AJAX GET and POST requests with Google App Engine (Python)

I have confusion on how the servers(here app engine) respond to AJAX GET and POST requests. I want send a GET request to my server and get some JSON data back.
Here is the AJAX GET request
function syncRestoreLinks(e) {
var request = new XMLHttpRequest();
var url = "/sync"
request.open("GET", url);
request.setRequestHeader("Content-Type", "application/json");
request.onreadystatechange = function() {
if (request.readyState === 4) {
console.log(request.responseText);
}
}
request.send(null);
console.log("Getting links from db");
}
Handler on the server side
class SyncHandler(Handler):
def get(self):
response_data = {"loggedIn":False, "linkData":None, "success":False}
json_txt = json.dumps(response_data)
self.response.headers['Content-Type'] = 'application/json; charset=UTF-8'
self.response.out.write(json_txt)
def post(self):
response_data = {"loggedIn":False, "linkData":None, "success":False}
json_txt = json.dumps(response_data)
self.response.headers['Content-Type'] = 'application/json; charset=UTF-8'
self.response.out.write(json_txt)
This handler writes my response data out to the screen where as I want it to send it back and let JS handle it. (I am able to use server redirects here.)
If I make a POST request instead, the code works the way I intend it to. But here, I cannot make server redirects or render pages and only the script making request has that control.
Is this how GET/POST responses work or I am doing something stupid in my code?
Is there any way for GET response not to be written on the page and be sent to JS? In the code above the responseText is an empty string but, the json is printed on screen.
I'm doing AJAX Get requests successfully with app engine right now.
Your sync handler looks correct. Are you sure it is being called? Add a logging.info() statement there to make sure. If it is being called, then I suspect the error is on the front end. I use jQuery and not XMLHttpRequest so I can't you help you with that. My jQuery call looks like this:
$.get(url, callback_function, 'json');
You can add a POST handler to your SyncHandler like this:
def post(self):
...
self.response.out.write(json_txt)
The strange part is that your POST request should not be working without this code to handle the request. You only show a get() method in your code.

Categories