API in Flask--returns JSON but HTML exceptions break my JSON client
Solution 1
You should define HTTP error handlers in flask.
A simple JSON returing 404 handler might look something like this:
@app.errorhandler(404)
def page_not_found(e):
return flask.jsonify(error=404, text=str(e)), 404
With this you will be able to check for data.error
on the client and if it exists you can get the error text with data.text (the error passed as e
is werkzeug.exceptions.NotFound
whose string representation is "404: Not Found").
Solution 2
Making the traceback available to the JSON client has the potential to disclose sensitive information.
My advice is:
- turn debug off
- install a log aggregation tool like sentry
- make the error 500 page for this application return a generic error in json format
The 500 page could look like:
{ "error": "500 - internal server error" }
Solution 3
The code below should do the trick. So the idea is to catch any exception that might have been raised, get the exception details formatted as a string using the traceback module and then return that as valid json. I would recommend putting a bunch of except statements with the main types of errors you expect to happen and a more readable error message. Then you can have one last except as a catch all in case something strange and unexpected happens.
import traceback
@app.route('/route1')
def api_route1():
if user_id in request.args:
try:
k1 = request.args['user_id']
return flask.jsonify(recs=some_function(k1))
except:
return flask.jsonify(exception=traceback.format_exc())
else:
return flask.jsonify(exception="no valid user_id supplied")
Deepak Mathpal
i build Systems & Tools for Analysis, Prediction, Visualization, & Simulation. i also design, code, and deploy complete distributed and (horizontally) scalable Machine Learning-based applications (e.g., anti-fraud filter, recommendation engine, monitoring/anomaly detectors), often in the service layer decoupled from the main app. Techniques: Machine Learning decision tree (CART/C4.5) & random forest deep learning (multi-layer perceptron) support vector machine (SVM/SVR) kNN/kdtree probabilistic graphical models (eg, Bayesian Net, Markov Random Field) - ***Dimension Reduction Techniques*** - spectral decomposition (PCA & kPCA, kLDA) - Kohonen Map (self-organizing map) - ***ETL pipelines*** - akka stream - Apache Spark - Kafka/Zookeeper - ***Social Network Analysis & Visualization*** - using graph theoretic techniques for - community detection - identify members essential for network health/growth - identify nascent sub-communities - particular fluency in *NetworkX*, *GraphViz* - ***Analysis & Modeling of Time Series*** - decomposition - forecasting - anomaly detection - ***Optimization*** - combinatorial optimization - csp - ***Numerical Methods*** - matrix decomposition - monte carlo techniques - Gaussian quadrature, - finite difference methods - ***Persistence*** - redis - postgres - ***Geo-Spatial Data Modeling, Persistence, & Computation*** - postgis (storage, query, computation) toolchain: scala apache spark apache kafka akka & akka-stream R python NumPy + SciPy + Matplotlib + pandas git (& gitHub) travis ci no recruiters
Updated on June 05, 2022Comments
-
Deepak Mathpal almost 2 years
exceptions returned in HTML break my JSON client. I want to jsonify this output.
More detail: i have a view function which an endpoint of this api app.
As you can see, this function returns the result in json.
@app.route('/route1') def api_route1(): if user_id in request.args: k1 = request.args['user_id'] return flask.jsonify(recs=some_function(k1)) else: return "no valid user_id supplied"
The problem, unhandled exception are in HTML, e.g.,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>TypeError: 'NoneType' object is not iterable // Werkzeug Debugger</title> <link rel="stylesheet" href="?__debugger__=yes&cmd=resource&f=style.css" type="text/css">
This breaks my json client. The HTML format is clearly a default, but i don't know how to opt out of it and specify jsonified exceptions (and ideally jsonify anything returned even headers).
I suspect what i need is somewhere in the excellent Flask documentation, but i can't find it.
-
sberry over 11 yearsThis is what the OP should do.
-
Anurag over 11 yearseven the else part can have jsonify, this will again return html when user_id is not in arguments.
-
Marwan Alsabbagh over 11 years@Codeanu good suggestion, I updated the answer with what you suggested.
-
Michael almost 2 yearsDoes this mean I need to create an error handler per non-success http status code (5xx and 4xx)? There must be a better way.