Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement optional url prefix the Django way #15080

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions awx/api/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra
kwargs = {}
if 'version' not in kwargs:
kwargs['version'] = settings.REST_FRAMEWORK['DEFAULT_VERSION']
url = drf_reverse(viewname, args, kwargs, request, format, **extra)

return transform_optional_api_urlpattern_prefix_url(request, url)
return drf_reverse(viewname, args, kwargs, request, format, **extra)


class URLPathVersioning(BaseVersioning):
Expand Down
26 changes: 26 additions & 0 deletions awx/main/middleware.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

import functools
import logging
import threading
import time
Expand All @@ -23,6 +24,7 @@
from awx.conf import fields, register
from awx.main.utils.profiling import AWXProfiler
from awx.main.utils.common import memoize
from awx.urls import get_urlpatterns


logger = logging.getLogger('awx.main.middleware')
Expand Down Expand Up @@ -220,3 +222,27 @@ class MigrationRanCheckMiddleware(MiddlewareMixin):
def process_request(self, request):
if is_migrating() and getattr(resolve(request.path), 'url_name', '') != 'migrations_notran':
return redirect(reverse("ui:migrations_notran"))


class OptionalURLPrefixPath(MiddlewareMixin):
@functools.lru_cache
def _url_optional(self, prefix):
# Relavant Django code path https://github.com/django/django/blob/stable/4.2.x/django/core/handlers/base.py#L300
#
# resolve_request(request)
# get_resolver(request.urlconf)
# _get_cached_resolver(request.urlconf) <-- cached via @functools.cache
#
# Django will attempt to cache the value(s) of request.urlconf
# Being hashable is a prerequisit for being cachable.
# tuple() is hashable list() is not.
# Hence the tuple(list()) wrap.
return tuple(get_urlpatterns(prefix=prefix))

def process_request(self, request):
prefix = settings.OPTIONAL_API_URLPATTERN_PREFIX

if request.path.startswith(f"/api/{prefix}"):
request.urlconf = self._url_optional(prefix)
else:
request.urlconf = 'awx.urls'
1 change: 1 addition & 0 deletions awx/settings/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@
'django.contrib.auth.middleware.AuthenticationMiddleware',
'awx.main.middleware.DisableLocalAuthMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'awx.main.middleware.OptionalURLPrefixPath',
'awx.sso.middleware.SocialAuthMiddleware',
'crum.CurrentRequestUserMiddleware',
'awx.main.middleware.URLModificationMiddleware',
Expand Down
58 changes: 32 additions & 26 deletions awx/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,42 @@
from awx.main.views import handle_400, handle_403, handle_404, handle_500, handle_csp_violation, handle_login_redirect


urlpatterns = [
re_path(r'', include('awx.ui.urls', namespace='ui')),
re_path(r'^ui_next/.*', include('awx.ui_next.urls', namespace='ui_next')),
path('api/', include('awx.api.urls', namespace='api')),
]
def get_urlpatterns(prefix=None):
if not prefix:
prefix = '/'
else:
prefix = f'/{prefix}/'

urlpatterns = [
re_path(r'', include('awx.ui.urls', namespace='ui')),
re_path(r'^ui_next/.*', include('awx.ui_next.urls', namespace='ui_next')),
path(f'api{prefix}', include('awx.api.urls', namespace='api')),
]

if settings.OPTIONAL_API_URLPATTERN_PREFIX:
urlpatterns += [
path(f'api/{settings.OPTIONAL_API_URLPATTERN_PREFIX}/', include('awx.api.urls')),
path(f'api{prefix}v2/', include(resource_api_urls)),
re_path(r'^sso/', include('awx.sso.urls', namespace='sso')),
re_path(r'^sso/', include('social_django.urls', namespace='social')),
re_path(r'^(?:api/)?400.html$', handle_400),
re_path(r'^(?:api/)?403.html$', handle_403),
re_path(r'^(?:api/)?404.html$', handle_404),
re_path(r'^(?:api/)?500.html$', handle_500),
re_path(r'^csp-violation/', handle_csp_violation),
re_path(r'^login/', handle_login_redirect),
]

urlpatterns += [
re_path(r'^api/v2/', include(resource_api_urls)),
re_path(r'^sso/', include('awx.sso.urls', namespace='sso')),
re_path(r'^sso/', include('social_django.urls', namespace='social')),
re_path(r'^(?:api/)?400.html$', handle_400),
re_path(r'^(?:api/)?403.html$', handle_403),
re_path(r'^(?:api/)?404.html$', handle_404),
re_path(r'^(?:api/)?500.html$', handle_500),
re_path(r'^csp-violation/', handle_csp_violation),
re_path(r'^login/', handle_login_redirect),
]

if settings.SETTINGS_MODULE == 'awx.settings.development':
try:
import debug_toolbar

urlpatterns += [re_path(r'^__debug__/', include(debug_toolbar.urls))]
except ImportError:
pass
if settings.SETTINGS_MODULE == 'awx.settings.development':
try:
import debug_toolbar

urlpatterns += [re_path(r'^__debug__/', include(debug_toolbar.urls))]
except ImportError:
pass

return urlpatterns


urlpatterns = get_urlpatterns()

handler400 = 'awx.main.views.handle_400'
handler403 = 'awx.main.views.handle_403'
Expand Down
Loading