Flask not streaming JSON response - python

I have below flask application that should stream JSON response
Directory structure:
server -
api.py
resources -
stream.py
api.py
from flask import Flask
from flask_restful import Api
from resources.stream import Stream
from flask_compress import Compress
compress = Compress()
app = Flask(__name__)
compress.init_app(app)
api = Api(app)
api.add_resource(Stream, '/stream')
if __name__ == '__main__':
app.run(debug=False,host='0.0.0.0')
stream.py in resources directory
from flask import Response, request, stream_with_context
from flask_restful import Resource
class Stream(Resource):
def get(self):
def generator():
yield '{"data": ['
#creating large number of entries for data array with yield
yield ']}'
resp = Response(stream_with_context(generator()), status=200, content_type='application/json')
return resp
I started the flask app with python3.9 api.py
I am able to get response when I hit url http://127.0.0.1:5000/stream but in network tab I can see some issues:
If the response was streamed it should not have content-length
The streamed response should not be in Waiting for server response state, somehow its waiting to finish whole response and then starts downloading.
And below is the output that I am trying to achieve. A streamed output which would start Content Downloading and not be stuck in Waiting for server response

I found the solution for the problem I faced. I was using flask_compress which was causing this issue. Removing it would stream the response as expected. Thank you for the help though.

Related

Flask teardown request equivalent in Fastapi

I am building a rest api with fastapi. I implemented the data layer separately from the fastapi application meaning I do not have direct access to the database session in my fastapi application.
I have access to the storage object which have method like close_session which allow me to close the current session.
Is there a equivalent of flask teardown_request in fastapi?
Flask Implementation
from models import storage
.....
.....
#app.teardown_request
def close_session(exception=None):
storage.close_session()
I have looked at fastapi on_event('shutdown') and on_event('startup'). These two only runs when the application is shutting down or starting up.
We can do this by using dependency.
credit to williamjemir: Click here to read the github discussion
from fastapi import FastAPI, Depends
from models import storage
async def close_session() -> None:
"""Close current after every request."""
print('Closing current session')
yield
storage.close()
print('db session closed.')
app = FastAPI(dependencies=[Depends(close_session)])
#app.get('/')
def home():
return "Hello World"
if __name__ == '__main__':
import uvicorn
uvicorn.run(app)
use fastapi middleware
A "middleware" is a function that works with every request before it is processed by any specific path operation. And also with every response before returning it.
It takes each request that comes to your application.
It can then do something to that request or run any needed code.
Then it passes the request to be processed by the rest of the application (by some path operation).
It then takes the response generated by the application (by some path operation).
It can do something to that response or run any needed code.
Then it returns the response.
Example:
import time
from fastapi import FastAPI, Request
app = FastAPI()
#app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# do things before the request
response = await call_next(request)
# do things after the response
return response
references:
https://fastapi.tiangolo.com/tutorial/middleware/

Issue with simple python API in flask. Trying to create a post method to add json data to a list

I am trying to build a simple flask api to post json data to a list (eventually with be redshift but this is just a simple test program).
I have attached the api code first followed by the code to send data.
I am getting internal server error issues when running the second script.
The code seems very simple though and I cannot figure out what is wrong.
from flask_restful import Api, Resource
from flask import request
app = Flask(__name__)
api = Api(app)
audit_log = []
class audit(Resource):
#def get (self):
#return {"data":"HelloWorld"}
def put (self):
new_item = request.get_json()
audit_log.append(new_item)
return new_item
api.add_resource(audit,"/")
app.run()
import requests
BASE = "HTTP://127.0.0.1:5000/"
response = requests.put(BASE, params = {'auditid' : 'xyz', 'jobname' : 'abc'})
print (response.json())
It seems that you haven't imported the Flask properly
instead of this
from flask import request
use this
from flask import Flask, request
This should work fine...

Returning 'still loading' response with Flask API

I have a scikit-learn classifier running as a Dockerised Flask app, launched with gunicorn. It receives input data in JSON format as a POST request, and responds with a JSON object of results.
When the app is first launched with gunicorn, a large model (serialised with joblib) is read from a database, and loaded into memory before the app is ready for requests. This can take 10-15 minutes.
A reproducible example isn't feasible, but the basic structure is illustrated below:
from flask import Flask, jsonify, request, Response
import joblib
import json
def classifier_app(model_name):
# Line below takes 10-15 mins to complete
classifier = _load_model(model_name)
app = Flask(__name__)
#app.route('/classify_invoice', methods=['POST'])
def apicall():
query = request.get_json()
results = _build_results(query['data'])
return Response(response=results,
status=200,
mimetype='application/json')
print('App loaded!')
return app
How do I configure Flask or gunicorn to return a 'still loading' response (or suitable error message) to any incoming http requests while _load_model is still running?
Basically, you want to return two responses for one request. So there are two different possibilities.
First one is to run time-consuming task in background and ping server with simple ajax requests every two seconds to check if task is completed or not. If task is completed, return result, if not, return "Please standby" string or something.
Second one is to use websockets and flask-socketio extension.
Basic server code would be something like this:
from threading import Thread
from flask import Flask
app = Flask(__name__)
socketio = SocketIO(app)
def do_work():
result = your_heavy_function()
socketio.emit("result", {"result": result}, namespace="/test/")
#app.route("/api/", methods=["POST"])
def start():
socketio.start_background_task(target=do_work)
# return intermediate response
return Response()
On the client side you should do something like this
var socket = io.connect('http://' + document.domain + ':' + location.port + '/test/');
socket.on('result', function(msg) {
// Process your request here
});
For further details, visit this blog post, flask-socketio documentation for server-side reference and socketio documentation for client-side reference.
PS Using web-sockets this you can make progress-bar too.

Python flask Dockerized Web application api not return response ERROR:BrokenFilesystemWarning

I am using python 2.7 and flask that returns a complete response to my local setup. Now the application is dockerized the and deployed in Google kubernetes container. This is a sample API of POST method which takes inputs as application/json, currently the internal function able to fetch the data in JSON format but its not return to the client end.
Python part:
from flask import Flask, render_template, request, jsonify
from flask_cors import CORS, cross_origin
import sys
from runmodel import run
reload(sys) # Reload is a hack
sys.setdefaultencoding('UTF8')
app = Flask(__name__, static_url_path='/static')
CORS(app)
#app.route("/modelrun", methods=['POST'])
def modelrun():
"""TO run the model and get data to populate"""
req_data = request.json
res = run(req_data) #another function return the data it will return json format
return jsonify(res)
My current problem is I am not getting the complete response, its return the ValueError: View function did not return a response// Werkzeug Debugger in the web browser.
Here are the logs and Traceback:
labels{
container.googleapis.com/stream: "stderr"
}
BrokenFilesystemWarning)
severity: "ERROR"
textPayload: " BrokenFilesystemWarning)

My Python Rest API hangs on CURL

I created a simple REST API in Python using Flask. The code for that service is:
from flask import Flask, request, Response, jsonify
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Ping(Resource):
def get(self):
resp = jsonify({"response": 'Pong!'})
resp.status_code = 200
return resp
api.add_resource(Ping, '/ping')
if __name__ == '__main__':
app.run()
I start the service with: $python minimal-rest.py
I curl the ping endpoint with: $ curl -i http://127.0.0.1:5000/ping and the results are exactly what I expect.
I then hit the same endpoint from a browser, and again the results are as expected.
If I issue another curl command, the console just hangs. However, if I then go refresh my browser, it responds, as well as the console that was running the hung curl.
Any ideas?
Try changing the Ping class:
class Ping(Resource):
def get(self):
resp = {"response": 'Pong!'}
return resp, 200

Categories