Crate server_fn

source ·
Expand description

Server Functions

This package is based on a simple idea: sometimes it’s useful to write functions that will only run on the server, and call them from the client.

If you’re creating anything beyond a toy app, you’ll need to do this all the time: reading from or writing to a database that only runs on the server, running expensive computations using libraries you don’t want to ship down to the client, accessing APIs that need to be called from the server rather than the client for CORS reasons or because you need a secret API key that’s stored on the server and definitely shouldn’t be shipped down to a user’s browser.

Traditionally, this is done by separating your server and client code, and by setting up something like a REST API or GraphQL API to allow your client to fetch and mutate data on the server. This is fine, but it requires you to write and maintain your code in multiple separate places (client-side code for fetching, server-side functions to run), as well as creating a third thing to manage, which is the API contract between the two.

This package provides two simple primitives that allow you instead to write co-located, isomorphic server functions. (Co-located means you can write them in your app code so that they are “located alongside” the client code that calls them, rather than separating the client and server sides. Isomorphic means you can call them from the client as if you were simply calling a function; the function call has the “same shape” on the client as it does on the server.)

#[server]

The #[server] macro allows you to annotate a function to indicate that it should only run on the server (i.e., when you have an ssr feature in your crate that is enabled).

Important: All server functions must be registered by calling ServerFn::register_in somewhere within your main function. Important: Before calling a server function on a non-web platform, you must set the server URL by calling set_server_url.

#[server(ReadFromDB)]
async fn read_posts(how_many: usize, query: String) -> Result<Vec<Posts>, ServerFnError> {
  // do some server-only work here to access the database
  let posts = ...;
  Ok(posts)
}

// call the function
async {
  let posts = read_posts(3, "my search".to_string()).await;
  log::debug!("posts = {posts:#?}");
}

// make sure you've registered it somewhere in main
fn main() {
  // for non-web apps, you must set the server URL manually
  server_fn::set_server_url("http://localhost:3000");
  _ = ReadFromDB::register();
}

If you call this function from the client, it will serialize the function arguments and POST them to the server as if they were the inputs in <form method="POST">.

Here’s what you need to remember:

  • 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.
  • Return types must implement Serialize. This should be fairly obvious: we have to serialize arguments to send them to the server, and we need to deserialize the result to return it to the client.
  • Arguments must be implement serde::Serialize. They are serialized as an application/x-www-form-urlencoded form data using serde_urlencoded or as application/cbor using cbor.

Enums

  • Holds the current options for encoding types. More could be added, but they need to be serde
  • A dual type to hold the possible Response datatypes
  • Type for errors that can occur when using server functions.

Traits

  • Defines a “server function.” A server function can be called from the server or the client, but the body of its code will only be run on the server, i.e., if a crate feature ssr (server-side-rendering) is enabled.
  • Something that can register a server function.

Functions

  • Executes the HTTP call to call a server function from the client, given its URL and argument type.
  • Attempts to find a server function registered at the given path.
  • Returns the set of currently-registered server function paths, for debugging purposes.
  • Set the root server url that all server function paths are relative to for the client. On WASM this will default to the origin.

Type Definitions

Attribute Macros

  • 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.