Skip to content

[18.0][ADD] http_api_dispatcher: generic dispatcher for JSON APIs - #179

Open
simahawk wants to merge 1 commit into
OCA:18.0from
camptocamp:18-add-http_json_dispatcher
Open

simahawk wants to merge 1 commit into
OCA:18.0from
camptocamp:18-add-http_json_dispatcher

Conversation

@simahawk

@simahawk simahawk commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

base_rest ties every API to its components and to the restapi route type, so an API can't leave base_rest (shopfloor included) without a replacement. This module provides the common plumbing of an API endpoint as a route type of its own, http_json, independent of components. APIs can then move to it one endpoint at a time. The error format and the params stay compatible with base_rest .

Key features

  • http_json route type: params parsed once from the query string and the body (JSON or forms)
  • language set from the Accept-Language header
  • input and output validated/converted by pluggable params declared on the route (see http_json_cerberus)
  • results serialized as JSON (dates as ISO strings, decimals as floats)
  • exceptions turned into JSON error responses w/ the proper status codes
  • hooks on each step, extensible via standard Odoo inheritance

A bit more of context in comparison to base_rest/fastapi (from module's readme)

base_rest (OCA/rest-framework) has been the foundation of many APIs,
including the Shopfloor apps. Over time it showed some limits:

  • it is a monolith: dispatcher, service layer, validation,
    documentation and routing are bound together
    and you cannot use one piece without the others
  • services must be components, a second registry
    with its own inheritance and boot lifecycle,
    which is often used only to look up a class by name
  • controllers are generated at boot from the services,
    making routing hard to follow and to customize

The fastapi stack is a way to go for new standalone APIs,
but moving existing APIs to it means rewriting every service and schema and endpoints are not extendable models.
Plus, it pulls in more external dependencies that for many cases are not needed.

This module is the base of a lighter stack, made of small modules
that can be used separately and extended via standard Odoo inheritance:

  • http_json_dispatcher: the http_json route type (parsing, validation hooks, JSON errors)
    usable by plain Odoo controllers
  • endpoint_spec: declare endpoints on services, for routes generators
  • http_json_cerberus: Cerberus validation
  • openapi_doc_base: API docs from the actual routes
  • endpoint_route_handler generators: routes computed from the code
    without storing a row per route

Goals:

  • simplify the base_rest stack without moving to fastapi
  • keep modules small and reusable
  • drop the dependency on component, staying highly customizable
    (routing keys per route, ir.http hooks per database)
  • stay compatible with base_rest clients (error format, validation behavior)
    to allow a gradual migration

The only doubt that I have ATM is: should this stay here or go to rest-framework repo? (even though is not strictly bound to "REST" stuff.

@lmignon would be nice to have your feedback 🙏
One last thing: as this work it's a derivation of base_rest, I've tried to keep the copyright where it made sense, but please let me know if I left something behind 😉

@OCA-git-bot OCA-git-bot added series:18.0 mod:http_json_dispatcher Module http_json_dispatcher labels Oct 16, 2026
simahawk added a commit to camptocamp/web-api that referenced this pull request Oct 16, 2026
Pending OCA#179 (http_json_dispatcher).
To be removed once merged.
@simahawk
simahawk force-pushed the 18-add-http_json_dispatcher branch from 63e7a78 to 810a3df Compare October 16, 2026 14:22
simahawk added a commit to camptocamp/web-api that referenced this pull request Oct 16, 2026
Pending OCA#179 (http_json_dispatcher).
To be removed once merged.
@lmignon

lmignon commented Oct 16, 2026 •

Copy link
Copy Markdown

@simahawk I like the idea and the approach. It seems like a good step towards reducing the amount of code while adding more value on top of Odoo's standard features while also providing a safe path away from base_rest.

Regarding:

fastapi endpoints are not extendable models.

I agree, but even though Odoo controllers can be inherited, if the business logic is implemented directly in a route method, it becomes difficult to extend as well. That's why, regardless of the approach, the actual logic should be delegated to a model, wizard, or transient model. 😏

For the record, pydantic models are extendable.... (you need extra libs and addon but it works like a charm)

rest-framework seems to me like a more logical place for this kind of addon, but that's just my personal opinion.

Comment thread http_api_dispatcher/parsers.py
@lmignon

lmignon commented Oct 19, 2026

Copy link
Copy Markdown

@simahawk http_json is may be too restrictive.... REST doesn't limit to json. You could receive multipart request with a form part with a json document and others part with binary files....
Another question: how do you plan to allow the developer to not hard link its service to a specific authentication method?

@simahawk

Copy link
Copy Markdown
Contributor Author

@simahawk http_json is may be too restrictive.... REST doesn't limit to json. You could receive multipart request with a form part with a json document and others part with binary files....

That's correct but I couldn't find a better naming and a json payload is what is going to handle 99% of the times 😅 Would you prefer http_api?

Another question: how do you plan to allow the developer to not hard link its service to a specific authentication method?

One of the nice pros of this approach is that you can use standard controllers and as such you can use auth="whatever" and support that w/ ir.http._auth_method_whatever().

Same for the Cerberus validator #182 that you can use on std controllers.

@lmignon

lmignon commented Oct 19, 2026

Copy link
Copy Markdown

That's correct but I couldn't find a better naming and a json payload is what is going to handle 99% of the times 😅 Would you prefer http_api?

http_api looks better to me, but this choice deserves more input than just mine. ;-)

@simahawk

Copy link
Copy Markdown
Contributor Author

That's correct but I couldn't find a better naming and a json payload is what is going to handle 99% of the times 😅 Would you prefer http_api?

http_api looks better to me, but this choice deserves more input than just mine. ;-)

Curious thing: I first chose that name but I found it too generic 😆

@simahawk
simahawk force-pushed the 18-add-http_json_dispatcher branch 2 times, most recently from fb10938 to bf8a38b Compare October 20, 2026 13:21
Route type `http_api`: generic dispatcher for HTTP routes speaking JSON.

* parse query string and body (JSON, forms) once
* set lang from `Accept-Language`
* validate/convert input and output via pluggable params
  declared on the route
* serialize results as JSON
* map exceptions to JSON error responses (format compatible w/ base_rest)
* `ir.http` hooks to extend each step of the pipeline (`_http_api_*`)

Lazy params: `ApiCall` exposes `query`, `body` and `params` as cached
properties, parsed on first access. `params` merges them: query, then
body, then URL args.

CSRF: the token is read from the `X-CSRF-Token` header first; the query
and the body are parsed only when the header is missing. The `csrf_token`
key is transport data: it is never part of the params of the endpoint.

Parsers: routes override the body parsers via `body_parsers` (mimetype
map, formerly `parsers`) and the query parser via `query_parser`.

Params: `ApiParam.from_params(call)` receives the `ApiCall` and reads
`call.params`, `call.query` or `call.body` as it needs. A param reading
only the query never parses the body.

Errors: `dev_mode` is configured in the `[http_api]` section.
@simahawk
simahawk force-pushed the 18-add-http_json_dispatcher branch from bf8a38b to f00fde4 Compare October 21, 2026 07:25
simahawk added a commit to camptocamp/web-api that referenced this pull request Oct 21, 2026
Pending OCA#179 (http_api_dispatcher).
To be removed once merged.
@OCA-git-bot OCA-git-bot added mod:http_api_dispatcher Module http_api_dispatcher and removed mod:http_json_dispatcher Module http_json_dispatcher labels Oct 21, 2026
@simahawk simahawk changed the title [18.0][ADD] http_json_dispatcher: JSON API dispatcher route type [18.0][ADD] http_api_dispatcher: generic dispatcher for JSON APIs Oct 21, 2026
@simahawk

Copy link
Copy Markdown
Contributor Author

renamed module back to http_api* and routing type to http_api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:http_api_dispatcher Module http_api_dispatcher series:18.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants