@@ -8,6 +8,7 @@ use crate::emit::doc_attr;
88use crate :: emit:: emit_type;
99use crate :: emit:: models:: emit_struct;
1010use crate :: error:: Result ;
11+ use crate :: ir:: Body ;
1112use crate :: ir:: CookieParam ;
1213use crate :: ir:: Cookies ;
1314use crate :: ir:: HeaderParam ;
@@ -29,6 +30,24 @@ impl crate::emit::ServerEmitter for AxumServer {
2930 }
3031}
3132
33+ /// The handler extractor pattern + type for a request body of the given kind.
34+ fn body_extractor ( kind : crate :: ir:: BodyKind , ty : & TokenStream ) -> TokenStream {
35+ return match kind {
36+ crate :: ir:: BodyKind :: Json => quote ! { axum:: Json ( body) : axum:: Json <#ty> } ,
37+ crate :: ir:: BodyKind :: Text => quote ! { body: String } ,
38+ crate :: ir:: BodyKind :: Form => quote ! { axum:: Form ( body) : axum:: Form <#ty> } ,
39+ } ;
40+ }
41+
42+ /// The response tuple term that renders a body of the given kind.
43+ fn response_body_term ( kind : crate :: ir:: BodyKind ) -> TokenStream {
44+ return match kind {
45+ crate :: ir:: BodyKind :: Json => quote ! { axum:: Json ( body) } ,
46+ crate :: ir:: BodyKind :: Text => quote ! { body } ,
47+ crate :: ir:: BodyKind :: Form => quote ! { axum:: Form ( body) } ,
48+ } ;
49+ }
50+
3251/// Emit the axum server interface: the `Api` trait, per-operation response
3352/// enums, the `Router` builder, and the internal handler functions.
3453fn service_items ( service : & Service ) -> Result < Vec < TokenStream > > {
@@ -100,7 +119,7 @@ fn emit_method_args(operation: &Operation) -> Result<Vec<TokenStream>> {
100119 args. push ( quote ! { cookies: #ty } ) ;
101120 }
102121 if let Some ( body) = & operation. body {
103- let ty = emit_type ( body) ?;
122+ let ty = emit_type ( & body. ty ) ?;
104123 args. push ( quote ! { body: #ty } ) ;
105124 }
106125 return Ok ( args) ;
@@ -152,7 +171,7 @@ fn emit_fixed_response(
152171 name : & proc_macro2:: Ident ,
153172 variant : & proc_macro2:: Ident ,
154173 code : u16 ,
155- body : & Option < RustType > ,
174+ body : & Option < Body > ,
156175) -> Result < ( TokenStream , TokenStream ) > {
157176 let code = proc_macro2:: Literal :: u16_unsuffixed ( code) ;
158177 let status = quote ! {
@@ -163,12 +182,13 @@ fn emit_fixed_response(
163182 } ;
164183 let result = match body {
165184 Some ( body) => {
166- let ty = emit_type ( body) ?;
185+ let ty = emit_type ( & body. ty ) ?;
167186 let variant_def = quote ! { #variant( #ty) } ;
187+ let term = response_body_term ( body. kind ) ;
168188 let arm = quote ! {
169189 #name:: #variant( body) => {
170190 #status
171- ( STATUS , axum :: Json ( body ) ) . into_response( )
191+ ( STATUS , #term ) . into_response( )
172192 }
173193 } ;
174194 ( variant_def, arm)
@@ -193,14 +213,15 @@ fn emit_fixed_response(
193213fn emit_dynamic_response (
194214 name : & proc_macro2:: Ident ,
195215 variant : & proc_macro2:: Ident ,
196- body : & Option < RustType > ,
216+ body : & Option < Body > ,
197217) -> Result < ( TokenStream , TokenStream ) > {
198218 let result = match body {
199219 Some ( body) => {
200- let ty = emit_type ( body) ?;
220+ let ty = emit_type ( & body. ty ) ?;
201221 let variant_def = quote ! { #variant( axum:: http:: StatusCode , #ty) } ;
222+ let term = response_body_term ( body. kind ) ;
202223 let arm = quote ! {
203- #name:: #variant( status, body) => ( status, axum :: Json ( body ) ) . into_response( ) ,
224+ #name:: #variant( status, body) => ( status, #term ) . into_response( ) ,
204225 } ;
205226 ( variant_def, arm)
206227 }
@@ -298,8 +319,8 @@ fn emit_handler(operation: &Operation) -> Result<TokenStream> {
298319 call_args. push ( quote ! { cookies } ) ;
299320 }
300321 if let Some ( body) = & operation. body {
301- let ty = emit_type ( body) ?;
302- extractors. push ( quote ! { axum :: Json ( body) : axum :: Json <#ty> } ) ;
322+ let ty = emit_type ( & body. ty ) ?;
323+ extractors. push ( body_extractor ( body. kind , & ty ) ) ;
303324 call_args. push ( quote ! { body } ) ;
304325 }
305326
@@ -329,7 +350,7 @@ fn emit_response_with_headers(
329350 field_defs. push ( quote ! { status: axum:: http:: StatusCode } ) ;
330351 }
331352 if let Some ( body) = & case. body {
332- let ty = emit_type ( body) ?;
353+ let ty = emit_type ( & body. ty ) ?;
333354 field_defs. push ( quote ! { body: #ty } ) ;
334355 }
335356 let mut header_field_defs = Vec :: with_capacity ( case. headers . len ( ) ) ;
@@ -380,11 +401,14 @@ fn emit_response_with_headers(
380401 inserts. push ( emit_response_header_insert ( header) ) ;
381402 }
382403
383- let body_term = if case. body . is_some ( ) {
384- quote ! { , axum:: Json ( body) }
385- } else {
386- quote ! { }
387- } ;
404+ let body_term = case
405+ . body
406+ . as_ref ( )
407+ . map ( |b| {
408+ let t = response_body_term ( b. kind ) ;
409+ return quote ! { , #t } ;
410+ } )
411+ . unwrap_or_default ( ) ;
388412
389413 let arm = quote ! {
390414 #name:: #variant { #( #binds) , * } => {
0 commit comments