documentation
documentation copied to clipboard
Provide documentation concerning the "layers" of Odoo
Near the end of the ORM API docs page there is the following concerning exceptions:
Those types are understood by the RPC layer. Any other exception type bubbling until the RPC layer will be treated as a ‘Server error’.
I personally would find it extremely helpful to have a overview of what other "layers" there are in Odoo so I can better understand the architecture of when and how code is run.
What are all the "layers" of Odoo, including the RPC layer?
In that specific paragraph it means the errors are correctly serialized when sent over RPC.
The layers are what you would expect from any web framework: internet <-> http server <-> controller <-> models <-> database.
- The http server is responsible of parsing the incoming request and to identify which controller should process the request.
- The controller is the actual code that is executed to serve the request. Most of the time developer add controllers for their specific needs, e.g.
/web/content
to download an attachment (pretty narrow use case). - The models, the oriented-object abstraction wrapping database tables and rows
- Finally, the database itself.
Back to the sentence:
Those types are understood by the RPC layer. Any other exception type bubbling until the RPC layer will be treated as a ‘Server error’.
From all the controllers, there are two controllers that standout: the JSON-RPC controllers (/jsonrpc
and /web/dataset/...
) and the XML-RPC ones (/xmlrpc/2/
). Those "RPC" controllers provide a direct access to all the public methods on all the models (with regard to access rights). An external software can use Odoo via HTTP and the JSON-RPC or the XML-RPC controllers and perform models-related operation right away without implementing any new dedicated controller.
In order to be transmitted on the internet, both Odoo and the external software serialize the method arguments and return values either in JSON (json-rpc) either in XML (xml-rpc). Most python native objects (int, str, bool, list, tuple, ...) can be serialized/deserialized in both JSON and XML. The quoted paragraph explains that the exceptions that are not Odoo Exception are serialized as "ServerError" in order to hide the real cause of the issue. In the same mindset, when there is a non-odoo-error exception in other controllers, the HTTP response is simply "500 Internal Server Error", it doesn't show the real error.
Thanks for the detailed response! It wasn't immediately clear to me that the "layers" referred to in the documentation at this place are simply the typical layers of an HTTP server.
Regarding the serialization for non-Odoo exceptions as "ServerError" to hide the real cause: Is there a reason that this serialization is skipped for type="json"
routes? For example, if I create a controller like so:
from odoo.http import Controller, route
class TestController(Controller):
@route("/test", methods=["GET"], type="json", auth="public")
def endpoint_test(self):
raise Exception
And then call it at http://localhost:8069/test
, I get the following response:
{
"jsonrpc": "2.0",
"id": null,
"error": {
"code": 200,
"message": "Odoo Server Error",
"data": {
"name": "builtins.Exception",
"debug": "Traceback (most recent call last):\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 624, in _handle_exception\n return super(JsonRequest, self)._handle_exception(exception)\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 310, in _handle_exception\n raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])\n File \"/usr/lib/python3/dist-packages/odoo/tools/pycompat.py\", line 14, in reraise\n raise value\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 669, in dispatch\n result = self._call_function(**self.params)\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 350, in _call_function\n return checked_call(self.db, *args, **kwargs)\n File \"/usr/lib/python3/dist-packages/odoo/service/model.py\", line 94, in wrapper\n return f(dbname, *args, **kwargs)\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 339, in checked_call\n result = self.endpoint(*a, **kw)\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 915, in __call__\n return self.method(*args, **kw)\n File \"/usr/lib/python3/dist-packages/odoo/http.py\", line 515, in response_wrap\n response = f(*args, **kw)\n File \"/mnt/<path-omitted>/test.py\", line 6, in endpoint_test\n raise Exception\nException\n",
"message": "",
"arguments": [],
"exception_type": "internal_error",
"context": {}
}
}
}
Which, as you can see, includes detailed information regarding the exception, even though the route is public. Is that intentional? It seems like this is something you'd want to omit in production (only show during development).
Indeed it is different in JSON-RPC. The JSON-RPC protocol is the one used inside the web client (/web). We want the traceback to be shown in such case.
Isn't that kind of a security hole then? Anyone could just call something with JSON-RPC instead of XML-RPC if they wish to see a full traceback instead of a simple 500 response?
The quoted paragraph explains that the exceptions that are not Odoo Exception are serialized as "ServerError" in order to hide the real cause of the issue
I was wrong about it, it is a limitation of XML-RPC, we can only give back a single int and a single string. The traceback doesn't fit. It is not a security, we don't want to hide the underlying issue, just XML-RPC doesn't give us the choice.
There is no such thing in JSON-RPC, we can send back a whole payload so we include the traceback :)
That makes more sense. Thanks for clarifying that!
Concerning the original topic of this issue, I think the "layers" of Odoo could actually deserve some documentation on an "architecture" page. It wouldn't need to go into a lot of detail, it would be a high level overview of the parts of Odoo from a technical perspective and the basics of how they interact.
Here is an example of the kind of page I'm talking about for another software platform I like called Directus. Notice how in the page content they use phrases like "At the lowest layer..." and then later "The next layer contains..." to explain the different "layers" of the platform. For developers like myself trying to understand how Odoo is structured at a high level, a page like this would be very helpful.