#[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 is enabled on this crate.
§Usage
#[server]
pub async fn blog_posts(
category: String,
) -> Result<Vec<BlogPost>, ServerFnError> {
let posts = load_posts(&category).await?;
// maybe do some other work
Ok(posts)
}§Named Arguments
You can 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)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)
#[server(
name = SomeStructName,
prefix = "/my_api",
endpoint = "my_fn",
input = Cbor,
output = Json
)]
pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<usize, ServerFnError> {
unimplemented!()
}
// expands to
#[derive(Deserialize, Serialize)]
struct SomeStructName {
input: Vec<String>
}
impl ServerFn for SomeStructName {
const PATH: &'static str = "/my_api/my_fn";
// etc.
}§Adding layers to server functions
Layers allow you to transform the request and response of a server function. You can use layers to add authentication, logging, or other functionality to your server functions. Server functions integrate with the tower ecosystem, so you can use any layer that is compatible with tower.
Common layers include:
tower_http::trace::TraceLayerfor tracing requests and responsestower_http::compression::CompressionLayerfor compressing large responsestower_http::cors::CorsLayerfor adding CORS headers to responsestower_http::timeout::TimeoutLayerfor adding timeouts to requeststower_sessions::service::SessionManagerLayerfor adding session management to requests
You can add a tower Layer to your server function with the middleware attribute:
#[server]
// The TraceLayer will log all requests to the console
#[middleware(tower_http::timeout::TimeoutLayer::new(std::time::Duration::from_secs(5)))]
pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<usize, ServerFnError> {
unimplemented!()
}§Extracting additional data from requests
Server functions automatically handle serialization and deserialization of arguments and responses.
However, you may want to extract additional data from the request, such as the user’s session or
authentication information. You can do this with the extract function. This function returns any
type that implements the FromRequestParts
trait:
#[server]
pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<String, ServerFnError> {
let headers: axum::http::header::HeaderMap = extract().await?;
Ok(format!("The server got a request with headers: {:?}", headers))
}§Sharing data with server functions
You may need to share context with your server functions like a database pool. Server
functions can access any context provided through the launch builder. You can access
this context with the FromContext extractor:
#[derive(Clone, Copy, Debug)]
struct DatabasePool;
fn main() {
LaunchBuilder::new()
.with_context(server_only! {
DatabasePool
})
.launch(app);
}
#[server]
pub async fn my_wacky_server_fn(input: Vec<String>) -> Result<String, ServerFnError> {
let FromContext(pool): FromContext<DatabasePool> = extract().await?;
Ok(format!("The server read {:?} from the shared context", pool))
}