|
| 1 | +--- |
| 2 | +title: HTTP Handlers |
| 3 | +slug: /functions/http-handlers |
| 4 | +--- |
| 5 | + |
| 6 | +import Tabs from '@theme/Tabs' |
| 7 | +import TabItem from '@theme/TabItem' |
| 8 | + |
| 9 | +HTTP handlers allow a SpacetimeDB database to expose an HTTP API. |
| 10 | +External clients can make HTTP requests to routes nested under [`/v1/database/:name_or_address/route`](../../00300-resources/00200-reference/00200-http-api/00300-database.md#any-v1databasename_or_identityroutepath); these requests are resolved to routes defined by the database and then passed to the corresponding HTTP handler. |
| 11 | + |
| 12 | +:::warning |
| 13 | +***HTTP handlers are currently in beta, and their API may change in upcoming SpacetimeDB releases.*** |
| 14 | +::: |
| 15 | + |
| 16 | +## Defining HTTP Handlers |
| 17 | + |
| 18 | +<Tabs groupId="server-language" queryString> |
| 19 | +<TabItem value="rust" label="Rust"> |
| 20 | + |
| 21 | +Because HTTP handlers are unstable, Rust modules that define them must opt in to the `unstable` feature in their `Cargo.toml`: |
| 22 | + |
| 23 | +```toml |
| 24 | +[dependencies] |
| 25 | +spacetimedb = { version = "2.*", features = ["unstable"] } |
| 26 | +``` |
| 27 | + |
| 28 | +Define an HTTP handler by annotating a function with `#[spacetimedb::http::handler]`. |
| 29 | + |
| 30 | +The function must accept exactly two arguments: |
| 31 | + |
| 32 | +1. A `&mut spacetimedb::http::HandlerContext`. |
| 33 | +2. A `spacetimedb::http::Request`. |
| 34 | + |
| 35 | +The function must return a `spacetimedb::http::Response`. |
| 36 | + |
| 37 | +```rust |
| 38 | +use spacetimedb::http::{Body, handler, HandlerContext, Request, Response}; |
| 39 | + |
| 40 | +#[handler] |
| 41 | +fn say_hello(_ctx: &mut HandlerContext, _req: Request) -> Response { |
| 42 | + Response::new(Body::from_bytes("Hello!")) |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +</TabItem> |
| 47 | +</Tabs> |
| 48 | + |
| 49 | +## Registering Handlers to Routes |
| 50 | + |
| 51 | +Once you've [defined an HTTP handler](#defining-http-handlers), you must register it to a route in order to make it reachable for requests. |
| 52 | + |
| 53 | +<Tabs groupId="server-language" queryString> |
| 54 | +<TabItem value="rust" label="Rust"> |
| 55 | + |
| 56 | +All routes exposed by your module are declared in a `spacetimedb::http::Router`. Register the `Router` for your database by returning it from a function annotated with `#[spacetimedb::http::router]`. |
| 57 | + |
| 58 | +```rust |
| 59 | +use spacetimedb::http::{router, Router}; |
| 60 | + |
| 61 | +#[router] |
| 62 | +fn router() -> Router { |
| 63 | + Router::new() |
| 64 | + .get("/say-hello", say_hello) |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +Add routes within a router with the `get`, `head`, `options`, `put`, `delete`, `post`, `patch` and `any` methods, which register an HTTP handler for that HTTP method at a given path. |
| 69 | + |
| 70 | +Nest routers with `router.nest(prefix, sub_router)`, which causes `sub_router` to handle routing for all paths that start with `prefix`. |
| 71 | + |
| 72 | +Combine routers with `router.merge(other_router)`, which combines both routers. |
| 73 | + |
| 74 | +</TabItem> |
| 75 | +</Tabs> |
| 76 | + |
| 77 | +### Strict Routing |
| 78 | + |
| 79 | +SpacetimeDB uses strict routing, meaning that a request must match a path exactly in order to be routed to that handler. Trailing slashes are significant. |
| 80 | + |
| 81 | +## Sending Requests |
| 82 | + |
| 83 | +Routes defined by a SpacetimeDB database are exposed under the prefix `/v1/database/:name/route`. To access the `say-hello` route above, send a request to `$SPACETIMEDB_URI/v1/database/$DATABASE/route/say-hello`, where `$SPACETIMEDB_URI` is the SpacetimeDB host (usually `https://maincloud.spacetimedb.com`), and `$DATABASE` is the name of the database. |
0 commit comments