From 44d7d8ba2692b81df2d647c8aeebd132a78e999f Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 8 May 2025 12:43:52 +0200 Subject: [PATCH] base_rest: api-docs add current server option Sometimes the current domain is not what is used in web.base.url. If this is the case, show the option to use the current domain as server. --- .../apispec/base_rest_service_apispec.py | 29 +++++++++++++------ base_rest/tests/test_openapi_generator.py | 24 +++++++++++---- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/base_rest/apispec/base_rest_service_apispec.py b/base_rest/apispec/base_rest_service_apispec.py index a9c4bdbf..26ce57a8 100644 --- a/base_rest/apispec/base_rest_service_apispec.py +++ b/base_rest/apispec/base_rest_service_apispec.py @@ -6,6 +6,8 @@ from apispec import APISpec +from odoo.http import request + from ..core import _rest_services_databases from ..tools import ROUTING_DECORATOR_ATTR from .rest_method_param_plugin import RestMethodParamPlugin @@ -42,15 +44,24 @@ def _get_servers(self): if spec["collection_name"] == self._service._collection: collection_path = path break - base_url = env["ir.config_parameter"].sudo().get_param("web.base.url") - return [ - { - "url": ( - f"{base_url.strip('/')}/{collection_path.strip('/')}" - f"/{self._service._usage}" - ) - } - ] + base_domain = ( + env["ir.config_parameter"].sudo().get_param("web.base.url").strip("/") + ) + current_domain = request.httprequest.url_root.strip("/") + domains = [base_domain] + if base_domain != current_domain: + domains.append(current_domain) + res = [] + for domain in domains: + res.append( + { + "url": "/".join( + [domain, collection_path.strip("/"), self._service._usage] + ) + } + ) + + return res def _get_plugins(self): return [ diff --git a/base_rest/tests/test_openapi_generator.py b/base_rest/tests/test_openapi_generator.py index f555d64c..92d60c2c 100644 --- a/base_rest/tests/test_openapi_generator.py +++ b/base_rest/tests/test_openapi_generator.py @@ -2,6 +2,7 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo.addons.component.core import Component +from odoo.addons.website.tools import MockRequest from .. import restapi from .common import TransactionRestServiceRegistryCase @@ -42,12 +43,20 @@ def _get_partner_schema(self): self._build_services(self, PartnerService) service = self._get_service_component(self, "partner") - openapi = service.to_openapi() + with MockRequest(self.env, url_root="https://example.com"): + openapi = service.to_openapi() self.assertTrue(openapi) # The service url is available at base_url/controller._root_path/_usage - url = openapi["servers"][0]["url"] - self.assertEqual(self.base_url + "/test_controller/partner", url) + servers = openapi.get("servers", []) + self.assertEqual(len(servers), 2) + expected = sorted( + [ + f"{self.base_url}/test_controller/partner", + "https://example.com/test_controller/partner", + ] + ) + self.assertListEqual(sorted([s["url"] for s in servers]), expected) # The title is generated from the service usage # The service info must contains a title and a description @@ -122,7 +131,8 @@ def update_name(self, _id, _name): self._build_services(self, PartnerService) service = self._get_service_component(self, "partner") - openapi = service.to_openapi() + with MockRequest(self.env, url_root="https://example.com"): + openapi = service.to_openapi() self.assertTrue(openapi) paths = openapi["paths"] self.assertIn("/{id}/update_name/{name}", paths) @@ -201,7 +211,8 @@ def _get_openapi_default_responses(self): self._build_services(self, PartnerService) service = self._get_service_component(self, "partner") - openapi = service.to_openapi() + with MockRequest(self.env, url_root="https://example.com"): + openapi = service.to_openapi() paths = openapi["paths"] self.assertIn("/{id}/update_name/{name}", paths) path = paths["/{id}/update_name/{name}"] @@ -250,7 +261,8 @@ def _get_attachment_schema(self): self._build_services(self, AttachmentService) service = self._get_service_component(self, "attachment") - openapi = service.to_openapi() + with MockRequest(self.env, url_root="https://example.com"): + openapi = service.to_openapi() paths = openapi["paths"] # The paths must contains 2 entries (1 by routes) self.assertSetEqual({"/{id}/download", "/create"}, set(openapi["paths"]))