diff --git a/leptos_macro/src/lib.rs b/leptos_macro/src/lib.rs index 1ce7dd5336..6af2401b64 100644 --- a/leptos_macro/src/lib.rs +++ b/leptos_macro/src/lib.rs @@ -871,12 +871,15 @@ pub fn slot(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { /// relative to the prefix (defaults to the function name followed by unique hash) /// - `input`: the encoding for the arguments (defaults to `PostUrl`) /// - `output`: the encoding for the response (defaults to `Json`) +/// - `client`: a custom `Client` implementation that will be used for this server fn /// - `encoding`: (legacy, may be deprecated in future) specifies the encoding, which may be one /// of the following (not case sensitive) /// - `"Url"`: `POST` request with URL-encoded arguments and JSON response /// - `"GetUrl"`: `GET` request with URL-encoded arguments and JSON response /// - `"Cbor"`: `POST` request with CBOR-encoded arguments and response /// - `"GetCbor"`: `GET` request with URL-encoded arguments and CBOR response +/// - `req` and `res` specify the HTTP request and response types to be used on the server (these +/// should usually only be necessary if you are integrating with a server other than Actix/Axum) /// /// ```rust,ignore /// #[server( @@ -949,6 +952,8 @@ pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { s.into(), Some(syn::parse_quote!(::leptos::server_fn)), "/api", + None, + None, ) { Err(e) => e.to_compile_error().into(), Ok(s) => s.to_token_stream().into(), diff --git a/server_fn/server_fn_macro_default/src/lib.rs b/server_fn/server_fn_macro_default/src/lib.rs index 9d18372839..fbd25da524 100644 --- a/server_fn/server_fn_macro_default/src/lib.rs +++ b/server_fn/server_fn_macro_default/src/lib.rs @@ -34,12 +34,15 @@ use syn::__private::ToTokens; /// relative to the prefix (defaults to the function name followed by unique hash) /// - `input`: the encoding for the arguments (defaults to `PostUrl`) /// - `output`: the encoding for the response (defaults to `Json`) +/// - `client`: a custom `Client` implementation that will be used for this server fn /// - `encoding`: (legacy, may be deprecated in future) specifies the encoding, which may be one /// of the following (not case sensitive) /// - `"Url"`: `POST` request with URL-encoded arguments and JSON response /// - `"GetUrl"`: `GET` request with URL-encoded arguments and JSON response /// - `"Cbor"`: `POST` request with CBOR-encoded arguments and response /// - `"GetCbor"`: `GET` request with URL-encoded arguments and CBOR response +/// - `req` and `res` specify the HTTP request and response types to be used on the server (these +/// should usually only be necessary if you are integrating with a server other than Actix/Axum) /// ```rust,ignore /// #[server( /// name = SomeStructName, @@ -71,6 +74,8 @@ pub fn server(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream { s.into(), Some(syn::parse_quote!(server_fns)), "/api", + None, + None, ) { Err(e) => e.to_compile_error().into(), Ok(s) => s.to_token_stream().into(), diff --git a/server_fn_macro/Cargo.toml b/server_fn_macro/Cargo.toml index 5fb3b6b561..472d640b1b 100644 --- a/server_fn_macro/Cargo.toml +++ b/server_fn_macro/Cargo.toml @@ -20,3 +20,4 @@ nightly = [] ssr = [] actix = [] axum = [] +reqwest = [] diff --git a/server_fn_macro/src/lib.rs b/server_fn_macro/src/lib.rs index 03db265357..d2b4a8cbcc 100644 --- a/server_fn_macro/src/lib.rs +++ b/server_fn_macro/src/lib.rs @@ -35,6 +35,8 @@ pub fn server_macro_impl( body: TokenStream2, server_fn_path: Option, default_path: &str, + preset_req: Option, + preset_res: Option, ) -> Result { let mut body = syn::parse::(body.into())?; @@ -65,7 +67,12 @@ pub fn server_macro_impl( output, fn_path, builtin_encoding, + req_ty, + res_ty, + client, + custom_wrapper, } = args; + _ = custom_wrapper; // TODO: this should be used to enable custom encodings let prefix = prefix.unwrap_or_else(|| Literal::string(default_path)); let fn_path = fn_path.unwrap_or_else(|| Literal::string("")); let input_ident = match &input { @@ -380,9 +387,16 @@ pub fn server_macro_impl( PathInfo::None => quote! {}, }; - // TODO reqwest - let client = quote! { - #server_fn_path::client::browser::BrowserClient + let client = if let Some(client) = client { + client.to_token_stream() + } else if cfg!(feature = "reqwest") { + quote! { + #server_fn_path::client::reqwest::ReqwestClient + } + } else { + quote! { + #server_fn_path::client::browser::BrowserClient + } }; let req = if !cfg!(feature = "ssr") { @@ -397,11 +411,16 @@ pub fn server_macro_impl( quote! { #server_fn_path::request::actix::ActixRequest } + } else if let Some(req_ty) = req_ty { + req_ty.to_token_stream() + } else if let Some(req_ty) = preset_req { + req_ty.to_token_stream() } else { return Err(syn::Error::new( Span::call_site(), "If the `ssr` feature is enabled, either the `actix` or `axum` \ - features should also be enabled.", + features should also be enabled, or the `req = ` argument should \ + be provided to specify the request type.", )); }; let res = if !cfg!(feature = "ssr") { @@ -416,11 +435,16 @@ pub fn server_macro_impl( quote! { #server_fn_path::response::actix::ActixResponse } + } else if let Some(res_ty) = res_ty { + res_ty.to_token_stream() + } else if let Some(res_ty) = preset_res { + res_ty.to_token_stream() } else { return Err(syn::Error::new( Span::call_site(), "If the `ssr` feature is enabled, either the `actix` or `axum` \ - features should also be enabled.", + features should also be enabled, or the `res = ` argument should \ + be provided to specify the response type.", )); }; @@ -614,6 +638,10 @@ struct ServerFnArgs { input: Option, output: Option, fn_path: Option, + req_ty: Option, + res_ty: Option, + client: Option, + custom_wrapper: Option, builtin_encoding: bool, } @@ -628,6 +656,10 @@ impl Parse for ServerFnArgs { // new arguments: can only be keyed by name let mut input: Option = None; let mut output: Option = None; + let mut req_ty: Option = None; + let mut res_ty: Option = None; + let mut client: Option = None; + let mut custom_wrapper: Option = None; let mut use_key_and_value = false; let mut arg_pos = 0; @@ -703,6 +735,38 @@ impl Parse for ServerFnArgs { )); } output = Some(stream.parse()?); + } else if key == "req" { + if req_ty.is_some() { + return Err(syn::Error::new( + key.span(), + "keyword argument repeated: `req`", + )); + } + req_ty = Some(stream.parse()?); + } else if key == "res" { + if res_ty.is_some() { + return Err(syn::Error::new( + key.span(), + "keyword argument repeated: `res`", + )); + } + res_ty = Some(stream.parse()?); + } else if key == "client" { + if client.is_some() { + return Err(syn::Error::new( + key.span(), + "keyword argument repeated: `client`", + )); + } + client = Some(stream.parse()?); + } else if key == "custom" { + if custom_wrapper.is_some() { + return Err(syn::Error::new( + key.span(), + "keyword argument repeated: `custom`", + )); + } + custom_wrapper = Some(stream.parse()?); } else { return Err(lookahead.error()); } @@ -794,6 +858,10 @@ impl Parse for ServerFnArgs { output, fn_path, builtin_encoding, + req_ty, + res_ty, + client, + custom_wrapper, }) } }