Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
R2 Storage and the Developer Toolchain  ›  Lesson

Routing with Hono — Taming the if-Chain

Hono 12 minHono turns a Worker's fetch handler into a table of method-and-path routes with a context object for the request, bindings and responses, plus middleware for shared checks.

Routing with Hono — Taming the if-Chain

Hoplink's fetch handler has become a wall of if (request.method === ... && url.pathname ...) checks, and the new file routes will make it worse. A router turns that wall into a readable table of routes. On Workers the most popular choice is Hono, a small, fast framework built on the same web-standard Request and Response you already know.

The rule

One line per route: method, path pattern, handler.

import { Hono } from "hono";

const app = new Hono();

app.get("/:code", async (c) => {
  const target = await c.env.LINKS.get(c.req.param("code"));
  if (!target) return c.text("No such link", 404);
  return c.redirect(target, 302);
});

app.post("/links", async (c) => {
  const { code, url } = await c.req.json();
  await c.env.LINKS.put(code, url);
  return c.json({ created: code }, 201);
});

export default app;

Reading it part by part:

  • app.get / app.post choose the HTTP method.
  • "/:code" is a path pattern; :code captures whatever sits in that position, read with c.req.param("code").
  • The context c bundles the request (c.req), your bindings (c.env) and response helpers (c.text, c.json, c.redirect).
  • export default app works because a Hono app already has the fetch(request, env, ctx) method the runtime expects.

Query strings stay separate from the path: for /links?owner=priya, the handler reads c.req.query("owner"). Keeping the two apart matters — the path says which thing, the query says how to filter or shape it.

Hono also supports middleware — functions that run before or after handlers. app.use("/admin/*", checkToken) guards every admin route with one line instead of repeating the check.

Itty Router is a still smaller alternative with the same route-table idea. And if you are shipping a full frontend (React, Svelte, Astro and friends), Cloudflare can serve its built files as static assets from the same Worker, with Hono handling the API routes beside them.

The shortcut

Write the route table first, as a comment, before any handler code. Then order it so specific paths come before catch-all patterns — routers try routes in the order you register them.

Adding the file routes without breaking redirectsStep 1 of 4
  1. List the routes

    POST /files, GET /files/:name, GET /:code, POST /links.

Trap: registering app.get("/:code") at the top. A later app.get("/stats") would never run, because stats is swallowed as a short code.

Drills

Answer fast — trust the rule.

quick drill

In app.get("/:code", ...), how does the handler read the value of code?

quick drill

Why can a Hono app be the default export of a Worker?

quick drill

Inside a Hono handler, where are your KV, R2 and D1 bindings?

quick drill

Routes are registered as GET /:code, then GET /stats. What does GET /stats do?

quick drill

Every /admin/... route must check a token. What is the cleanest approach?

Remember

  • One line per route: method, path pattern, handler.
  • Shortcut: route table first, specific paths before catch-alls.
  • Trap: a greedy /:code registered early swallows later routes.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhy did /stats break?

Hoplink's Hono app registers GET /:code first, then GET /stats and POST /files. Visitors to /stats get a 'No such link' page. Explain why, how to fix it, and how the stats handler reaches the D1 binding.