Python 基于Flask中的Accept标头路由请求

Python 基于Flask中的Accept标头路由请求,python,flask,http-headers,werkzeug,Python,Flask,Http Headers,Werkzeug,我想根据Accept HTTP头路由到不同的Flask视图,例如: @api.route('/test', accept='text/html') def test_html(): return "<html><body>Test</body></html>" @api.route('/test', accept='text/json') def test_json(): return jsonify(test="Test")

我想根据Accept HTTP头路由到不同的Flask视图,例如:

@api.route('/test', accept='text/html')
def test_html():
    return "<html><body>Test</body></html>"

@api.route('/test', accept='text/json')
def test_json():
    return jsonify(test="Test")
@api.route('/test',accept='text/html')
def test_html():
返回“测试”
@api.route('/test',accept='text/json')
def test_json():
返回jsonify(test=“test”)
我在中未找到相关选项,该选项由Flask使用。这是一个缺失的功能,还是可能以不同的方式实现相同的效果,例如在路由之前拦截和修改URL路径

我不想将视图合并到一个视图中,因为这会使代码变得非常复杂,因为有很多视图,它们位于不同的蓝图中

我知道有人问过,但没有人用烧瓶回答。可以在不同的web框架中实现这一点,例如在Pyramid中使用-示例代码可以在中找到。

我编写了一个实现这一点的程序(复制到这里供后人使用)。这只是一个可以进一步改进的粗略想法(例如,当没有与给定MIME类型匹配的处理程序时,返回
406 Not Acceptable
响应,而不是使用默认处理程序)。评论中有更多的解释

导入工具
从烧瓶导入烧瓶,请求,jsonify
app=烧瓶(名称)
def accept(func_或_mimetype=None):
“”“Decorator,它允许对单个MIME使用多个MIME类型处理程序。”
终点。
"""
#默认MIME类型。
mimetype='text/html'
类接受(对象):
定义初始化(self,func):
self.default\u mimetype=mimetype
self.accept_处理程序={mimetype:func}
functools.update_包装器(self,func)
定义调用(self,*args,**kwargs):
默认值=self.default\u mimetype
mimetypes=request.accept\u mimetypes
best=mimetypes.best\u匹配(self.accept\u handlers.keys(),默认)
#在Accept://*的情况下,选择默认处理程序。
如果最好的话!=默认和mimetypes[最佳]==mimetypes[默认]:
最佳=默认值
返回self.accept_处理程序[最佳](*args,**kwargs)
def接受(自我,mimetype):
“”“注册MIME类型处理程序。”“”
def装饰器(func):
self.accept_处理程序[mimetype]=func
返回函数
返回装饰器
#如果在没有参数列表的情况下调用decorator,则返回Accept实例。
如果可调用(func\u或mimetype):
返回接受(func_或mimetype)
#否则,设置新的MIME类型(如果提供),并让Accept充当
#装饰师。
如果func_或_mimetype不是None:
mimetype=函数或mimetype
退货接受
@应用程序路径(“/”)
@accept#或:@accept('text/html')
def index():
返回'foobar'
@accept('application/json')
def index_json():
返回jsonify(foobar=True)
@index.accept('text/plain')
def index_text():
返回'foobar\n',200,{'Content-Type':'text/plain'}

我知道这是一个老问题,但我最终在这里寻找类似的问题,所以我希望它能帮助其他人

具有通过不同路由处理不同接受类型的功能

from flask import Flask, jsonify
from flask_accept import accept
app = Flask(__name__)

@app.route('/')
@accept('text/html')
def hello_world():
    return 'Hello World!'

@hello_world.support('application/json')
def hello_world_json():
    return jsonify(result="Hello World!")

if __name__ == '__main__':
    app.run()
如果您只想根据请求是否为特定数据类型而拒绝请求,您也可以使用

当尝试在没有有效Accept标头的情况下访问终结点时:


您可以使用根据Accept标头返回不同的响应类型。例如

if request.accept_mimetypes['application/json']:
           return jsonify(<object>), '200 OK'
if request.accept_mimetypes['application/json']:
返回jsonify(),“200确定”

做了类似的事情;它支持根据
Accept
标题格式化查看结果。默认情况下,它只支持JSON,但可扩展。看,它的方法是不同的;它建立在完成最终路由的基础上;Flask已经提供了一种基于方法的分派,我相信同样的技术也可以以类似的方式用于基于接受的分派。@MartijnPieters谢谢,这很有趣。我相信Flask使用Werkzeug进行基于HTTP方法的路由。可插入视图可以帮助更好地组织代码,但这并不理想,因为最终我只注册了一条路由。是的,Werkzeug负责路由,而该机制不支持基于头的路由。它只支持方法,扩展它并不简单或容易。如果有人感兴趣,我写了一篇文章,允许在Flask中进行这种路由。感谢提供的信息,看起来新的库/可能性变得可用。请参阅github.com/di/Flask-accept/issues/11-无法首先让它工作,必须在macports上升级到python3.8,确保所有端口选择都正常。重新启动并升级liclipse python环境。
$ curl localhost:5000 -I
HTTP 415 (Unsupported Media Type)
if request.accept_mimetypes['application/json']:
           return jsonify(<object>), '200 OK'