#[server]Expand description
Declares that a function is a server function.
This means that its body will only run on the server, i.e., when the ssr feature on this crate is enabled.
If you call a server function from the client (i.e., when the csr or hydrate features
are enabled), it will instead make a network request to the server.
§Named Arguments
You can provide any combination of the following named arguments:
name: sets the identifier for the server function’s type, which is a struct created to hold the arguments (defaults to the function identifier in PascalCase)prefix: a prefix at which the server function handler will be mounted (defaults to/api) your prefix must begin with/. Otherwise your function won’t be found.endpoint: specifies the exact path at which the server function handler will be mounted, relative to the prefix (defaults to the function name followed by unique hash)input: the encoding for the arguments (defaults toPostUrl)output: the encoding for the response (defaults toJson)client: a customClientimplementation that will be used for this server fnencoding: (legacy, may be deprecated in future) specifies the encoding, which may be one of the following (not case sensitive)"Url":POSTrequest with URL-encoded arguments and JSON response"GetUrl":GETrequest with URL-encoded arguments and JSON response"Cbor":POSTrequest with CBOR-encoded arguments and response"GetCbor":GETrequest with URL-encoded arguments and CBOR response
reqandresspecify 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)impl_from: specifies whether to implement traitFromfor server function’s type or not. By default, if a server function only has one argument, the macro automatically implements theFromtrait to convert from the argument type to the server function type, and vice versa, allowing you to convert between them easily. Settingimpl_fromtofalsedisables this, which can be necessary for argument types for which this would create a conflicting implementation. (defaults totrue)
#[server(
name = SomeStructName,
prefix = "/my_api",
endpoint = "my_fn",
input = Cbor,
output = Json
impl_from = true
)]
pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<usize, ServerFnError> {
todo!()
}§Server Function Encodings
Server functions are designed to allow a flexible combination of input and output encodings, the set
of which can be found in the server_fn::codec module.
The serialization/deserialization process for server functions consists of a series of steps, each of which is represented by a different trait:
IntoReq: The client serializes theServerFnargument type into an HTTP request.- The
Clientsends the request to the server. FromReq: The server deserializes the HTTP request back into theServerFntype.- The server calls calls
ServerFn::run_bodyon the data. IntoRes: The server serializes theServerFn::Outputtype into an HTTP response.- The server integration applies any middleware from
ServerFn::middlewareand responds to the request. FromRes: The client deserializes the response back into theServerFn::Outputtype.
Whatever encoding is provided to input should implement IntoReq and FromReq. Whatever encoding is provided
to output should implement IntoRes and FromRes.
§Default Values for Parameters
Individual function parameters can be annotated with #[server(default)], which will pass
through #[serde(default)]. This is useful for the empty values of arguments with some
encodings. The URL encoding, for example, omits a field entirely if it is an empty Vec<_>,
but this causes a deserialization error: the correct solution is to add #[server(default)].
pub async fn with_default_value(#[server(default)] values: Vec<u32>) /* etc. */§Important Notes
- Server functions must be
async. Even if the work being done inside the function body can run synchronously on the server, from the client’s perspective it involves an asynchronous function call. - Server functions must return
Result<T, ServerFnError>. Even if the work being done inside the function body can’t fail, the processes of serialization/deserialization and the network call are fallible.ServerFnErrorcan be generic over some custom error type. If so, that type should implementFromStrandDisplay, but does not need to implementError. This is so the value can be easily serialized and deserialized along with the result.
- Server functions are part of the public API of your application. A server function is an ad hoc HTTP API endpoint, not a magic formula. Any server function can be accessed by any HTTP client. You should take care to sanitize any data being returned from the function to ensure it does not leak data that should exist only on the server.
- Server functions can’t be generic. Because each server function creates a separate API endpoint, it is difficult to monomorphize. As a result, server functions cannot be generic (for now?) If you need to use a generic function, you can define a generic inner function called by multiple concrete server functions.
- Arguments and return types must be serializable. We support a variety of different encodings, but one way or another arguments need to be serialized to be sent to the server and deserialized on the server, and the return type must be serialized on the server and deserialized on the client. This means that the set of valid server function argument and return types is a subset of all possible Rust argument and return types. (i.e., server functions are strictly more limited than ordinary functions.)
- Context comes from the server. Server functions are provided access to the HTTP request and other relevant server data via the server integrations, but they do not have access to reactive state that exists in the client.
- Your server must be ready to handle the server functions at the API prefix you list. The easiest way to do this
is to use the
handle_server_fnsfunction fromleptos_actixorleptos_axum. - Server functions must have unique paths. Unique paths are automatically generated for each
server function. If you choose to specify a path in the fourth argument, you must ensure that these
are unique. You cannot define two server functions with the same URL prefix and endpoint path,
even if they have different URL encodings, e.g. a POST method at
/api/fooand a GET method at/api/foo.