Return HTTP status code 201 in flask - python

We're using Flask for one of our API's and I was just wondering if anyone knew how to return a HTTP response 201?
For errors such as 404 we can call:
from flask import abort
abort(404)
But for 201 I get
LookupError: no exception for 201
Do I need to create my own exception like this in the docs?

You can use Response to return any http status code.
> from flask import Response
> return Response("{'a':'b'}", status=201, mimetype='application/json')

You can read about it here.
return render_template('page.html'), 201

You can do
result = {'a': 'b'}
return result, 201
if you want to return a JSON data in the response along with the error code
You can read about responses here and here for make_response API details

As lacks suggested send status code in return statement
and if you are storing it in some variable like
notfound = 404
invalid = 403
ok = 200
and using
return xyz, notfound
than time make sure its type is int not str. as I faced this small issue
also here is list of status code followed globally
http://www.w3.org/Protocols/HTTP/HTRESP.html
Hope it helps.

In your flask code, you should ideally specify the MIME type as often as possible, as well:
return html_page_str, 200, {'ContentType':'text/html'}
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
...etc

Ripping off Luc's comment here, but to return a blank response, like a 201 the simplest option is to use the following return in your route.
return "", 201
So for example:
#app.route('/database', methods=["PUT"])
def database():
update_database(request)
return "", 201

you can also use flask_api for sending response
from flask_api import status
#app.route('/your-api/')
def empty_view(self):
content = {'your content here'}
return content, status.HTTP_201_CREATED
you can find reference here http://www.flaskapi.org/api-guide/status-codes/

In my case I had to combine the above in order to make it work
return Response(json.dumps({'Error': 'Error in payload'}),
status=422,
mimetype="application/json")

Dependent on how the API is created, normally with a 201 (created) you would return the resource which was created. For example if it was creating a user account you would do something like:
return {"data": {"username": "test","id":"fdsf345"}}, 201
Note the postfixed number is the status code returned.
Alternatively, you may want to send a message to the client such as:
return {"msg": "Created Successfully"}, 201

for error 404 you can
def post():
#either pass or get error
post = Model.query.get_or_404()
return jsonify(post.to_json())
for 201 success
def new_post():
post = Model.from_json(request.json)
return jsonify(post.to_json()), 201, \
{'Location': url_for('api.get_post', id=post.id, _external=True)}

You just need to add your status code after your returning data like this:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world(): # put application's code here
return 'Hello World!',201
if __name__ == '__main__':
app.run()
It's a basic flask project. After starting it and you will find that when we request http://127.0.0.1:5000/ you will get a status 201 from web broswer console.

So, if you are using flask_restful Package for API's
returning 201 would becomes like
def bla(*args, **kwargs):
...
return data, 201
where data should be any hashable/ JsonSerialiable value, like dict, string.

Related

Make flask return status-code that is not just a number for Vertex AI

In the Vertex AI docs it is stated "...request within 10 seconds with status code 200 OK. The contents of the response body do not matter;".
I have never used Flask before (I have used Django) but a lot of exampels on how to make a custom container is with flask. I struggle to figure out how I can return 200 OK as status code (I find that phrasing odd, since I have never seen status-codes being anything else than a number)
I have tried this
from flask import Flask,Response,make_response
.
.
#app.route('/health',methods=["GET","POST"])
def health():
return Response("OK",status=200)
#app.route('/health',methods=["GET","POST"])
def health():
return Response(status="200 OK")
#app.route('/health',methods=["GET","POST"])
def health():
return make_response("200 OK")
but neither seem to work.
Flask docs on response object mention that you have either status or status_code available.
property status: str
The HTTP status code as a string.
property status_code: int
The HTTP status code as a number.
This would imply that you could just use status_code in your example.
Alternatively you could use a return without the response object, like so:
result = {'a': 'b'}
return result, 200
As taken from this SO question semi related to yours.

Flask POST Request Response With Processed Request [duplicate]

This question already has answers here:
Flask view return error "View function did not return a response"
(3 answers)
Closed 1 year ago.
I am trying to send a webhook with a json to my flask app- it then takes the key values and inputs it to my search engine and should reply back with the results and 200 (code that it was successful) my code looks like this:
from flask import Flask, request, abort
from Webhooks.TGSearchEngine import TGSearch
app = Flask(__name__)
#app.route('/', methods=['POST'])
def webhook():
sys.stdout.flush()
if request.method == 'POST':
reply = request.json['reply']
query = request.json['query']
channel = request.json['channel']
messageid = request.json['id']
return TGSearch.main(reply, query, channel, messageid), 200
else:
abort(400)
But I get TypeError( TypeError: The view function did not return a valid response. The function either returned None or ended without a return statement.
My TGSearch.main() module takes the vars and returns a dictionary with the results. I don't understand why it would throw this error. Any ideas?
If you are sure that TGSearch.main(reply, query, channel, messageid), 200 doesn't return None value, you had to convert the result of the response to a valid response object.
Try one of these options:
You can pass the result in a variable to a template rendering:
response = TGSearch.main(reply, query, channel, messageid), 200
return render_template("example.html", response)
You can convert the response into a JSON:
from flask.json import jsonify
result = TGSearch.main(reply, query, channel, messageid), 200
response = jsonify(result)
Or in the case you are getting a tuple, you can access separate values and make them a string.
result = TGSearch.main(reply, query, channel, messageid), 200 // "Message", 200
return str(result[0]) + str(result[1])
Flask must always return something. In your else statement you should add a return.
Note: you specified methods=['POST'] in your route, so the only method allowed will be POST, I don't think it's necessary to check if request.method == 'POST'

Change response based on content type of request in Flask

I have a Flask application that returns both HTML pages and JSON responses to API requests. I want to change what an error handler returns based on the content type of the request. If the client requests application/json, I want to return a jsonify response, otherwise I want to return a render_template response. How can I detect what was requested and change the response appropriately?
The current error handlers I have only return an HTML response.
def register_errorhandlers(app):
"""Register error handlers."""
def render_error(error):
"""Render error template."""
# If a HTTPException, pull the `code` attribute; default to 500
error_code = getattr(error, 'code', 500)
return render_template('{0}.html'.format(error_code)), error_code
for errcode in [401, 404, 500]:
app.errorhandler(errcode)(render_error)
Use request.content_type to get the content type the client sent with the request. Use request.accept_mimetypes the get the mimetypes the client indicated it can accept in a response. Use these to determine what to return.
from flask import request, jsonify, render_template
if request.accept_mimetypes.accept_json:
return jsonify(...)
else:
return render_template(...)
I used the after_request decorator to do this and checked the content type:
#app.after_request
def after_request_helper(resp):
if resp.content_type == "text/html":
# If a HTTPException, pull the `code` attribute; default to 500
error_code = getattr(error, 'code', 500)
return render_template('{0}.html'.format(error_code)), error_code
else:
return app.errorhandler(errcode)(render_error)
A more detailed answer:
def wants_json_response():
return request.accept_mimetypes['application/json'] >= \
request.accept_mimetypes['text/html']
The wants_json_response() helper function compares the preference for JSON or HTML selected by the client in their list of preferred formats. If JSON rates higher than HTML, then it is necessary to return a JSON response.
Otherwise, return the original HTML responses based on templates.
For the JSON responses would slightly supplement the function with one condition:
if wants_json_response(): which is what you need. So the answer is in that.
If the condition is true we could write a function that would generate a response:
def api_error_response(status_code, message=None):
payload = {'error': HTTP_STATUS_CODES.get(status_code, 'Unknown error')}
if message:
payload['message'] = message
response = jsonify(payload)
response.status_code = status_code
return response
This function uses the handy HTTP_STATUS_CODES dictionary from Werkzeug (a core dependency of Flask) that provides a short descriptive name for each HTTP status code.
For easier and faster understanding, 'error' is used to represent errors, so you only need to worry about the numeric status code and the optional long description.
The jsonify() function returns a Flask Response object with a default status code of 200, so after the response is created, it is necessary to set the status code to the correct one for the error.
So if we put it all together now it would look like this:
# app/__init__.py
import requests
def register_errorhandlers(app):
from .errors import render_error
for e in [
requests.codes.INTERNAL_SERVER_ERROR,
requests.codes.NOT_FOUND,
requests.codes.UNAUTHORIZED,
]:
app.errorhandler(e)(render_error)
and
# app/errors.py
import requests
from flask import render_template, request, jsonify
from werkzeug.http import HTTP_STATUS_CODES
from .extensions import db
def api_error_response(status_code, message=None):
payload = {'error': HTTP_STATUS_CODES.get(status_code, 'Unknown error')}
if message:
payload['message'] = message
response = jsonify(payload)
response.status_code = status_code
return response
def wants_json_response():
return request.accept_mimetypes['application/json'] >= \
request.accept_mimetypes['text/html']
def render_error(e):
if requests.codes.INTERNAL_SERVER_ERROR == e.code:
db.session.rollback()
if wants_json_response():
return api_error_response(e.code)
else:
return render_template(f'{e.code}.html'), e.code
Additionally
Then they could use the response generation for other cases as well.
The most common error that the API is going to return is going to be
the code 400, which is the error for “bad request”. This is the error
that is used when the client sends a request that has invalid data in it.
In order to generate messages to the function below even easier in these cases, we forward only the required description - message.
def bad_request(message):
return api_error_response(400, message)
I hope this will help in approaching with errors :)

Is HTTP Post blocked by Cloud9?

I've been playing around with Python/Flask on Cloud9 ide. Pretty fun so far. But when I try to add a http post to my test project, Flask returns either a 403 or a 500. From what I can tell, when I attach data or send the POST method, the 'request' object is None. It doesn't make sense though. This is pretty straight forward and should work as far as I can tell. Here's the python:
from flask import Flask, jsonify, abort, request
#app.route('/test', methods = ['POST'])
def post():
print ('started')
print request
if request.method == 'POST':
something = request.get_json()
print something
Flask is running correctly. I can hit a GET url, returning data just fine. I get an error when I land on 'print request' because request is None.
Thanks,
You have two problems here:
You're getting a 500 error
"something" is always None
The first problem is because you're not returning anything from your route function.
127.0.0.1 - - [15/Dec/2014 15:08:59] "POST /test HTTP/1.1" 500 -
Traceback (most recent call last):
...snip...
ValueError: View function did not return a response
You can remedy this by adding a return statement at the end of the function. Don't forget it needs to be a string.
#app.route('/hi', methods = ['POST'])
def post():
return "Hello, World!"
The second problem isn't what it seems. I suspect that the object isn't None, but the function that returns the string representation returns None, so that's what gets printed. Try print type(request) to see this in action.
What I think you want access to is the form field. Here is a complete example:
from flask import Flask, request
app = Flask(__name__)
#app.route('/test', methods = ['POST'])
def post():
print type(request)
if request.method == 'POST':
print request.form
return str(request.form)
app.run(debug=True)

Proper way to modify a response in Flask with eg process_response

Given a simple Flask application, I'm just curious about whether there is a proper way to modify a Response in the hooks such as process_response?
e.g. Given:
from flask import Flask, Response
class MyFlask(Flask):
def process_response(self, response):
# edit response data, eg. add "... MORE!", but
# keep eg mimetype, status_code
response.data += "... This is added" # but should I modify `data`?
return response
# or should I:
# return Response(response.data + "... this is also added",
# mimetype=response.mimetype, etc)
app = MyFlask(__name__)
#app.route('/')
def root():
return "abddef"
if __name__ == '__main__':
app.run()
Is it proper to just create a new response each time, or is it canonical to just edit in-place the response parameter and return that modified response?
This may be purely stylistic, but I'm curious – and I haven't noticed anything in my reading that would indicate the preferred way to do this (even though it's probably quite common).
Thanks for reading.
From the Flask.process_response docs:
Can be overridden in order to modify the response object before it's sent to the WSGI server.
The response object is created on flask dispacher mechanism (Flask.full_dispatch_request). So if you want to create response objects under your own way, override Flask.make_reponse. Use Flask.process_response only when the desired modifications can be made using the created response object parameter.
Actually, you can use Flask.process_response to intercept and modify the response this way:
from flask import Flask
import json
import ast
appVersion = 'v1.0.0'
class LocalFlask(Flask):
def process_response(self, response):
#Every response will be processed here first
response.headers['App-Version'] = appVersion
success = True if response.status_code in [ 200, 201, 204 ] else False
message = 'Ok' if success else 'Error'
dict_str = response.data.decode("UTF-8")
dataDict = ast.literal_eval(dict_str)
standard_response_data = {
'success': success,
'message': message,
'result': dataDict
}
response.data = json.dumps(standard_response_data)
super(LocalFlask, self).process_response(response)
return response

Categories