flask请求返回400问题

客户端有个请求大概如下requests.get(“http://127.0.0.1:5000/data/get_something”, headers={‘Content-Type’: ‘application/json’}),现象是服务器一直返回400

检查url,服务器代码之类,并没有异常,只有新加的在服务端检查了request.json是否存在,这个检查只是为了兼容老代码,怀疑是这个json解析问题,顺便理了下flask解析json的流程

flask的request.json部分代码如下

# ...site-packages/werkzeug/wrappers/json.py
class JSONMixin(object):
...
@property
def json(self):
    """The parsed JSON data if :attr:`mimetype` indicates JSON
    (:mimetype:`application/json`, see :meth:`is_json`).
    Calls :meth:`get_json` with default arguments.
    """
    return self.get_json()
  
@property
def is_json(self):
    """Check if the mimetype indicates JSON data, either
    :mimetype:`application/json` or :mimetype:`application/*+json`.
    """
    mt = self.mimetype
    return (
        mt == "application/json"
        or mt.startswith("application/")
        and mt.endswith("+json")
    )
def get_json(self, force=False, silent=False, cache=True):
    """Parse :attr:`data` as JSON.
    If the mimetype does not indicate JSON
     (:mimetype:`application/json`, see :meth:`is_json`), this
     returns ``None``.
     If parsing fails, :meth:`on_json_loading_failed` is called and
     its return value is used as the return value.
     :param force: Ignore the mimetype and always try to parse JSON.
     :param silent: Silence parsing errors and return ``None``
         instead.
     :param cache: Store the parsed JSON to return for subsequent
         calls.
     """
    if cache and self._cached_json[silent] is not Ellipsis:
         return self._cached_json[silent]

     if not (force or self.is_json):
         return None

     data = self._get_data_for_json(cache=cache)

     try:
         rv = self.json_module.loads(data)
     except ValueError as e:
         if silent:
             rv = None

             if cache:
                 normal_rv, _ = self._cached_json
                 self._cached_json = (normal_rv, rv)
         else:
             rv = self.on_json_loading_failed(e)

             if cache:
                 _, silent_rv = self._cached_json
                 self._cached_json = (rv, silent_rv)
     else:
         if cache:
             self._cached_json = (rv, rv)

     return rv
        
def on_json_loading_failed(self, e):
     """Called if :meth:`get_json` parsing fails and isn't silenced.
     If this method returns a value, it is used as the return value
     for :meth:`get_json`. The default implementation raises
     :exc:`~werkzeug.exceptions.BadRequest`.
     """
     raise BadRequest("Failed to decode JSON object: {0}".format(e))

...
# ...site-packages/werkzeug/exceptions.py
class BadRequest(HTTPException):
    """*400* `Bad Request`
    Raise if the browser sends something to the application the application
    or server cannot handle.
    """

    code = 400
    description = (
        "The browser (or proxy) sent a request that this server could "
        "not understand."
    )

通过上面代码就很清楚了,首先get_json默认是非静默的(silent=False),解析json失败就会报错返回400,同时又因为前端指定了mimetype是json,这肯定是个错误指定了,并没有传json,因为前端指定json,self.is_json 是True,导致get_json不会返回None,往后面走,去解析了,解析错误导致返回400

问题

前端请求,严格指定数据格式,不能随意指定,如这次指定是json格式,其实不是
flask后端慎用request.json,或者增加检查,再或者不用request.json,用request.get_json(silent=True)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值