Skip to content

Commit

Permalink
allow custom req/res/client types
Browse files Browse the repository at this point in the history
  • Loading branch information
gbj committed Jan 19, 2024
1 parent 1b1e027 commit 46e7abf
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 5 deletions.
5 changes: 5 additions & 0 deletions leptos_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(),
Expand Down
5 changes: 5 additions & 0 deletions server_fn/server_fn_macro_default/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions server_fn_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ nightly = []
ssr = []
actix = []
axum = []
reqwest = []
78 changes: 73 additions & 5 deletions server_fn_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub fn server_macro_impl(
body: TokenStream2,
server_fn_path: Option<Path>,
default_path: &str,
preset_req: Option<Type>,
preset_res: Option<Type>,
) -> Result<TokenStream2> {
let mut body = syn::parse::<ServerFnBody>(body.into())?;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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") {
Expand All @@ -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") {
Expand All @@ -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.",
));
};

Expand Down Expand Up @@ -614,6 +638,10 @@ struct ServerFnArgs {
input: Option<Type>,
output: Option<Type>,
fn_path: Option<Literal>,
req_ty: Option<Type>,
res_ty: Option<Type>,
client: Option<Type>,
custom_wrapper: Option<Type>,
builtin_encoding: bool,
}

Expand All @@ -628,6 +656,10 @@ impl Parse for ServerFnArgs {
// new arguments: can only be keyed by name
let mut input: Option<Type> = None;
let mut output: Option<Type> = None;
let mut req_ty: Option<Type> = None;
let mut res_ty: Option<Type> = None;
let mut client: Option<Type> = None;
let mut custom_wrapper: Option<Type> = None;

let mut use_key_and_value = false;
let mut arg_pos = 0;
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -794,6 +858,10 @@ impl Parse for ServerFnArgs {
output,
fn_path,
builtin_encoding,
req_ty,
res_ty,
client,
custom_wrapper,
})
}
}
Expand Down

0 comments on commit 46e7abf

Please sign in to comment.