diff --git a/base_future_response/README.rst b/base_future_response/README.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/base_future_response/__init__.py b/base_future_response/__init__.py new file mode 100644 index 00000000000..6c39179246e --- /dev/null +++ b/base_future_response/__init__.py @@ -0,0 +1 @@ +from . import future_response diff --git a/base_future_response/__manifest__.py b/base_future_response/__manifest__.py new file mode 100644 index 00000000000..16f86aeb0b4 --- /dev/null +++ b/base_future_response/__manifest__.py @@ -0,0 +1,13 @@ +# Copyright 2021 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Future Response", + "summary": """ + Backport Odoo 16 FutureReponse mechanism.""", + "version": "14.0.1.0.0", + "license": "LGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "maintainers": ["sbidoul"], + "website": "https://github.com/OCA/server-tools", +} diff --git a/base_future_response/future_response.py b/base_future_response/future_response.py new file mode 100644 index 00000000000..13622ed7952 --- /dev/null +++ b/base_future_response/future_response.py @@ -0,0 +1,73 @@ +# Copyright 2021 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import functools + +import werkzeug +from werkzeug.wrappers import Response + +from odoo import http + + +class FutureResponse: + """ + werkzeug.Response mock class that only serves as placeholder for + headers to be injected in the final response. + """ + + # used by werkzeug.Response.set_cookie + charset = "utf-8" + max_cookie_size = 4093 + + def __init__(self): + self.headers = werkzeug.datastructures.Headers() + + @functools.wraps(werkzeug.Response.set_cookie) + def set_cookie( + self, + key, + value="", + max_age=None, + expires=None, + path="/", + domain=None, + secure=False, + httponly=False, + samesite=None, + ): + werkzeug.Response.set_cookie( + self, + key, + value=value, + max_age=max_age, + expires=expires, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + +_original_WebRequest_init = http.WebRequest.__init__ + + +def WebRequest_init(self, httprequest): + _original_WebRequest_init(self, httprequest) + self.future_response = FutureResponse() + + +http.WebRequest.__init__ = WebRequest_init + + +_original_get_response = http.root.__class__.get_response + + +def get_response(self, httprequest, result, explicit_session): + response = _original_get_response(self, httprequest, result, explicit_session) + if isinstance(response, Response): + response.headers.extend(http.request.future_response.headers) + return response + + +http.root.__class__.get_response = get_response diff --git a/base_future_response/readme/DESCRIPTION.rst b/base_future_response/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..06446cedb1f --- /dev/null +++ b/base_future_response/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This is a backport of Odoo 16 ``request.future_response`` mechanism, to allow +setting cookies in the response before the response is constructed. diff --git a/base_future_response/readme/ROADMAP.rst b/base_future_response/readme/ROADMAP.rst new file mode 100644 index 00000000000..660c60ff9e6 --- /dev/null +++ b/base_future_response/readme/ROADMAP.rst @@ -0,0 +1,4 @@ +This module monkey patches the request object as soon as it is imported. The patch is +not reverted when the module is uninstalled. It should be totally harmless though, since +it simply adds a ``future_response`` attribute to the request object, and does not +change the response if cookies or headers are added to future_response. diff --git a/setup/base_future_response/odoo/addons/base_future_response b/setup/base_future_response/odoo/addons/base_future_response new file mode 120000 index 00000000000..9b3432b6e7d --- /dev/null +++ b/setup/base_future_response/odoo/addons/base_future_response @@ -0,0 +1 @@ +../../../../base_future_response \ No newline at end of file diff --git a/setup/base_future_response/setup.py b/setup/base_future_response/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/base_future_response/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)