3.x Changelog¶
3.0.0¶
Released: 2364-01-27Features¶
- Default
copy_scopetoTruefor ASGI handlers#breaking Every
asgihandler, mounted or not, now receives a copy of the ASGIscope, so the wrapped application can no longer add, replace or remove top-level scope keys seen by the outer application. The default wasNone, which passed the original scope through, warned at registration and warned again when the wrapped application mutated the scope; both warnings are gone.The copy is shallow, so nested values such as
scope["state"]are still shared with the outer scope.Set
copy_scope=Falsewhere the wrapped application is meant to communicate with the outer application through the scope, for example by writingscope["user"]for outer middleware to read, or by callingRequest.set_sessionorRequest.clear_session. All of these now fail silently.References: https://github.com/litestar-org/litestar/pull/5164
- Remove support for declaring
DTOFieldvia Pydantic’sField.extra#breaking Declaring a
DTOFieldthrough Pydantic’sField.extra, that isField(**dto_field("read-only")), is no longer supported. The mark was already ignored in 2.x and only emitted a deprecation warning. Remove the declaration and useAnnotated[int, DTOField(mark="read-only")]instead; leaving it in place can make OpenAPI schema generation fail.References: https://github.com/litestar-org/litestar/pull/5163
- Require “reserved kwargs” to be declared with their type#breaking
Declaring the “reserved kwargs”
body,cookies,data,headers,query,request,scopeandsocketwithout the type listed below, or with a different one, raisesImproperlyConfiguredExceptionat startup.For this, add the types
RawBody,QueryParamsandRequestCookies, and the body markerRequestBody, which declares a body of the default media type,application/json.Parameter
Type
bodycookiesdataA body marker, e.g.
JSONBodyorRequestBodyheadersqueryrequestThe request class configured for the handler, or one of its base classes, e.g.
RequestscopesocketThe websocket class configured for the handler, or one of its base classes, e.g.
WebSocketheadersreceives the request’sHeaders. Before,headers: dict[str, str]received adictandheaders: Headersfailed validation with a400 - Bad Request.In route handlers,
cookies,headers,queryandscopecan also be accessed through the request, e.g.request.headers.See also
References: https://github.com/litestar-org/litestar/pull/5154
- Remove support for implicitly declared request parameters#breaking
Remove the deprecated implicit request parameter declaration. All request parameters must now be explicitly marked (e.g. with
FromQuery).Deprecated
Use instead
def h(name: str)(implicit query parameter)def h(name: FromQuery[str])def h(user_id: int)(implicit path parameter)def h(user_id: FromPath[int])Annotated[str, Parameter(query="alias")]Annotated[str, QueryParameter(name="alias")]Annotated[str, Parameter(header="X-API-KEY")]Annotated[str, HeaderParameter(name="X-API-KEY")]Annotated[str, Parameter(cookie="session")]Annotated[str, CookieParameter(name="session")]name: str = Parameter(...)(default-value style)name: Annotated[str, QueryParameter(...)]See also
References:
- Add support for
leewayparameter in JWT security backends#breaking Add support for
leewayparameter in JWT security backends, which allows set a number of potential seconds as a clock error for expired tokens.Token.decodeandToken.decode_payloadnow take aleewayargument. Custom token classes overriding either method must accept it and forward tosuper(), otherwise decoding raisesTypeError.References: https://github.com/litestar-org/litestar/issues/4584, https://github.com/litestar-org/litestar/pull/5037
- Return HTTP 413 when the multipart form part limit is exceeded#breaking
Exceeding the configured multipart form part limit now returns
413 Request Entity Too Largeinstead of400 Bad Request.References: https://github.com/litestar-org/litestar/issues/4439, https://github.com/litestar-org/litestar/pull/4990
- Remove the RapiDoc OpenAPI UI plugin#breaking
The
RapidocRenderPluginhas been removed due to lack of upstream maintenance.Applications using
RapidocRenderPluginshould migrate to another bundled UI plugin, such asScalarRenderPlugin(the default),SwaggerRenderPlugin,RedocRenderPluginorStoplightRenderPlugin.References: https://github.com/litestar-org/litestar/pull/4977
- Migrate
CSRFMiddlewaretoASGIMiddleware#breaking CSRFMiddlewarehas been moved from the legacyMiddlewareProtocolbase toASGIMiddleware, as part of migrating all built-in middleware off the legacy bases. It now lives inlitestar.middleware._internal. This removes thelitestar.middleware.csrfmodule, including thegenerate_csrf_tokenandgenerate_csrf_hashhelpers, from the public API.Applications that configure CSRF protection through
CSRFConfigare unaffected, since Litestar constructs the middleware itself, via afrom_configclassmethod on the middleware.Two behavioural changes for excluded routes:
excludepatterns are now matched against the handler’s path template (e.g./user/{user_id:int}) at startup, instead of the request path (e.g./user/1) at runtime. Patterns targeting literal paths keep working; patterns written to match expanded path parameters must be rewritten against the template.Handlers excluded via
excludeorexclude_from_csrfnow bypass the middleware entirely at startup rather than per request.
References: https://github.com/litestar-org/litestar/issues/4009, https://github.com/litestar-org/litestar/pull/4998
- Migrate
ResponseCacheMiddlewaretoASGIMiddleware#breaking ResponseCacheMiddlewarehas been moved from the legacyAbstractMiddlewarebase toASGIMiddleware, as part of migrating all built-in middleware off the legacy bases. It now lives inlitestar.middleware._internal, removing it from the public API.Note
The move into
litestar.middleware._internaldoes not affect usage: the middleware was only ever applied internally by Litestar to begin with.Applications that configure response caching through
ResponseCacheConfigand the handler-levelcacheargument are unaffected – Litestar constructs the middleware itself.Code composing the middleware directly into an ASGI stack must drop the
appargument, pass the settings as keyword arguments rather than aResponseCacheConfig, and apply the instance to the next ASGI app:# before middleware = ResponseCacheMiddleware(app=next_app, config=response_cache_config) # after middleware = ResponseCacheMiddleware( default_expiration=response_cache_config.default_expiration, key_builder=response_cache_config.key_builder, store=response_cache_config.store, cache_response_filter=response_cache_config.cache_response_filter, ) asgi_app = middleware(next_app)
Since
ASGIMiddleware.__call__returns a closure rather than the middleware instance, a middleware stack can no longer be introspected by walking the.appattribute of each layer.References: https://github.com/litestar-org/litestar/issues/4009, https://github.com/litestar-org/litestar/pull/4953
- Migrate
CORSMiddlewaretoASGIMiddleware#breaking CORSMiddlewarehas been moved from the legacyAbstractMiddlewarebase toASGIMiddleware, as part of migrating all built-in middleware off the legacy bases.Applications that configure CORS through
CORSConfigare unaffected – Litestar constructs the middleware itself.Code instantiating the middleware directly must drop the
appargument, pass the settings as keyword arguments rather than aCORSConfig, and apply the instance to the next ASGI app:# before middleware = CORSMiddleware(app=next_app, config=cors_config) # after middleware = CORSMiddleware(allow_origins=cors_config.allow_origins, ...) asgi_app = middleware(next_app)
The settings are copied on construction, so mutating
CORSConfigafter the application has been created no longer affects the middleware.Since
ASGIMiddleware.__call__returns a closure rather than the middleware instance, a middleware stack can no longer be introspected by walking the.appattribute of each layer.References: https://github.com/litestar-org/litestar/issues/4009, https://github.com/litestar-org/litestar/pull/4952
- Move
httpxto thetestingextra#breaking httpx, used by the test clients, has been moved from the default dependencies to thelitestar[testing]extra. It remains included inlitestar[full].Importing anything from
litestar.testingwithout the extra installed now raises aMissingDependencyExceptionnaming the extra to install.See also
References: https://github.com/litestar-org/litestar/pull/4950
- Require
rich-click>=1.9#breaking The
litestar[cli]extra now requiresrich-click>=1.9.rich-clickwas previously capped at<1.9, which silently disabled the CLI’sstar-boxtheme: the underlyingthemeoption only exists from 1.9 onwards, and assigning an unknown setting is ignored rather than raising.The CLI configuration has been migrated off the options 1.9 deprecates (
use_markdown/use_rich_markupin favour oftext_markup, andshow_metavars_column/append_metavars_helpin favour ofoptions_table_column_types/options_table_help_sections).The layout of the help output is preserved: option tables keep the long form in the first column, the
*marker on required parameters, and the metavar appended directly after the help text. Colours do change, as thestar-boxtheme now takes effect for the first time.This only affects applications that additionally pin
rich-click<1.9themselves.See also
References: https://github.com/litestar-org/litestar/pull/4951
- Move
click,richandrich-clickto thecliextra#breaking click,richandrich-click, which power the CLI, have been moved from the default dependencies to thelitestar[cli]extra. They remain included inlitestar[standard]andlitestar[full].Installing
litestaron its own therefore no longer provides thelitestarcommand. Invoking it without the extra now raises aMissingDependencyExceptionnaming the extra to install.See also
References: https://github.com/litestar-org/litestar/pull/4949
- Remove deprecated
litestar.contribnamespace#breaking Remove the deprecated
litestar.contribnamespace. Integrations previously available from this namespace have moved to their replacement modules.References: https://github.com/litestar-org/litestar/issues/4720
- Remove deprecated declaration of metadata through default values#breaking
Remove declaring parameter and body metadata through default values and setting defaults inside markers.
The
defaultkeyword has been removed fromParameterandBody, along with the underlyingKwargDefinition.defaultfield. Passing it now raises aTypeError.Using a
QueryParameter/HeaderParameter/PathParameter/CookieParameterorBodymarker as a parameter default value (for exampledata: Foo = Body(...)orparam: int = QueryParameter(...)) now raises an exception
Migration
If metadata is declared on the marker, move the marker into
Annotated:data: Foo = Body(min_items=2)becomesdata: Annotated[Foo, Body(min_items=2)]param: int = QueryParameter(gt=1)becomesparam: Annotated[int, QueryParameter(gt=1)]
For the unconstrained case the dedicated markers can be used as a shorthand, e.g.
JSONBody[Foo],MsgPackBody[Foo],MultipartBody[Foo]orURLEncodedBody[Foo]for bodies, andFromQuery[int],FromHeader[int],FromCookie[int]orFromPath[int]for parameters.Hoist defaults set inside
Annotatedinto the parameter default:param: Annotated[int, QueryParameter(default=5)]becomesparam: Annotated[int, QueryParameter(...)] = 5.
See also
References: https://github.com/litestar-org/litestar/pull/4819
- Remove deprecated
params.Dependencyandparams.DependencyKwarg#breaking Remove
params.Dependencyandparams.DependencyKwargthat were deprecated in2.23.0.Migration
Replace
foo: int = Dependency()withfoo: NamedDependency[int]Replace
foo: Annotated[int, Dependency(default=1)]by hoisting the default into the parameter default:foo: NamedDependency[int] = 1Replace
foo: Annotated[int, Dependency(skip_validation=True)withfoo: NamedDependency[SkipValidation[int]]
References: https://github.com/litestar-org/litestar/pull/4818
- Drop support for Pydantic 1#breaking
Drop support for Pydantic 1.
Pydantic 1 is no longer supported or tested against. No changes required for applications already using Pydantic 2. Applications using Pydantic 1 or a mix between 1 and 2 should upgrade to Pydantic 2.
References:
- Add
ping_intervaltoServerSentEventfor keepalive pings# Added optional
ping_intervalparameter toServerSentEventthat sends SSE comment keepalive pings at the specified interval to prevent connection timeouts from reverse proxies or clients.References: https://github.com/litestar-org/litestar/issues/4082, https://github.com/litestar-org/litestar/pull/4623
- Remove logging config and related constructs#breaking
Remove Litestar’s logging configuration, and related modules. In particular, the following have been removed:
Litestar.logging_configparameterLitestar.loggerattributeLitestar.get_loggermethodAppConfig.logging_configattributeASGIConnection.loggerpropertylitestar.loggingmodulelitestar.plugins.structlogmodulelitestar.middleware.lgging.LoggingMiddlewareConfigclass
Aside from debugging, there is only one place where Litestar logs, which is
LoggingMiddleware, which has been changed to accept a logger directly.litestar.middleware.lgging.LoggingMiddlewareConfighas also been removed, withLoggingMiddlewarenow accepting all configuration arguments directly.Users that have previously relied on Litestar to configure logging, can simply use the standard logging configuration provided by their logging library of choice.
See also
References: https://github.com/litestar-org/litestar/issues/2858,, https://github.com/litestar-org/litestar/issues/3913,, https://github.com/litestar-org/litestar/issues/3455, https://github.com/litestar-org/litestar/pull/4615
- Remove default exception handler for all unhandled exceptions#breaking
Remove the default exception handler for all unhandled exceptions. Unhandled exceptions will now be re-raised, for the server to handle. “Unhandled exceptions” in this context means any exception for which no custom exception handler exist, and that does not derive from
LitestarExceptionorHTTPException.Important
Your application’s runtime behaviour won’t change in terms of if exceptions get handled. The main difference will be that, for an unhandled exception, it will be the ASGI server that creates a
500 - Internal Server Errorresponse, instead of LitestarReferences: https://github.com/litestar-org/litestar/pull/4610
- Remove all SQLAlchemy modules in favor of direct advanced-alchemy imports#breaking
Remove all SQLAlchemy functionality from Litestar. Both
litestar.contrib.sqlalchemyandlitestar.plugins.sqlalchemymodules have been completely removed. Users must now import directly fromadvanced_alchemy.extensions.litestar.Migration: -
from litestar.contrib.sqlalchemy import X→from advanced_alchemy.extensions.litestar import X-from litestar.plugins.sqlalchemy import Y→from advanced_alchemy.extensions.litestar import YThis completes the separation of concerns, with advanced-alchemy being the sole provider of SQLAlchemy integration for Litestar.
References: https://github.com/litestar-org/litestar/pull/4340
- Remove deprecated
litestar.contrib.prometheusmodule#breaking Remove the deprecated
litestar.contrib.prometheusmodule. Code still using imports from this module should switch to usinglitestar.plugins.prometheus.References: https://github.com/litestar-org/litestar/issues/4305, https://github.com/litestar-org/litestar/pull/4328
- Make
AsyncTestClientasync-native#breaking Re-implement
AsyncTestClientto be async-native, i.e. use the currently running event loop to run the application, instead of running a separate event loop in a new thread. Additionally, a newAsyncWebSocketTestSessionhas been introduced, providing an async testing utility for WebSockets.To ensure consisten behaviour across
TestClientandAsyncTestClient, all testing utilities have been rewritten to be async first, with their synchronous counterparts proxying calls to the async implementation, which they run internally within a dedicated thread + event loop.References: https://github.com/litestar-org/litestar/issues/1920, https://github.com/litestar-org/litestar/pull/4291
- Remove deprecated plugin properties from
Litestar#breaking Remove deprecated
<plugin_type>_pluginsproperties fromLitestar.Removed
Use instead
Litestar.openapi_schema_pluginsLitestar.plugins.openapi_schemaLitestar.cli_pluginsLitestar.plugins.cliLitestar.serialization_pluginsLitestar.serialization.cliReferences: https://github.com/litestar-org/litestar/pull/4297
- Remove deprecated
allow_reservedandallow_empty_valueproperty fromResponseHeaderandOpenAPIHeader#breaking Remove the deprecated properties
allow_reservedandallow_empty_valuefromResponseHeaderandOpenAPIHeader.References: https://github.com/litestar-org/litestar/pull/4299
- Remove deprecated
traceback_line_limitparameter ofLoggingConfig#breaking The
traceback_line_limitparameter oflitestar.logging.config.LoggingConfighas been removed. This parameter had no effect since version2.9.0, so it can be removed safely from applications without any change in behaviour.References: https://github.com/litestar-org/litestar/pull/4300
- Remove deprecated
litestar.middleware.corsmodule#breaking Remove the deprecated
litestar.middleware.corsmodule andlitestar.middleware.cors.CORSMiddleware. To configure the CORS middleware, useCORSConfig.References: https://github.com/litestar-org/litestar/pull/4309
- Remove deprecated
encoded_headersparameter from ASGI response classes andto_asgi_responsemethods#breaking The deprecated
encoded_headersparameter has been removed from the following clases:Existing code still using
encoded_headersshould be migrated to using theheadersparameter instead.References: https://github.com/litestar-org/litestar/pull/4311
- Remove deprecated
litestar.contrib.htmxmodule#breaking Remove the deprecated
litestar.contrib.htmxmodule. Code still using imports from this module should switch to usinglitestar_htmx.Install it via
litestar[htmx]extra.References: https://github.com/litestar-org/litestar/issues/4303, https://github.com/litestar-org/litestar/pull/4316
- Remove deprecated
LitestarType#breaking Remove the deprecated
litestar.types.internal_types.LitestarTypetype alias. In its stead,type[Litestar]can be used.References: https://github.com/litestar-org/litestar/pull/4312
- Remove deprecated
TemplateContext#breaking Remove the deprecated
litestar.template.base.TemplateContexttype. Its usages should be replaced withcollections.abc.Mapping.References: https://github.com/litestar-org/litestar/pull/4313
- Remove deprecated
ASGIResponse.encoded_headersproperty#breaking Remove the deprecated
ASGIResponse.encoded_headersproperty. Instead,encode_headers()should be used.References: https://github.com/litestar-org/litestar/pull/4314
- Remove deprecated
pydantic_get_unwrapped_annotation_and_type_hints#breaking Remove the deprecated
pydantic_get_unwrapped_annotation_and_type_hintsfunction.References: https://github.com/litestar-org/litestar/pull/4315
- Remove deprecated
litestar.contrib.attrsmodule#breaking Remove the deprecated
litestar.contrib.attrsmodule. Code still using imports from this module should switch to usinglitestar.plugins.attrs.References: https://github.com/litestar-org/litestar/issues/4302, https://github.com/litestar-org/litestar/pull/4322
- Remove deprecated
litestar.contrib.jwtmodule#breaking Remove the deprecated
litestar.contrib.jwtmodule. Code still using imports from this module should switch to usinglitestar.security.jwt.References: https://github.com/litestar-org/litestar/issues/4304, https://github.com/litestar-org/litestar/pull/4333
- Remove deprecated
litestar.contrib.repositorymodule#breaking Remove the deprecated
litestar.contrib.repositorymodule. Code still using imports from this module should switch to usinglitestar.repository.References: https://github.com/litestar-org/litestar/issues/4307, https://github.com/litestar-org/litestar/pull/4337
- Remove deprecated
litestar.contrib.pydanticmodule#breaking Remove the deprecated
litestar.contrib.pydanticmodule. Code still using imports from this module should switch to usinglitestar.plugins.pydantic.References: https://github.com/litestar-org/litestar/issues/4306, https://github.com/litestar-org/litestar/pull/4339
- Remove deprecated module
litestar/contrib/minijnja#breaking Remove the deprecated module
litestar.contrib.minijnja. This module was created with a typo in its name (minijnja instead of minijinja). Insteadlitestar.contrib.minijinjashould be used.References: https://github.com/litestar-org/litestar/issues/4357, https://github.com/litestar-org/litestar/pull/4357
- Add
round_tripparameter toPydanticPlugin# New
round_trip: boolparameter toPydanticPluginallows serializing types likepydanctic.Jsoncorrectly.References: https://github.com/litestar-org/litestar/issues/4349, https://github.com/litestar-org/litestar/pull/4350
- Remove deprecated
litestar.contrib.minijinja.minijinja_from_statefunction#breaking Remove the deprecated
litestar.contrib.minijinja.minijinja_from_statefunction. Instead use a callable that receives the minijinjaStateobject as first argument.References: https://github.com/litestar-org/litestar/issues/4356, https://github.com/litestar-org/litestar/pull/4355
- Remove deprecated
litestar.contrib.piccolomodule#breaking Use
litestar[piccolo]extra installation target andlitestar_piccoloplugin instead: https://github.com/litestar-org/litestar-piccoloReferences: https://github.com/litestar-org/litestar/issues/4364, https://github.com/litestar-org/litestar/pull/4363
- Move
litestar.contrib.opentelemetrytolitestar.plugins.opentelemetryand add upstream parity#breaking Move the OpenTelemetry integration from
litestar.contrib.opentelemetrytolitestar.plugins.opentelemetry. Code still using imports from the old module should switch to the new path.OpenTelemetryConfighas been brought in line with the upstreamopentelemetry.instrumentation.asgi.OpenTelemetryMiddlewareconfiguration, addingclient_request_hook_handler,client_response_hook_handler,tracer,exclude,exclude_opt_key,exclude_urls_env_key,exclude_spans,http_capture_headers_server_request,http_capture_headers_server_response, andhttp_capture_headers_sanitize_fields.Also fixes a
KeyError: 'route_handler'raised on every request whenexclude_opt_keywas set, and corrects theOpenTelemetryHookHandlersignature to accept the span, ASGI scope, and ASGI message as documented by upstream.References: https://github.com/litestar-org/litestar/issues/4466,, https://github.com/litestar-org/litestar/issues/4468, https://github.com/litestar-org/litestar/pull/4691
- Zero cost excluded middlewares#breaking
Middlewares inheriting from
ASGIMiddlewarewill now have zero runtime cost when they are excluded e.g. via thescopeorexclude_opt_keyoptions.Previously, the base middleware was always being invoked for every request, evaluating the exclusion criteria, and then calling the user defined middleware functions. If a middleware had defined
scopes = (ScopeType.HTTP,), it would still be called for every request, regardless of the scope type. Only for requests with the typeHTTP, it would then call the user’s function.Note
This behaviour is still true for the legacy
AbstractMiddlewareWith zero cost exclusion, the exclusion is being evaluated statically. At app creation time, when route handlers are registered and their middleware stacks are being built, a middleware that is to be excluded will simply not be included in the stack.
Note
Even though this change is marked as breaking, no runtime behaviour difference is expected. Some test cases may break though if they relied on the fact that the middleware wrapper created by
ASGIMiddlewarewas always being calledReferences:
- Support for
typing.ReadOnlyin typed dict schemas# Support unwrapping
ReadOnlytype in schemas like:from typing import ReadOnly, TypedDict class User(TypedDict): id: ReadOnly[int]
typing_extensions.ReadOnlyshould be used for python versions <3.13.References: https://github.com/litestar-org/litestar/issues/4423, https://github.com/litestar-org/litestar/pull/4424
- Add
should_bypass_for_scopetoASGIMiddlewareto allow excluding middlewares dynamically# Add a new attribute
should_bypass_for_scope; A callable which takes in aScopeand returns a boolean to indicate whether to bypass the middleware for the current request.References: https://github.com/litestar-org/litestar/pull/4441
Bugfixes¶
- DI: Correctly set Pydantic dependency fields as required without a default#
Fix a bug, causing a Pydantic model used as a dependency to fail at startup with
Missing declaration for parameterfor each of its fields without a marker, sincePydanticDIPluginmarked them as dependencies only in the signature, not in the type hints used by the rest of the machinery.References: https://github.com/litestar-org/litestar/pull/5195
- DI: Correctly set
msgspec.Structdependency fields as required without a default# Fix a bug that would implicitly give a field of an
msgspec.Structused as a dependency a default ofmsgspec.NODEFAULTand mark it as optional. Struct fields without a default are now correctly marked as required.References: https://github.com/litestar-org/litestar/pull/5194
- Parse every
cookieheader of a request#breaking Only the first
cookieheader was parsed intocookies. Over HTTP/2 and HTTP/3 the header may repeat, and browsers send one per cookie, so every cookie but those in the first header went missing. Allcookieheaders are now parsed, joined with the"; "delimiter RFC 9113 and RFC 9114 prescribe.A cookie name sent more than once now keeps its first value, where it kept its last one before, following the RFC 6265 ordering that serialises the cookie of the longer path first. Scope a cookie holding a session or a CSRF token with the
__Host-prefix so that a cookie of the same name, set under a longer path, cannot take precedence over it.cookiesofLoggingMiddleware’s response log likewise holds the first of severalset-cookieheaders of one name, not the last.References: https://github.com/litestar-org/litestar/issues/5177
- Restore a session split across several cookies over HTTP/2 and HTTP/3#
A session too large for one cookie is stored across several, named
session-0,session-1and so on. Over HTTP/2 and HTTP/3 only the chunks carried by the firstcookieheader were read, andClientSideSessionBackendyields an empty session when it cannot decode the value in full, so such a session was silently dropped and the user logged out. Every chunk is now read.References: https://github.com/litestar-org/litestar/issues/5177
- Send repeated headers separately from the test client#breaking
The test client merged headers of the same name into one comma-joined header, which is invalid for
cookie, and left a request carrying a repeated header impossible to simulate. Repeated headers now reach the application as they were given, on requests and onwebsocket_connect(), which dropped all but the last of them.A test passing a header of the same name twice is affected: the application now receives the two values it was given, rather than one comma-joined value. Header values are also passed on as the bytes they were given in, where they were decoded and re-encoded as UTF-8 before.
References: https://github.com/litestar-org/litestar/issues/5177
- Fix
Optional/Any+required=False+ without default parameters receivingEmpty#breaking Fix a bug that would cause a request parameter typed
OptionalorAny, and declared without a default and annotated asrequired=Falseto receive theEmptysentinel when that parameter was missing from the request.A parameter annotated
required=Falsethat is consumed by any handler or dependency, and does not have a default, now raisesImproperlyConfiguredExceptionat startup.This includes a marker for a parameter also declared as a layer parameter with
required=False. Layer parameters that are not consumed are not affected by this.References: https://github.com/litestar-org/litestar/pull/5185
- Fix
ModuleNotFoundErrorwhen Pydantic or attrs are not installed# Fix a bug that would raise
ModuleNotFoundErrorwhen attrs or Pydantic were not installed.References: https://github.com/litestar-org/litestar/issues/5142
- ServerSideSessionBackend: Prevent storing empty sessions and session cookies for every request#
Fix a bug where
ServerSideSessionBackendwould store an empty session under a new session ID and set a session cookie for every request, even when that request did not have a session cookie attached.The fixed backend will now only store a session if the client has a session cookie set. Empty sessions for a request with a session cookie will now also be deleted reliably.
References: https://github.com/litestar-org/litestar/issues/5182, https://github.com/litestar-org/litestar/pull/5172
- Apply
allow_symlinks_outside_directory=Falseto every part of a static file’s path# Fix a bug that would resolve symlinks only for the directory path, not the file path, when
allow_symlinks_outside_directory=False. The whole path is now always resolved.References: https://github.com/litestar-org/litestar/pull/5181
- Match mounted ASGI apps on path segments#breaking
A mount matched any path merely starting with its path string, so a mount on
/adminserved/administrator, handing the mounted appistrator/as its path. A mount now matches only its own path and sub-paths of it,/adminand/admin/..., and/still mounts everything that no more specific mount claims.Of several mounts matching a path, the longest one now receives the request, so a mount nested under another, e.g.
/admin/innerunder/admin, is reachable. This also fixes mounts sharing a prefix shadowing one another, and mount paths containing regex metacharacters, which raised500 - Internal Server Erroror failed application startup.An application relying on a mount absorbing sibling paths that merely share its prefix now receives
404 - Not Foundfor them. Mount the application one path segment higher, or declare the sibling path as a further path of the mount, e.g.@asgi(["/admin", "/administrator"], is_mount=True).References: https://github.com/litestar-org/litestar/issues/5173, https://github.com/litestar-org/litestar/pull/5178
- Declare
socketin the original signature of awebsocket_streamhandler# A
websocket_streamhandler whose function takes nosocketparameter adds one to itsparsed_fn_signature, but only to itsparameters, so itsoriginal_signaturelacked a parameter itsparametersdeclared. It now declaressocketin both.References: https://github.com/litestar-org/litestar/pull/5161
- Read constraint metadata on
dataas on any other parameter# A
dataparameter annotated with metadata, e.g.data: Annotated[int, annotated_types.Gt(0)], was interpreted as a request body without a body marker, which got around the check ofdatabeing missing a markerReferences: https://github.com/litestar-org/litestar/pull/5157
- Only read parameters marked as path parameters from the path#breaking
A parameter whose name matched a path segment was read from the path even when it was marked with
FromQuery,FromHeader,FromCookieor the correspondingParameterkwarg, and was documented as a path parameter. Such a parameter is now read from, and documented at, the location it is marked with.A parameter named like a path segment that declares no location, the deprecated inferred path parameter style, now raises
ImproperlyConfiguredExceptionwhen the application is created. Declare it withFromPath.References: https://github.com/litestar-org/litestar/pull/5128
- Fix
TypeErrorwhen generating a schema for a union of enums# Annotating a handler with a union whose members are all enums (e.g.
Color | Size) crashed schema generation withTypeError: issubclass() arg 1 must be a class, as the union was dispatched to the enum schema handler. Such unions are now documented as aoneOfwith a component schema per enum.References: https://github.com/litestar-org/litestar/pull/4997
- Stop caching responses of handlers that do not enable caching#
ResponseCacheMiddlewareis applied per route, so a handler that never setcachestill had its responses written to the store when it shared a path with a handler that did – for example aPOSThandler on a path whoseGEThandler setscache=True. Those entries were written on every request, without an expiry, and were never read back, since responses are only served from the cache for handlers that enable it.The middleware now passes such requests through untouched.
References: https://github.com/litestar-org/litestar/pull/4953
- Harden the PsycoPg channels listener#
Serialize subscription changes and consume notifications in a background task so dynamic
LISTENandUNLISTENoperations no longer contend with the listener. Psycopg 3.2.4 or newer is now required for development and documentation builds.References:
- Fix OpenAPI schema incorrectly marking nullable required fields as not required#
Fields typed as
T | None(nullable) without a default value are now correctly included in the OpenAPI schema’srequiredarray. Previously, Litestar conflated nullability (the type can beNone) with optionality (having a default value), causing the generated schema to diverge from the OpenAPI 3.1.0 specification.This affected all model types: dataclasses, msgspec Structs, attrs classes, and Pydantic models. For example, a field
name: int | Nonewith no default was previously excluded fromrequired; it is now correctly included.Runtime request validation behavior is unchanged — nullable parameters without defaults were already enforced as required at the validation layer.
References: https://github.com/litestar-org/litestar/issues/4673, https://github.com/litestar-org/litestar/pull/4687
- Fix
raise_server_exceptionsflag in test clients# Fix the
raise_server_exceptions. This flag has been non-functional (i.e. did not change the behaviour at all) since version 1. This is now fixed, and unhandled exceptions will be re-raised by the test clientReferences: https://github.com/litestar-org/litestar/pull/4610
- Fix swallowing of unhandled exceptions in WebSocket client#
Fix a bug that could lead to unhandled exceptions raised within websocket handlers, and not derived from
LitestarExceptionorHTTPExceptionto be silently swallowed. This would lead to a closing of the WebSocket connection without any indication of an exceptionReferences: https://github.com/litestar-org/litestar/pull/4610
- Change
OptionaltoNotRequiredfor pydantic fields withdefault_factory# Now, in the OpenAPI schema,
pydanticfields withdefault_factoryare displayed as non-null and not required. Previously, this fields was nullable and not required.References: https://github.com/litestar-org/litestar/issues/4294, https://github.com/litestar-org/litestar/pull/4347
- Fix KeyError when ClassVar exists on msgspec Struct#
Fix a bug in
MsgspecDTOwhere a KeyError was raised if amsgspec.Structcontained aClassVar. ClassVars are now correctly skipped when generating field definitions.References: https://github.com/litestar-org/litestar/pull/4665