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

Support RequestDataTooBig exceptions #92

Merged
merged 1 commit into from
Feb 22, 2022
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
40 changes: 40 additions & 0 deletions worf/renderers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.http import HttpResponse, JsonResponse
from django.template.response import TemplateResponse

from worf.conf import settings


def browsable_response(request, response, status_code=200):
template = "worf/api.html"
context = dict(
content=response.content.decode("utf-8"),
response=response,
settings=settings,
)

response = TemplateResponse(request, template, context=context)
response.status_code = status_code
response.render()

return response


def render_response(request, data, status_code=200):
is_browsable = (
settings.WORF_BROWSABLE_API
and "text/html" in request.headers.get("Accept", "")
and request.GET.get("format") != "json"
)

response = (
JsonResponse(data, json_dumps_params=dict(indent=2 if is_browsable else 0))
if data != ""
else HttpResponse()
)

response.status_code = status_code

if is_browsable:
response = browsable_response(request, response, status_code)

return response
1 change: 1 addition & 0 deletions worf/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.conf import settings

DATA_UPLOAD_MAX_MEMORY_SIZE = getattr(settings, "DATA_UPLOAD_MAX_MEMORY_SIZE")

WORF_API_NAME = getattr(settings, "WORF_API_NAME", "Worf API")
WORF_API_ROOT = getattr(settings, "WORF_API_ROOT", "/api/")
Expand Down
33 changes: 8 additions & 25 deletions worf/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@
from django.core.exceptions import (
ImproperlyConfigured,
ObjectDoesNotExist,
RequestDataTooBig,
ValidationError,
)
from django.http import HttpResponse, JsonResponse
from django.template.response import TemplateResponse
from django.template.defaultfilters import filesizeformat
from django.views import View
from django.views.decorators.cache import never_cache
from django.utils.decorators import method_decorator

from worf.conf import settings
from worf.casing import camel_to_snake, snake_to_camel
from worf.exceptions import HTTP_EXCEPTIONS, HTTP404, HTTP422, PermissionsException
from worf.renderers import render_response
from worf.serializers import LegacySerializer
from worf.validators import ValidationMixin

Expand All @@ -41,29 +42,7 @@ def render_to_response(self, data=None, status_code=200):
msg += "render_to_response, nor did its serializer method"
raise ImproperlyConfigured(msg)

is_browsable = (
settings.WORF_BROWSABLE_API
and "text/html" in self.request.headers.get("Accept", "")
and self.request.GET.get("format") != "json"
)

json_kwargs = dict(json_dumps_params=dict(indent=2)) if is_browsable else {}

response = JsonResponse(data, **json_kwargs) if data != "" else HttpResponse()
response.status_code = status_code

if is_browsable:
template = "worf/api.html"
context = dict(
content=response.content.decode("utf-8"),
response=response,
settings=settings,
)
response = TemplateResponse(self.request, template, context=context)
response.status_code = status_code
response.render()

return response
return render_response(self.request, data, status_code)


class AbstractBaseAPI(APIResponse, ValidationMixin):
Expand Down Expand Up @@ -221,5 +200,9 @@ def dispatch(self, request, *args, **kwargs):
return self.render_to_response(
dict(message=HTTP404.message), HTTP404.status
)
except RequestDataTooBig:
self.request._body = self.request.read(None) # prevent further raises
message = f"Max upload size is {filesizeformat(settings.DATA_UPLOAD_MAX_MEMORY_SIZE)}"
return self.render_to_response(dict(message=message), HTTP422.status)
except ValidationError as e:
return self.render_to_response(dict(message=e.message), HTTP422.status)