Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide documentation concerning the "layers" of Odoo #2203

Open
AaronBeaudoin opened this issue Jun 13, 2022 · 6 comments
Open

Provide documentation concerning the "layers" of Odoo #2203

AaronBeaudoin opened this issue Jun 13, 2022 · 6 comments
Assignees

Comments

@AaronBeaudoin
Copy link

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?

@AaronBeaudoin AaronBeaudoin changed the title Documenting the "layers" of Odoo Documenting the "layers" of Odoo? Jun 13, 2022
@AaronBeaudoin AaronBeaudoin changed the title Documenting the "layers" of Odoo? Provide documentation concerning the "layers" of Odoo Jun 13, 2022
@Julien00859
Copy link
Member

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.

  1. The http server is responsible of parsing the incoming request and to identify which controller should process the request.
  2. 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).
  3. The models, the oriented-object abstraction wrapping database tables and rows
  4. 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.

@AaronBeaudoin
Copy link
Author

AaronBeaudoin commented Jun 14, 2022

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).

@Julien00859
Copy link
Member

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.

@AaronBeaudoin
Copy link
Author

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?

@Julien00859
Copy link
Member

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 :)

@AaronBeaudoin
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants