Skip to content

Commit

Permalink
Add MAINTENANCE_MODE_RESPONSE_TYPE (html or json) setting suppo…
Browse files Browse the repository at this point in the history
…rt. #160
  • Loading branch information
fabiocaccamo committed Dec 11, 2023
1 parent 1e1c900 commit efabcba
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 13 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ MAINTENANCE_MODE_LOGOUT_AUTHENTICATED_USER = False
MAINTENANCE_MODE_REDIRECT_URL = None
```

```python
# the type of the response returned during maintenance mode, can be either "html" or "json"
MAINTENANCE_MODE_RESPONSE_TYPE = "html"
```

```python
# the template that will be shown by the maintenance-mode page
MAINTENANCE_MODE_TEMPLATE = "503.html"
Expand Down
58 changes: 45 additions & 13 deletions maintenance_mode/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.conf import settings
from django.contrib.auth import logout
from django.core.exceptions import ImproperlyConfigured
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.urls import NoReverseMatch, Resolver404, resolve, reverse
from django.utils.cache import add_never_cache_headers
Expand All @@ -13,15 +14,8 @@
from maintenance_mode.utils import get_client_ip_address


def get_maintenance_response(request):
"""
Return a '503 Service Unavailable' maintenance response.
"""
if settings.MAINTENANCE_MODE_REDIRECT_URL:
return redirect(settings.MAINTENANCE_MODE_REDIRECT_URL)

def get_maintenance_response_context(request):
context = {}

if settings.MAINTENANCE_MODE_GET_TEMPLATE_CONTEXT:
try:
get_request_context_func = import_string(
Expand All @@ -34,19 +28,57 @@ def get_maintenance_response(request):
) from error

context = get_request_context_func(request=request)
return context


def get_maintenance_response(request):
"""
Return a '503 Service Unavailable' HTML or JSON response based on user preference.
"""
if settings.MAINTENANCE_MODE_REDIRECT_URL:
return redirect(settings.MAINTENANCE_MODE_REDIRECT_URL)

response = None
response_type = settings.MAINTENANCE_MODE_RESPONSE_TYPE
if response_type == "html":
response = get_maintenance_html_response(request)
elif response_type == "json":
response = get_maintenance_json_response(request)
else:
raise ImproperlyConfigured(
"settings.MAINTENANCE_MODE_RESPONSE_TYPE value must be 'html' or 'json'."
)

kwargs = {"context": context}
if settings.MAINTENANCE_MODE_RETRY_AFTER:
response["Retry-After"] = settings.MAINTENANCE_MODE_RETRY_AFTER

add_never_cache_headers(response)
return response


def get_maintenance_html_response(request):
"""
Return an HTML response for maintenance.
"""
context = get_maintenance_response_context(request)
response = render(
request,
settings.MAINTENANCE_MODE_TEMPLATE,
status=settings.MAINTENANCE_MODE_STATUS_CODE,
**kwargs,
context=context,
)
return response

if settings.MAINTENANCE_MODE_RETRY_AFTER:
response["Retry-After"] = settings.MAINTENANCE_MODE_RETRY_AFTER

add_never_cache_headers(response)
def get_maintenance_json_response(request):
"""
Return a JSON response for maintenance.
"""
context = get_maintenance_response_context(request)
response = JsonResponse(
context,
status=settings.MAINTENANCE_MODE_STATUS_CODE,
)
return response


Expand Down
3 changes: 3 additions & 0 deletions maintenance_mode/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
if not hasattr(settings, "MAINTENANCE_MODE_REDIRECT_URL"):
settings.MAINTENANCE_MODE_REDIRECT_URL = None

if not hasattr(settings, "MAINTENANCE_MODE_RESPONSE_TYPE"):
settings.MAINTENANCE_MODE_RESPONSE_TYPE = "html"

if not hasattr(settings, "MAINTENANCE_MODE_STATE_BACKEND"):
settings.MAINTENANCE_MODE_STATE_BACKEND = (
"maintenance_mode.backends.LocalFileBackend"
Expand Down
21 changes: 21 additions & 0 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.core.management import call_command
from django.core.management.base import CommandError
from django.http import HttpResponse, JsonResponse
from django.test import (
Client,
RequestFactory,
Expand Down Expand Up @@ -1000,6 +1001,26 @@ def test_middleware_get_template_context(self):
val = response.context.get("TEST_MAINTENANCE_MODE_GET_TEMPLATE_CONTEXT", False)
self.assertFalse(val)

def test_middleware_response_type(self):
self.__reset_state()

settings.MAINTENANCE_MODE = True
request = self.__get_anonymous_user_request("/")

settings.MAINTENANCE_MODE_RESPONSE_TYPE = "none"
with self.assertRaises(ImproperlyConfigured):
self.middleware.process_request(request)

settings.MAINTENANCE_MODE_RESPONSE_TYPE = "json"
response = self.middleware.process_request(request)
self.assertMaintenanceResponse(response)
self.assertTrue(isinstance(response, JsonResponse))

settings.MAINTENANCE_MODE_RESPONSE_TYPE = "html"
response = self.middleware.process_request(request)
self.assertMaintenanceResponse(response)
self.assertTrue(isinstance(response, HttpResponse))


class TestOverrideMaintenanceMode(SimpleTestCase):
"""
Expand Down

0 comments on commit efabcba

Please sign in to comment.