From a90f577333a69db181ac400c4a5072ab575c0ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= Date: Thu, 1 Oct 2026 08:37:12 +0100 Subject: [PATCH] fix: Answer unhandled REST requests with a not found error - The REST not handled error now carries a 404 status, as its MVC sibling does - Unmatched requests no longer answer with a 500 nor get reported to Sentry - Tests cover the status code and the routing of unmatched requests Fixes OMNI-LDJ-14 --- CHANGELOG.md | 1 + rest/src/rest/exceptions.py | 6 +++++- rest/src/rest/test.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 460e38953..76d651a6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,3 +98,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Certificate parser now handles optional version field correctly, supporting both v1 certificates (no version) and v2/v3 certificates * Sorting a list by an unknown field, such as one sent by a translated page, now keeps the default order instead of failing - [#47](https://github.com/hivesolutions/colony-plugins/issues/47) * Filtering a list by a field of a related entity defined in another module no longer discards the filtered value +* Requests for addresses that no service handles are now answered with a not found error instead of an internal error, and are no longer reported to Sentry diff --git a/rest/src/rest/exceptions.py b/rest/src/rest/exceptions.py index d36385e0e..1dfae5add 100644 --- a/rest/src/rest/exceptions.py +++ b/rest/src/rest/exceptions.py @@ -169,16 +169,20 @@ class RESTRequestNotHandled(BadServiceRequest): The REST request not handled class. """ - def __init__(self, message): + def __init__(self, message, status_code=404): """ Constructor of the class. :type message: String :param message: The message to be printed. + :type status_code: int + :param status_code: The integer describing the status + code that is going to be returned in the request. """ BadServiceRequest.__init__(self) self.message = message + self.status_code = status_code def __str__(self): """ diff --git a/rest/src/rest/test.py b/rest/src/rest/test.py index 35b7e3c17..d1550281d 100644 --- a/rest/src/rest/test.py +++ b/rest/src/rest/test.py @@ -120,6 +120,32 @@ def test_is_request_handler(self): mock_request.uri = "/dynamic/other" self.assertEqual(rest.is_request_handler(mock_request), False) + def test_handle_request_not_handled(self): + mock_plugin = mocks.MockPlugin() + rest = system.REST(mock_plugin, session_c=system.RESTSession) + + mock_request = mocks.MockRequest() + mock_request.uri = "/dynamic/rest/test/path" + self.assertRaises( + exceptions.RESTRequestNotHandled, rest.handle_request, mock_request + ) + + service_plugin = mocks.MockRESTServicePlugin("test.plugin.id", ["other/.*"]) + rest.load_rest_service_plugin(service_plugin) + + try: + rest.handle_request(mock_request) + except exceptions.RESTRequestNotHandled as exception: + status_code = exception.status_code + + self.assertEqual(status_code, 404) + + # registers a route matching the request so that it's verified that + # it was the lack of such route that prevented its handling + service_plugin = mocks.MockRESTServicePlugin("other.plugin.id", ["test/.*"]) + rest.load_rest_service_plugin(service_plugin) + rest.handle_request(mock_request) + def test_load_rest_service_plugin(self): mock_plugin = mocks.MockPlugin() rest = system.REST(mock_plugin, session_c=system.RESTSession) @@ -1177,6 +1203,15 @@ def test_rest_request_error(self): def test_rest_request_not_handled(self): exception = exceptions.RESTRequestNotHandled("no handler found") self.assertEqual(exception.message, "no handler found") + self.assertEqual(exception.status_code, 404) + self.assertEqual(str(exception), "REST Request Not handled - no handler found") + + def test_rest_request_not_handled_custom_status(self): + exception = exceptions.RESTRequestNotHandled( + "no handler found", status_code=410 + ) + self.assertEqual(exception.message, "no handler found") + self.assertEqual(exception.status_code, 410) self.assertEqual(str(exception), "REST Request Not handled - no handler found") def test_invalid_path(self):