Potato
Home
Getting Started
GitHub
  • 简体中文
  • English
Home
Getting Started
GitHub
  • 简体中文
  • English
  • Preface
  • Getting Started
  • Handler Function Annotations and Declaration
  • Server-Side Routing
  • Graceful Shutdown
  • Using the Client
  • Server-Sent Events
  • ACME Automatic Certificate Management
  • /en/guide/08_webtransport.html
  • Cache System
  • Controller

Server-Side Routing

Server-side routing is used to specify what actions to take for target request addresses, calling handler functions or specifying static files, etc. If one doesn't match, the next is tried. The default server-side routing is as follows (if not written, it defaults to this):

server.configure(|ctx| {
    ctx.use_handlers(false);
});

Here the use_handlers function represents searching for matching handler functions for the request path. If found, it redirects to the corresponding handler function.

In addition to the above handler functions, there are several other routes:

OpenAPI Documentation

Add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_openapi("/doc/");
    // ...
});

The path refers to the documentation URL. In production, prefer disabling docs endpoints or using a non-obvious path to reduce accidental exposure.

Local Directory Routing

Add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_location_route("/", "/wwwroot", false);
    // ...
});

The first parameter is the request path, the second parameter is the local directory path, and the third parameter controls whether symlinks are allowed to escape wwwroot:

  • true: allow symlinks inside wwwroot to point to files/directories outside wwwroot
  • false: block symlink escape outside wwwroot

If a file /wwwroot/a.json exists, it can be accessed via the request /a.json.

This route also supports common static-resource capabilities:

  • Conditional requests: If-None-Match, If-Modified-Since, If-Match, If-Unmodified-Since
  • Range download: Range and If-Range

Advanced note: combine this with CDN cache policy and large-file chunk strategy to reduce origin load.

Embedded Resource Routing

Add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_embedded_route("/", embed_dir!("assets/wwwroot"));
    // ...
});

Embedded resources mean that the directory specified by the embed_dir macro is built into the executable program at compile time. Subsequently, during runtime, it doesn't require the local path to exist and can still provide corresponding file request responses.

Memory Leak Debugging Routing

The implementation mechanism of this feature is to take over the program's memory allocation actions, recording the memory allocation location each time it allocates. Then at the dump location, it traverses all unreleased memory and prints memory allocation information. Enable the jemalloc feature of the potato library:

cargo add potato --features jemalloc

Then add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_jemalloc("/profile.pdf");
    // ...
});

This method requires the function's runtime environment to be Linux, and the following libraries to be installed:

# ubuntu/debian
sudo apt install libjemalloc-dev graphviz ghostscript

After running the service, request /profile.pdf to see the detailed memory allocation records of the program stack. If memory leak issues exist, focus on examining the functions with larger reports for troubleshooting.

Custom Routing

Add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_custom(|req| async { Some(HttpResponse::text("hello")) });
    ctx.use_custom_sync(|req| Some(HttpResponse::text("hello")));
    // ...
});

The use_custom function lets you insert async custom request handling logic, while use_custom_sync is for sync custom handling logic.

  • Async closure: ctx.use_custom(|req| async { ... })
  • Sync closure: ctx.use_custom_sync(|req| { ... })

If it returns Some(response), the response is returned immediately and later middleware/handlers are skipped. If it returns None, processing continues. For use_custom_sync, the framework invokes it on a purely synchronous path (not by wrapping it into an async call).

Global Preprocess and Postprocess

First, annotate preprocess and postprocess functions with macros:

#[potato::preprocess]
async fn my_preprocess(req: &mut HttpRequest) -> Option<HttpResponse> {
    // Preprocess logic: executed when request arrives
    // Return Some(response) to short-circuit the request
    None
}

#[potato::postprocess]
async fn my_postprocess(req: &mut HttpRequest, res: &mut HttpResponse) {
    // Postprocess logic: executed after handler completes
    res.add_header("X-Custom".into(), "value".into());
}

Then register them in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_preprocess(my_preprocess);
    ctx.use_postprocess(my_postprocess);
    // ...
});
  • use_preprocess: Register a global preprocess function, executed before all route handling. If it returns Some(response), the response is returned immediately, skipping all subsequent processing.
  • use_postprocess: Register a global postprocess function, executed after the handler generates a response, allowing you to modify the response (e.g., adding response headers).

Note: Preprocess and postprocess functions must be annotated with #[potato::preprocess] and #[potato::postprocess] macros.

WebDAV Routing

Enable the webdav feature of the potato library:

cargo add potato --features webdav

Then add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_webdav_localfs("/webdav", "/tmp");
    // ctx.use_webdav_memfs("/webdav");
    // ...
});

Reverse Proxy Routing

Add the following code in the configure function:

server.configure(|ctx| {
    // ...
    ctx.use_reverse_proxy("/", "http://www.fawdlstty.com", true);
    // ...
});

The use_reverse_proxy function is used to set up reverse proxy routing, and it accepts three parameters:

  • First parameter url_path: local path prefix, specifying which request paths need to be proxied
  • Second parameter proxy_url: target proxy server address, requests will be forwarded to this address
  • Third parameter modify_content: boolean value, specifying whether to modify URLs in the response content (replace proxy server address with local path)

When modify_content is set to true, proxy server addresses in the response content will be replaced with the local path, which is very useful for handling hardcoded URLs in static resources. This feature supports WebSocket connection proxying and can automatically handle protocol upgrades.

Last Updated:: 4/17/26, 10:45 PM
Contributors: fawdlstty
Prev
Handler Function Annotations and Declaration
Next
Graceful Shutdown