4

I have created a route with type Json in odoo 14.

@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

So when I receive request using this route everything is fine, but suppose I want to return a different status code like 401, I could not do that with the route which type is json. I have also tried the bellow method but the problem with this method is that it stops all odoo future requests.

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'}

So in the above example If I set the response status code to 401 all other requests even if they are to different routes will be stopped and its status code changes 401 . I have checked this problem in both odoo14 and odoo13.

Aemal Shirzai
  • 65
  • 1
  • 7

1 Answers1

9

You cannot specify the code of the response, as you can see the status code is hardcoded in 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))]
    )

If the result is not an error the status code is always 200. but you can change the code of the method directly or use a monkey patch witch if it's not really important to specify the code of status in the result don't do ti ^^.

A simple monkey patch put this in __init__.py of the module that you want this behavior in it.

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

and in the result of JSON api you can change the code of status like this

 def some_controler(self, **kwargs):
        result = ......
        result['very_very_rare_key_here'] = 401
        return result

The risk in monkey patching is you override the method compeletly and if some change is done in Odoo in new version you have to do you it in your method too. The above code is from odoo 13.0 I did a lot of this when I build a restfull module to work with a website uses axios witch don't allow sending body in GET request. and odoo expect the argument to be inside the body in json request.

Charif DZ
  • 14,415
  • 3
  • 21
  • 40
  • 1
    Thank you the answer worked absolutely fine. When I send a request from postman for example its fine. But it throws error if I open the module interface. so to handle that I just added a try and catch. try: if 'custom_status_code' in result: default_code = result.pop('custom_status_code', default_code) except Exception as e: _logger.warning("Custom Json Request Handling {}".format(str(e))) – Aemal Shirzai May 24 '21 at 10:40
  • 1
    My mistake forget that response could be a direct dictionary or list of dictoinary, I think verifying the type of reponse will do the trick to avoid logging warning that you don't need in your log file. Check my edits you will get the idea – Charif DZ May 24 '21 at 11:56
  • 1
    DUDE!!!! I wish i could give you a bro hug!!! Thank you so much. you just help me from my hours struggling :) – Jacky Supit Dec 16 '21 at 13:47