Route
Create
ovr’s built-in router offers efficient matching, supporting static paths, parameters, and wildcards. Utilizing a radix trie structure ensures performance does not degrade as more routes are added.
Create a route to a specific resource in your application with the Route class. Construct the route with an HTTP method, the route pattern, and the middleware to handle the request.
import { Route } from "ovr";
const route = new Route("GET", "/", () => "html");
Parameters
Create a parameter for a route by prefixing a segment with a colon :.
The pattern /api/:id sets Context.params.id to the actual path segment requested, for example /api/123. The name of the parameter is extracted from the pattern using TypeScript to ensure Context.params always has the correct type.
new Route("GET", "/api/:id", (c) => {
// matches "/api/123"
c.params.id; // "123"
});
Wildcard
Use an asterisk * to match all remaining segments in the route.
new Route("GET", "/files/*", (c) => {
c.params["*"]; // matched wildcard path (ex: "images/logo.png")
});
Prioritization
Routes are prioritized in this order:
Static > Parametric > Wildcard
Given three routes are added in any order:
app.use(new Route("GET", "/hello/*"));
app.use(new Route("GET", "/hello/world"));
app.use(new Route("GET", "/hello/:name"));
More specific matches are prioritized. The following pathnames would match the corresponding patterns:
| Pathname | Pattern |
|---|---|
/hello/world |
/hello/world |
/hello/john |
/hello/:name |
/hello/john/smith |
/hello/* |
Get
Route.get makes it easy to create a GET route and corresponding Anchor, Button, and Form components for it. This ensures if you change the route’s pattern, you don’t need to update all of the links to it throughout your application. Anytime you need to generate a link to a route use the Anchor component.
const page = Route.get("/", () => {
return (
<main>
{/* <a href="/"> */}
<page.Anchor>Home</page.Anchor>
{/* <button formmethod="GET" formaction="/"> */}
<page.Button>Submit</page.Button>
{/* <form method="GET" action="/"> */}
<page.Form>...</page.Form>
</main>
);
});
Post
There is also a Route.post function that will create a POST route and corresponding Form and Button elements. Anytime you need to handle a form submission, use the generated Form component. These components also automatically set the enctype=multipart/form-data attribute.
For Route.post, ovr will automatically generate a unique pathname for the route based on a hash of the middleware provided.
const login = Route.post(async (c) => {
const data = await c.req.formData();
// ...
c.redirect("/", 303);
});
const page = Route.get("/", () => {
return (
<main>
{/* <form method="POST" action="/_p/generated-hash" enctype="multipart/form-data"> */}
<login.Form>...</login.Form>
{/* <button formmethod="POST" formaction="/_p/generated-hash" formenctype="multipart/form-data"> */}
<login.Button>Submit</login.Button>
</main>
);
});
You can set the pattern manually if you need a stable pattern or if you are using parameters.
const custom = Route.post("/custom/:pattern", (c) => {
// ...
});
Props
Components created via helpers have the following props available:
params- if the route’s pattern has parameters, they must be passed as a prop to properly construct the URL.search- URLSearchParams to append to the URL, passed intoURLSearchParamsconstructor to create the query string.hash- fragment hash appended with a#at the end of the URL.
const page = Route.get("/hello/:name", () => {
return (
// <form method="GET" action="/hello/world?search=param#hash">
<page.Form
params={{ name: "world" }}
search={{ search: "param" }}
hash="hash"
>
...
</page.Form>
);
});
Properties
Given the following Route, a variety of other properties are available to use.
const page = Route.get("/hello/:name", (c) => <h1>Hello {c.params.name}</h1>);
Method
The route’s HTTP method.
page.method; // "GET"
Middleware
All Middleware added to the route.
page.middleware; // Middleware[]
Params
Params is a type helper to get the specific params of the route based on the pattern.
typeof page.Params; // { name: string }
Pattern
The pattern the route was created with.
page.pattern; // "/hello/:name"
Pathname
The pathname method inserts params into the pattern. It provides type safety to ensure you always pass the correct params (or no params) to create the pathname.
In this case, given the pattern /hello/:name, the name property must be passed in on the params object.
page.pathname({ name: "world" }); // `/hello/${string}`
page.pathname({ name: "world" } as const); // "/hello/world"
Using incorrect params results in a type error:
page.pathname({ id: "world" });
// Error: 'id' does not exist in type '{ name: string; }'
You can create a list of exact pathnames for given params:
const params = [
{ name: "world" },
{ name: "ross" },
] as const satisfies Route.Params<typeof page>[];
const pathnames = params.map((p) => page.pathname(p));
// ("/hello/world" | "/hello/ross")[]
Relative URL
The url method creates a relative URL (without the origin) for the route. This method is similar to pathname, but also provides the ability to also pass search and hash options to create the URL.
// /hello/world?search=param#hash
const relativeUrl = page.url({
params: { name: "world" },
search: { search: "param" },
hash: "hash",
});
const absoluteUrl = new URL(relativeUrl, "https://example.com");
absoluteUrl.href; // https://example.com/hello/world?search=param#hash