I'd like to accept and respond to JSON requests in Odoo from sources that may be out of my control. The reason this is not straightforward is because Odoo is forcing me to use JSON-RPC, which is not suitable for the source I'm interacting with.
For example, if I set the route type to http
in the @http.route
decorator, Odoo rejects the request if the mimetype is application/json
but the body has no content. This isn't going to work in my case because I may not be able to choose what the other source sends to me. Additionally, I am unable to send back a custom JSON response unless the incoming request doesn't have the application/json
mimetype, which again is not in my control.
I have done a lot of searching on the internet and read much of Odoo's HTTP source code. The "solution" I keep seeing everywhere is to monkey patch the JsonRequest
class one way or another. This allows me to indeed respond with whatever I want, however it doesn't allow me to accept whatever the service may send me.
One specific case I need to be able to handle is incoming application/json
GET requests with no body. How can I achieve this despite Odoo's heavy handed JSON-RPC handing?
CodePudding user response:
There is no correct way to accomplish this, I'd call the described method acceptable. It applies to versions of Odoo 10 through 15.
In my opinion, it would be better to leave JsonRequest class alone and let it do its JSON-RPC related job. There is odoo.http.Root.get_request method which constructs the json-rpc or http request object, depending on the content type:
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
"""
# ...
def get_request(self, httprequest):
# deduce type of request
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequest(httprequest)
else:
return HttpRequest(httprequest)
This point seems to be the most relevant one to be patched, with returning the custom request class object from this method. There is an issue, though - this method is called prior to any route detection. You have to invent a suitable method to tell, which request class object to return.
To have an idea about a possible implementation, please, see OCA base_rest module.