Skip to content

Commit

Permalink
fix(handlers): Allow returning Response[None] from head route handl…
Browse files Browse the repository at this point in the history
…ers (#3641)

Allow returning Response[None] from head route handlers
  • Loading branch information
provinzkraut authored Jul 23, 2024
1 parent 8c4c15b commit ffaf561
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
10 changes: 5 additions & 5 deletions litestar/handlers/http_handlers/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from litestar.openapi.spec import Operation
from litestar.response.file import ASGIFileResponse, File
from litestar.types import Empty, TypeDecodersSequence
from litestar.types.builtin_types import NoneType
from litestar.utils import is_class_and_subclass

from ._utils import is_empty_response_annotation
from .base import HTTPRouteHandler

if TYPE_CHECKING:
Expand Down Expand Up @@ -590,11 +590,11 @@ def _validate_handler_function(self) -> None:
super()._validate_handler_function()

# we allow here File and File because these have special setting for head responses
return_annotation = self.parsed_fn_signature.return_type.annotation
field_definition = self.parsed_fn_signature.return_type
if not (
return_annotation in {NoneType, None}
or is_class_and_subclass(return_annotation, File)
or is_class_and_subclass(return_annotation, ASGIFileResponse)
is_empty_response_annotation(field_definition)
or is_class_and_subclass(field_definition.annotation, File)
or is_class_and_subclass(field_definition.annotation, ASGIFileResponse)
):
raise ImproperlyConfiguredException(
f"{self}: Handlers for 'HEAD' requests must not return a value. Either return 'None' or a response type without a body."
Expand Down
23 changes: 21 additions & 2 deletions tests/unit/test_handlers/test_http_handlers/test_head.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from pathlib import Path
from typing import Generic, TypeVar

import pytest

from litestar import HttpMethod, Litestar, head
from litestar import HttpMethod, Litestar, Response, head
from litestar.exceptions import ImproperlyConfiguredException
from litestar.response.file import ASGIFileResponse, File
from litestar.status_codes import HTTP_200_OK
Expand All @@ -26,7 +27,25 @@ def test_head_decorator_raises_validation_error_if_body_is_declared() -> None:
def handler() -> dict:
return {}

handler.on_registration(Litestar())
Litestar(route_handlers=[handler])


def test_head_decorator_none_response_return_value_allowed() -> None:
# https://github.com/litestar-org/litestar/issues/3640
T = TypeVar("T")

class MyResponse(Generic[T], Response[T]):
pass

@head("/1")
def handler() -> Response[None]:
return Response(None)

@head("/2")
def handler_subclass() -> MyResponse[None]:
return MyResponse(None)

Litestar(route_handlers=[handler, handler_subclass])


def test_head_decorator_raises_validation_error_if_method_is_passed() -> None:
Expand Down

0 comments on commit ffaf561

Please sign in to comment.