如何强制请求Content-Type必须为application/vnd.api+json
强制JSON:API接口使用
application/vnd.api+json作为Content-Type的实现方案 你可以通过以下三种方式组合实现强制校验,从入口到框架层彻底解决application/json请求绕过校验的问题:
方案1:全局请求钩子拦截(最通用、优先级最高)
直接通过Flask原生的before_request钩子做全局入口校验,所有携带请求体的写接口请求会第一时间被校验Content-Type,不符合要求直接返回JSON:API规范的415错误,不会进入后续业务逻辑和参数解析流程:
from flask import request, jsonify @app.before_request def validate_jsonapi_content_type(): # 仅校验携带请求体的HTTP方法,GET/DELETE等无请求体方法不做限制 if request.method in ("POST", "PUT", "PATCH"): # 如需兼容带charset声明的场景(如application/vnd.api+json; charset=utf-8),可改用startswith判断 if not request.content_type or not request.content_type.startswith("application/vnd.api+json"): return jsonify({ "errors": [ { "status": "415", "title": "Unsupported Media Type", "detail": "请求必须使用application/vnd.api+json作为Content-Type" } ] }), 415
方案2:自定义flask-rest-jsonapi的参数解析器
flask-rest-jsonapi底层依赖webargs做参数解析,默认JSON解析器会同时接收application/json类型请求,你可以自定义解析器覆盖默认规则,从框架层阻断非JSON:API格式的请求进入Schema校验逻辑:
from flask_rest_jsonapi import Api from webargs.flaskparser import FlaskParser from webargs import ValidationError class StrictJSONAPIParser(FlaskParser): def _parse_json(self, req, schema, *, location, **kwargs): if not req.content_type or not req.content_type.startswith("application/vnd.api+json"): raise ValidationError("非法Content-Type,仅支持application/vnd.api+json") return super()._parse_json(req, schema, location=location, **kwargs) # 初始化Api实例时传入自定义解析器 api = Api(app, parser=StrictJSONAPIParser())
方案3:SAFRS框架规范配置
开启SAFRS的原生JSON:API严格模式,统一响应头和请求解析规则,和flask-rest-jsonapi的逻辑对齐:
from safrs import SAFRSAPI safrs_api = SAFRSAPI( app, json_api=True, # 强制启用JSON:API规范约束 prefix="/api/v1" )
注意:以上三个方案同时配置不会冲突,全局钩子负责入口兜底,自定义解析器负责参数解析层校验,SAFRS配置负责框架本身的规范对齐,可以完全避免
application/json请求绕过校验的问题。
内容的提问来源于stack exchange,提问作者begs
相关产品推荐
相关产品推荐

