Skip to content

Commit

Permalink
revert Swagger UI view to single request and alternative #211 #173
Browse files Browse the repository at this point in the history
  • Loading branch information
tfranzel committed Dec 17, 2020
1 parent 6cd3cc8 commit 042e8d4
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 15 deletions.
6 changes: 6 additions & 0 deletions drf_spectacular/templates/drf_spectacular/swagger_ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
<body>
<div id="swagger-ui"></div>
<script src="{{dist}}/swagger-ui-bundle.js"></script>
{% if script_url %}
<script src="{{script_url|safe}}"></script>
{% else %}
<script>
{% include template_name_js %}
</script>
{% endif %}
</body>
</html>
4 changes: 2 additions & 2 deletions drf_spectacular/templates/drf_spectacular/swagger_ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const swagger_settings = {{settings|safe}}

const ui = SwaggerUIBundle({
url: "{{schema_url|safe}}",
dom_id: '#swagger-ui',
dom_id: "#swagger-ui",
presets: [
SwaggerUIBundle.presets.apis,
],
Expand All @@ -11,7 +11,7 @@ const ui = SwaggerUIBundle({
],
layout: "BaseLayout",
requestInterceptor: (request) => {
request.headers['X-CSRFToken'] = "{{csrf_token}}"
request.headers["X-CSRFToken"] = "{{csrf_token}}"
return request;
},
...swagger_settings
Expand Down
27 changes: 26 additions & 1 deletion drf_spectacular/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,31 @@ class SpectacularSwaggerView(APIView):
template_name = 'drf_spectacular/swagger_ui.html'
template_name_js = 'drf_spectacular/swagger_ui.js'

@extend_schema(exclude=True)
def get(self, request, *args, **kwargs):
schema_url = self.url or get_relative_url(reverse(self.url_name, request=request))
return Response(
data={
'dist': spectacular_settings.SWAGGER_UI_DIST,
'favicon_href': spectacular_settings.SWAGGER_UI_FAVICON_HREF,
'schema_url': set_query_parameters(
url=schema_url,
lang=request.GET.get('lang')
),
'settings': json.dumps(spectacular_settings.SWAGGER_UI_SETTINGS),
'template_name_js': self.template_name_js
},
template_name=self.template_name,
)


class SpectacularSwaggerSplitView(SpectacularSwaggerView):
"""
Alternate Swagger UI implementation that separates the html request from the
javascript request to cater to web servers with stricter CSP policies.
"""
url_self = None

@extend_schema(exclude=True)
def get(self, request, *args, **kwargs):
if request.GET.get('script') is not None:
Expand All @@ -97,7 +122,7 @@ def get(self, request, *args, **kwargs):
content_type='application/javascript',
)
else:
script_url = request.get_full_path()
script_url = self.url_self or request.get_full_path()
return Response(
data={
'dist': spectacular_settings.SWAGGER_UI_DIST,
Expand Down
2 changes: 0 additions & 2 deletions tests/test_i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,4 @@ def test_i18n_schema(no_warnings, url, header, translated):
@pytest.mark.urls(__name__)
def test_i18n_schema_ui(no_warnings):
response = APIClient().get('/api/schema/swagger-ui/?lang=de')
assert b'/api/schema/swagger-ui/?lang=de&script=' in response.content
response = APIClient().get('/api/schema/swagger-ui/?lang=de&script=')
assert b'/api/schema/?lang=de' in response.content
28 changes: 18 additions & 10 deletions tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema
from drf_spectacular.validation import validate_schema
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from drf_spectacular.views import (
SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerSplitView, SpectacularSwaggerView,
)


@extend_schema(responses=OpenApiTypes.FLOAT)
Expand All @@ -25,7 +27,8 @@ def pi(request):
urlpatterns_v2 = [
path('api/v2/pi/', pi),
path('api/v2/pi-fast/', pi),
path('api/v2/schema/swagger-ui/', SpectacularSwaggerView.as_view(), name='swagger-ui'),
path('api/v2/schema/swagger-ui/', SpectacularSwaggerView.as_view(), name='swagger'),
path('api/v2/schema/swagger-ui-alt/', SpectacularSwaggerSplitView.as_view(), name='swagger-alt'),
path('api/v2/schema/redoc/', SpectacularRedocView.as_view(), name='redoc'),
]
urlpatterns_v2.append(
Expand Down Expand Up @@ -95,12 +98,17 @@ def test_spectacular_ui_view(no_warnings, ui):
response = APIClient().get(f'/api/v2/schema/{ui}/')
assert response.status_code == 200
assert response.content.startswith(b'<!DOCTYPE html>')
assert b'"/api/v2/schema/"' in response.content


if ui == 'redoc':
assert b'"/api/v2/schema/"' in response.content
else:
assert b'"/api/v2/schema/swagger-ui/?script="' in response.content
# second request to obtain swagger config (CSP self)
response = APIClient().get('/api/v2/schema/swagger-ui/?script=')
assert response.status_code == 200
assert b'"/api/v2/schema/"' in response.content
@pytest.mark.urls(__name__)
def test_spectacular_swagger_ui_alternate(no_warnings):
# first request for the html
response = APIClient().get('/api/v2/schema/swagger-ui-alt/')
assert response.status_code == 200
assert response.content.startswith(b'<!DOCTYPE html>')
# assert b'"/api/v2/schema/swagger-ui-alt/?script="' in response.content
# second request to obtain js swagger config (CSP self)
response = APIClient().get('/api/v2/schema/swagger-ui-alt/?script=')
assert response.status_code == 200
assert b'"/api/v2/schema/"' in response.content

0 comments on commit 042e8d4

Please sign in to comment.