@@ -28,6 +28,23 @@ def _get_updated_headers(self, headers: dict | None = None) -> dict:
2828 headers_ .update (headers )
2929 return headers_
3030
31+ def _get_json_headers (
32+ self ,
33+ headers : dict | None = None ,
34+ body : str | None = None ,
35+ files : Mapping [str , BytesIO ] | None = None ,
36+ ) -> dict :
37+ """Headers for a request whose body is serialized JSON.
38+
39+ The body is passed to httpx as raw ``content``, so the JSON content type has to be set
40+ explicitly - Starlette will not parse the body into the endpoint's model without it.
41+ Skipped for multipart requests and when the caller sets the header itself.
42+ """
43+ headers_ = self ._get_updated_headers (headers )
44+ if body is not None and not files and not any (k .lower () == "content-type" for k in headers_ ):
45+ headers_ ["Content-Type" ] = "application/json"
46+ return headers_
47+
3148 @staticmethod
3249 def _get_body (
3350 data : dict [str , Any ] | BaseModel | list [dict [str , Any ]] | list [BaseModel ] | None = None ,
@@ -50,10 +67,11 @@ async def post(
5067 ) -> Response :
5168 if query :
5269 url = self ._prepare_url (url , query )
70+ body = self ._get_body (data )
5371 response = await self .client .post (
5472 url ,
55- content = self . _get_body ( data ) ,
56- headers = self ._get_updated_headers (headers ),
73+ content = body ,
74+ headers = self ._get_json_headers (headers , body , files ),
5775 files = files ,
5876 )
5977 return response
@@ -67,10 +85,11 @@ async def put(
6785 ) -> Response :
6886 if query :
6987 url = self ._prepare_url (url , query )
88+ body = self ._get_body (data )
7089 response = await self .client .put (
7190 url ,
72- content = self . _get_body ( data ) ,
73- headers = self ._get_updated_headers (headers ),
91+ content = body ,
92+ headers = self ._get_json_headers (headers , body ),
7493 )
7594 return response
7695
@@ -94,11 +113,12 @@ async def delete(
94113 ) -> Response :
95114 if query :
96115 url = self ._prepare_url (url , query )
116+ body = self ._get_body (data )
97117 response = await self .client .request (
98118 "DELETE" ,
99119 url ,
100- content = self . _get_body ( data ) ,
101- headers = self ._get_updated_headers (headers ),
120+ content = body ,
121+ headers = self ._get_json_headers (headers , body ),
102122 )
103123 return response
104124
0 commit comments