-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fb6b727
commit 17d8822
Showing
7 changed files
with
203 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Copyright 2024 Akretion (http://www.akretion.com). | ||
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import logging | ||
from . import models | ||
from . import http | ||
from odoo import SUPERUSER_ID, api | ||
from odoo.addons.extendable.models.ir_http import IrHttp | ||
from odoo.addons.fastapi.tests.common import FastAPITransactionCase | ||
from odoo.tests.common import SavepointCase | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
FastAPITransactionCase.__bases__ = (SavepointCase,) | ||
|
||
|
||
@classmethod | ||
def _dispatch(cls): | ||
with cls._extendable_context_registry(): | ||
return super(IrHttp, cls)._dispatch() | ||
|
||
|
||
IrHttp._dispatch = _dispatch | ||
|
||
|
||
def post_init_hook(cr, registry): | ||
env = api.Environment(cr, SUPERUSER_ID, {}) | ||
# this is the trigger that sends notifications when jobs change | ||
_logger.info("Resyncing registries") | ||
endpoints_ids = env["fastapi.endpoint"].search([]).ids | ||
env["fastapi.endpoint"]._handle_registry_sync(endpoints_ids) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright 2024 Akretion (http://www.akretion.com). | ||
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "Fastapi Backport", | ||
"summary": "Backport of FastAPI to Odoo 14.0", | ||
"version": "14.0.1.0.0", | ||
"author": " Akretion", | ||
"license": "AGPL-3", | ||
"depends": [ | ||
"sixteen_in_fourteen", | ||
"base_future_response", | ||
"fastapi", | ||
"pydantic", | ||
"extendable_fastapi", | ||
"extendable", | ||
], | ||
"post_init_hook": "post_init_hook", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Copyright 2023 ACSONE SA/NV | ||
# Copyright 2024 Akretion (http://www.akretion.com). | ||
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import json | ||
import logging | ||
from functools import lru_cache | ||
|
||
import werkzeug.datastructures | ||
|
||
import odoo | ||
from odoo import http | ||
from odoo.tools import date_utils | ||
|
||
from odoo.addons.fastapi.fastapi_dispatcher import FastApiDispatcher | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class FastapiRootPaths: | ||
_root_paths_by_db = {} | ||
|
||
@classmethod | ||
def set_root_paths(cls, db, root_paths): | ||
cls._root_paths_by_db[db] = root_paths | ||
cls.is_fastapi_path.cache_clear() | ||
|
||
@classmethod | ||
@lru_cache(maxsize=1024) | ||
def is_fastapi_path(cls, db, path): | ||
return any( | ||
path.startswith(root_path) | ||
for root_path in cls._root_paths_by_db.get(db, []) | ||
) | ||
|
||
|
||
class FastapiRequest(http.WebRequest): | ||
_request_type = "fastapi" | ||
|
||
def __init__(self, *args): | ||
super().__init__(*args) | ||
self.params = {} | ||
self._dispatcher = FastApiDispatcher(self) | ||
|
||
def make_response(self, data, headers=None, cookies=None, status=200): | ||
"""Helper for non-HTML responses, or HTML responses with custom | ||
response headers or cookies. | ||
While handlers can just return the HTML markup of a page they want to | ||
send as a string if non-HTML data is returned they need to create a | ||
complete response object, or the returned data will not be correctly | ||
interpreted by the clients. | ||
:param basestring data: response body | ||
:param headers: HTTP headers to set on the response | ||
:type headers: ``[(name, value)]`` | ||
:param collections.abc.Mapping cookies: cookies to set on the client | ||
""" | ||
response = http.Response(data, status=status, headers=headers) | ||
if cookies: | ||
for k, v in cookies.items(): | ||
response.set_cookie(k, v) | ||
return response | ||
|
||
def make_json_response(self, data, headers=None, cookies=None, status=200): | ||
"""Helper for JSON responses, it json-serializes ``data`` and | ||
sets the Content-Type header accordingly if none is provided. | ||
:param data: the data that will be json-serialized into the response body | ||
:param int status: http status code | ||
:param List[(str, str)] headers: HTTP headers to set on the response | ||
:param collections.abc.Mapping cookies: cookies to set on the client | ||
:rtype: :class:`~odoo.http.Response` | ||
""" | ||
data = json.dumps(data, ensure_ascii=False, default=date_utils.json_default) | ||
|
||
headers = werkzeug.datastructures.Headers(headers) | ||
headers["Content-Length"] = len(data) | ||
if "Content-Type" not in headers: | ||
headers["Content-Type"] = "application/json; charset=utf-8" | ||
|
||
return self.make_response(data, headers.to_wsgi_list(), cookies, status) | ||
|
||
def dispatch(self): | ||
return self._dispatcher.dispatch(None, None) | ||
|
||
def _handle_exception(self, exception): | ||
_logger.exception( | ||
"Exception during fastapi request handling", exc_info=exception | ||
) | ||
return self._dispatcher.handle_error(exception) | ||
|
||
|
||
ori_get_request = http.root.__class__.get_request | ||
|
||
|
||
def get_request(self, httprequest): | ||
db = httprequest.session.db | ||
if db and odoo.service.db.exp_db_exist(db): | ||
# on the very first request processed by a worker, | ||
# registry is not loaded yet | ||
# so we enforce its loading here. | ||
odoo.registry(db) | ||
if FastapiRootPaths.is_fastapi_path(db, httprequest.path): | ||
return FastapiRequest(httprequest) | ||
return ori_get_request(self, httprequest) | ||
|
||
|
||
http.root.__class__.get_request = get_request |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import fastapi_endpoint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright 2024 Akretion (http://www.akretion.com). | ||
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
|
||
from odoo import api, models | ||
|
||
from ..http import FastapiRootPaths | ||
|
||
|
||
class FastapiEndpoint(models.Model): | ||
_inherit = "fastapi.endpoint" | ||
|
||
@api.model | ||
def _update_root_paths_registry(self): | ||
root_paths = self.env["fastapi.endpoint"].search([]).mapped("root_path") | ||
FastapiRootPaths.set_root_paths(self.env.cr.dbname, root_paths) | ||
|
||
def _register_hook(self): | ||
super()._register_hook() | ||
self._update_root_paths_registry() | ||
|
||
def _inverse_root_path(self): | ||
super()._inverse_root_path() | ||
self._update_root_paths_registry() | ||
|
||
@api.depends("root_path") | ||
def _compute_urls(self): | ||
base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url") | ||
for rec in self: | ||
rec.docs_url = f"{base_url}{rec.root_path}/docs" | ||
rec.redoc_url = f"{base_url}{rec.root_path}/redoc" | ||
rec.openapi_url = f"{base_url}{rec.root_path}/openapi.json" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../fastapi_backport |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
setup_requires=['setuptools-odoo'], | ||
odoo_addon=True, | ||
) |