My Python Rest API hangs on CURL - python

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

Related

Sending the output of a docker container as a response to a post request in flask

I am trying to build an application which takes a post request and runs a docker container which executes a shell script.I want to send back the output of the shell script as a response to this post request.For example the output of the shell file is "hello world" and It should be sent back as response to the post request.Here is the code
from flask import Flask, request
app = Flask(__name__)
#app.get('/run')
def test():
return 'running'
#app.post('/run')
def handle_request():
lang='python'
language = request.data
code=language.decode('utf-8')
if lang=='python':
file = open('input.py', 'w')
file.write(code)
else:
file = open('input.cpp', 'w')
file.write(code)
output=dockersandbox()
return output
if __name__ == '__main__':
app.run(debug=True)
import docker
import os
def dockersandbox():
image = 'myimage'
client = docker.from_env()
container = client.containers.run(
image=image,
volumes={os.getcwd(): {'bind': '/container/files', 'mode': 'rw'}},
remove=True,
stdout=True
)
output = container.decode('utf-8')
return output
Here the expected response for the post request is "helloworld" as the output of the shell file execution is "helloworld" but when I send a post request from postman I get this "Error: connect ECONNREFUSED 127.0.0.1:5000".I have separately ran that dockersandbox function and it works as intended and gives the correct output.I have also tested by sending only a string like "Test" as ouput of the dockersandbox function without implementing any docker container logic and code,in that case it gives the correct response for that post request,this issue happens if I implement this docker client logic in the dockersandbox function.I am using python's docker library to implement the docker logic and run the container.

Flask not streaming JSON response

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.

Deploying test flask API in pythonanywhere

I'm trying to deploy example flask API app given in flask document in pythonanywhere.
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
todos = {}
class TodoSimple(Resource):
def get(self, todo_id):
return {todo_id: todos[todo_id]}
def put(self, todo_id):
todos[todo_id] = request.form['data']
return {todo_id: todos[todo_id]}
api.add_resource(TodoSimple, '/<string:todo_id>')
if __name__ == '__main__':
app.run()
When I was testing this app locally in pycharm, I executed app successfully by sending data using
curl http://localhost:5000/todo1 -d "data=Remember the milk" -X PUT
command in pycharm terminal.
The result I got is
{
"todo1": "Remember the milk"
}
But when I tested the deployment using Postman the result I got is
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again
Parameters used in Query params in Postman are:
key:data
value:"Remember the milk"
The result got when executed the app in locally is the correct result.
What am I doing wrong?
PS:
When using the pythonanywhere I used
http://www.mydomain.pythonanywhere.com
You need to replace http://localhost:5000/ with the url from pythonanywhere, e.g.
http://yourusername.pythonanywhere.com
That is assuming you didn't pay and configure your own domain
Data has to be send in 'Body' tab, not in 'Param' tab.

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)

Categories