#[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 customClient
implementation 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"
: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
andres
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)
#[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::TraceLayer
for tracing requests and responsestower_http::compression::CompressionLayer
for compressing large responsestower_http::cors::CorsLayer
for adding CORS headers to responsestower_http::timeout::TimeoutLayer
for adding timeouts to requeststower_sessions::service::SessionManagerLayer
for 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))
}