@@ -109,7 +109,7 @@ pub fn server(attr: proc_macro::TokenStream, mut item: TokenStream) -> TokenStre
109109 query_params : vec ! [ ] ,
110110 route_lit : args. fn_path ,
111111 oapi_options : None ,
112- server_args : Default :: default ( ) ,
112+ server_args : args . server_args ,
113113 prefix : Some ( prefix) ,
114114 _input_encoding : args. input ,
115115 _output_encoding : args. output ,
@@ -1505,6 +1505,9 @@ struct ServerFnArgs {
15051505 /// The protocol to use for the server function implementation.
15061506 protocol : Option < Type > ,
15071507 builtin_encoding : bool ,
1508+ /// Server-only extractors (e.g., headers: HeaderMap, cookies: Cookies).
1509+ /// These are arguments that exist purely on the server side.
1510+ server_args : Punctuated < FnArg , Comma > ,
15081511}
15091512
15101513impl Parse for ServerFnArgs {
@@ -1529,7 +1532,18 @@ impl Parse for ServerFnArgs {
15291532 let mut use_key_and_value = false ;
15301533 let mut arg_pos = 0 ;
15311534
1535+ // Server-only extractors (key: Type pattern)
1536+ // These come after config options (key = value pattern)
1537+ // Example: #[server(endpoint = "/api/chat", headers: HeaderMap, cookies: Cookies)]
1538+ let mut server_args: Punctuated < FnArg , Comma > = Punctuated :: new ( ) ;
1539+
15321540 while !stream. is_empty ( ) {
1541+ // Check if this looks like an extractor (Ident : Type)
1542+ // If so, break out to parse extractors - they must come last
1543+ if stream. peek ( Ident ) && stream. peek2 ( Token ! [ : ] ) {
1544+ break ;
1545+ }
1546+
15331547 arg_pos += 1 ;
15341548 let lookahead = stream. lookahead1 ( ) ;
15351549 if lookahead. peek ( Ident ) {
@@ -1698,6 +1712,20 @@ impl Parse for ServerFnArgs {
16981712 }
16991713 }
17001714
1715+ // Now parse any remaining extractors (key: Type pattern)
1716+ while !stream. is_empty ( ) {
1717+ if stream. peek ( Ident ) && stream. peek2 ( Token ! [ : ] ) {
1718+ server_args. push_value ( stream. parse :: < FnArg > ( ) ?) ;
1719+ if stream. peek ( Comma ) {
1720+ server_args. push_punct ( stream. parse :: < Comma > ( ) ?) ;
1721+ } else {
1722+ break ;
1723+ }
1724+ } else {
1725+ break ;
1726+ }
1727+ }
1728+
17011729 // parse legacy encoding into input/output
17021730 let mut builtin_encoding = false ;
17031731 if let Some ( encoding) = encoding {
@@ -1740,6 +1768,7 @@ impl Parse for ServerFnArgs {
17401768 impl_from,
17411769 impl_deref,
17421770 protocol,
1771+ server_args,
17431772 } )
17441773 }
17451774}
0 commit comments