[英]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.我有一个 Flask 应用程序,它返回 HTML 页面和对 API 请求的 JSON 响应。 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.如果客户端请求application/json
,我想返回一个jsonify
响应,否则我想返回一个render_template
响应。 How can I detect what was requested and change the response appropriately?如何检测请求的内容并适当地更改响应?
The current error handlers I have only return an HTML response.我当前的错误处理程序只返回一个 HTML 响应。
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.使用request.content_type
获取客户端随请求发送的内容类型。 Use request.accept_mimetypes
the get the mimetypes the client indicated it can accept in a response.使用request.accept_mimetypes
获取客户端表示它可以在响应中接受的 mimetypes。 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:我使用after_request
装饰器来执行此操作并检查内容类型:
@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)
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. wants_json_response()
辅助函数比较客户端在其首选格式列表中选择的 JSON 或 HTML 的偏好。 If JSON rates higher than HTML, then it is necessary to return a JSON response.如果 JSON 速率高于 HTML,则有必要返回 JSON 响应。 Otherwise, return the original HTML responses based on templates.否则,返回基于模板的原始 HTML 响应。
For the JSON responses would slightly supplement the function with one condition: if wants_json_response():
which is what you need.对于 JSON 响应,该函数会稍微补充一个条件: if wants_json_response():
这就是您所需要的。 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.该函数使用 Werkzeug(Flask 的核心依赖项)提供的方便的HTTP_STATUS_CODES
字典,该字典为每个 HTTP 状态代码提供了一个简短的描述性名称。 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.为了更容易和更快的理解,'error'用来表示错误,所以你只需要担心数字状态码和可选的长描述。 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. jsonify()
函数返回一个 Flask Response 对象,默认状态码为 200,因此在创建响应后,需要为错误设置正确的状态码。
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
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”. API 将返回的最常见错误将是代码 400,这是“错误请求”的错误。 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
.为了在这些情况下更容易地为下面的函数生成消息,我们只转发所需的描述message
。
def bad_request(message):
return api_error_response(400, message)
I hope this will help in approaching with errors :)我希望这将有助于解决错误:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.