Island: Handle duplicate url parameter edge case in FlaskDIWrapper

This commit is contained in:
Mike Salvatore 2022-05-23 08:23:43 -04:00 committed by vakarisz
parent 108c86d56c
commit 4b9fe6a83d
2 changed files with 27 additions and 1 deletions

View File

@ -1,4 +1,5 @@
import os
import re
import uuid
from datetime import timedelta
from typing import Iterable, Type
@ -113,6 +114,8 @@ class FlaskDIWrapper:
class URLAlreadyExistsError(Exception):
pass
url_parameter_regex = re.compile(r"<.*?:.*?>")
def __init__(self, api: flask_restful.Api, container: DIContainer):
self._api = api
self._container = container
@ -125,7 +128,7 @@ class FlaskDIWrapper:
self._api.add_resource(resource, *resource.urls, resource_class_args=dependencies)
def _register_unique_urls(self, urls: Iterable[str]):
for url in map(lambda x: x.rstrip("/"), urls):
for url in map(FlaskDIWrapper._format_url, urls):
if url in self._registered_urls:
raise FlaskDIWrapper.URLAlreadyExistsError(
f"URL {url} has already been registered!"
@ -133,6 +136,11 @@ class FlaskDIWrapper:
self._registered_urls.add(url)
@staticmethod
def _format_url(url: str):
new_url = url.rstrip("/")
return FlaskDIWrapper.url_parameter_regex.sub("<PARAMETER_PLACEHOLDER>", new_url)
def init_api_resources(api: FlaskDIWrapper):
api.add_resource(Root)

View File

@ -35,6 +35,24 @@ def test_duplicate_urls(resource_mng):
resource_mng.add_resource(resource2)
def test_duplicate_urls__parameters(resource_mng):
resource1 = get_mock_resource("res1", ["/url/<string:param1>"])
resource2 = get_mock_resource("res2", ["/url/<string:param2>"])
resource_mng.add_resource(resource1)
with pytest.raises(FlaskDIWrapper.URLAlreadyExistsError):
resource_mng.add_resource(resource2)
def test_duplicate_urls__multiple_parameters(resource_mng):
resource1 = get_mock_resource("res1", ["/url/<string:agent_name>/<string:param>"])
resource2 = get_mock_resource("res2", ["/url/<int:agent_id>/<string:param>"])
resource_mng.add_resource(resource1)
with pytest.raises(FlaskDIWrapper.URLAlreadyExistsError):
resource_mng.add_resource(resource2)
def test_adding_resources(resource_mng):
resource = get_mock_resource("res1", ["/url"])