如何在 odoo 14 中使用 json 类型的路由设置响应状态代码
How to set response status code in route with type json in odoo 14
我在 odoo 14 中创建了一个 Json 类型的路由。
@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
所以当我收到使用这条路线的请求时,一切都很好,但假设我想 return 一个不同的状态代码,比如 401,我不能用类型为 json 的路线做到这一点.
我也试过下面的方法,但这个方法的问题是它停止了所有 odoo 未来的请求。
from odoo.http import request, Response
@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
Response.status = "401 unauthorized"
return {'error' : 'You are not allowed to access the resource'}
所以在上面的例子中,如果我将响应状态代码设置为 401 所有其他请求,即使它们是针对不同的路由,也将被停止并且其状态代码更改为 401 。
我在odoo14和odoo13都检查过这个问题。
您无法指定响应代码,因为您可以看到状态代码已硬编码在 http.py
:
def _json_response(self, result=None, error=None):
# ......
# ......
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
如果结果不是错误,状态代码始终为 200
。但是您可以直接更改方法的代码或使用猴子补丁 如果在结果中指定状态代码不是很重要,请不要这样做 ^^.
一个简单的猴子补丁将其放入您想要此行为的模块的 __init__.py
中。
from odoo.http import JsonRequest
class JsonRequestPatch(JsonRequest):
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
default_code = 200
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
# you don't want to remove some key of another result by mistake
if isinstance(response, dict)
defautl_code = response.pop('very_very_rare_key_here', default_code)
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', defautl_code ) or defautl_code,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
JsonRequest._json_response = JsonRequestPatch._json_response
并且在 JSON api 的结果中,您可以像这样更改状态代码
def some_controler(self, **kwargs):
result = ......
result['very_very_rare_key_here'] = 401
return result
猴子补丁的风险是你完全覆盖了方法,如果在新版本的 Odoo 中做了一些改变,你也必须在你的方法中做。
上面的代码来自 odoo 13.0
当我构建一个 restfull 模块来使用网站时,我做了很多这样的事情使用 axios
不允许在 GET
中发送正文要求。并且 odoo 期望参数在 json
请求的主体内。
我在 odoo 14 中创建了一个 Json 类型的路由。
@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
所以当我收到使用这条路线的请求时,一切都很好,但假设我想 return 一个不同的状态代码,比如 401,我不能用类型为 json 的路线做到这一点. 我也试过下面的方法,但这个方法的问题是它停止了所有 odoo 未来的请求。
from odoo.http import request, Response
@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
headers = request.httprequest.headers
args = request.httprequest.args
data = request.jsonrequest
Response.status = "401 unauthorized"
return {'error' : 'You are not allowed to access the resource'}
所以在上面的例子中,如果我将响应状态代码设置为 401 所有其他请求,即使它们是针对不同的路由,也将被停止并且其状态代码更改为 401 。 我在odoo14和odoo13都检查过这个问题。
您无法指定响应代码,因为您可以看到状态代码已硬编码在 http.py
:
def _json_response(self, result=None, error=None):
# ......
# ......
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
如果结果不是错误,状态代码始终为 200
。但是您可以直接更改方法的代码或使用猴子补丁 如果在结果中指定状态代码不是很重要,请不要这样做 ^^.
一个简单的猴子补丁将其放入您想要此行为的模块的 __init__.py
中。
from odoo.http import JsonRequest
class JsonRequestPatch(JsonRequest):
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
default_code = 200
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
# you don't want to remove some key of another result by mistake
if isinstance(response, dict)
defautl_code = response.pop('very_very_rare_key_here', default_code)
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', defautl_code ) or defautl_code,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
JsonRequest._json_response = JsonRequestPatch._json_response
并且在 JSON api 的结果中,您可以像这样更改状态代码
def some_controler(self, **kwargs):
result = ......
result['very_very_rare_key_here'] = 401
return result
猴子补丁的风险是你完全覆盖了方法,如果在新版本的 Odoo 中做了一些改变,你也必须在你的方法中做。
上面的代码来自 odoo 13.0
当我构建一个 restfull 模块来使用网站时,我做了很多这样的事情使用 axios
不允许在 GET
中发送正文要求。并且 odoo 期望参数在 json
请求的主体内。