Split serialization and de-serialization based on Accept header appearance

This commit is contained in:
2025-08-04 22:58:21 +03:00
parent 7480ad326b
commit 1191ee0ada
2 changed files with 26 additions and 2 deletions

View File

@@ -15,7 +15,7 @@ from .interfaces.serialized import SerializedResponse, SerializedRequest
from .interfaces.serialized.text import TextSerializedResponse
from .req_schema import UnwrappedRequest
from .router import Router, Route
from .types import HandlerType, InternalHandlerType, ContentType
from .types import HandlerType, InternalHandlerType, ContentType, Accept
from .internal_types import Scope, Receive, Send, MethodType, QTYPE, BTYPE, PTYPE, HTYPE
from breakshaft.convertor import ConvRepo
@@ -47,6 +47,26 @@ class HTTPApp(ASGIApp):
charset = properties.get('charset')
if charset is None:
# TODO: extract default charsets based on content type
if contenttype == 'application/json':
charset = 'utf-8'
else:
charset = 'latin1'
return ContentType(contenttype, charset)
def extract_accept_type(self, req: BasicRequest, ct: ContentType) -> Accept:
contenttype_header = req.headers.get('Accept')
if contenttype_header is None:
return ct
properties: dict[str, str]
contenttype, properties = parse_content_type(contenttype_header)
charset = properties.get('charset')
if charset is None:
# TODO: extract default charsets based on content type
if contenttype == 'application/json':
charset = 'utf-8'
else:
@@ -58,7 +78,7 @@ class HTTPApp(ASGIApp):
ser = self.serialize_selector.select(ct.contenttype, ct.charset)
return ser.req.deserialize(req, ct.charset)
def serialize_response(self, req: BasicRequest, sresp: SerializedResponse, ct: ContentType) -> BasicResponse:
def serialize_response(self, req: BasicRequest, sresp: SerializedResponse, ct: Accept) -> BasicResponse:
ser = self.serialize_selector.select(ct.contenttype, ct.charset)
sresponser = ser.resp
@@ -217,6 +237,7 @@ class SlothApp(HTTPApp, WSApp, LifespanApp, MethodRoutersApp):
return req.body
self.inj_repo.add_injector(self.extract_content_type)
self.inj_repo.add_injector(self.extract_accept_type)
self.inj_repo.add_injector(self.serialize_request)
self.inj_repo.add_injector(self.serialize_response)

View File

@@ -16,3 +16,6 @@ type InternalHandlerType = Callable[[Send, BasicRequest], Awaitable[None]]
class ContentType:
contenttype: str
charset: str
type Accept = ContentType