hono·

Hono Basic

Hono Basic

Hono Basic

!info hono example basic을 참고로 작성되었습니다.

!tip 관련 소스는 github에서 확인할 수 있습니다.

시작

pnpm create hono@latest
pnpm create hono@latest
create-hono version 0.19.2
✔ Target directory basic
✔ Which template do you want to use? cloudflare-workers
✔ Do you want to install project dependencies? Yes
✔ Which package manager do you want to use? pnpm
✔ Cloning the template
✔ Installing project dependencies
🎉 Copied project files
Get started with: cd basic

biome

우선 biome 설정

pnpm add -D -E @biomejs/biome
pnpm exec biome init

vscode에 biome extension 설치

vitest

pnpm add -D vitest

vitest.config.ts 생성

vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true
  }
});

package.json에 추가

"test": "vitest"

types

pnpm run cf-typegen

tsconfig.json에 추가

    "types": [
      "vitest/globals",
      "./worker-configuration.d.ts"
    ]

src/index.ts

import { Hono } from "hono";
import { basicAuth } from "hono/basic-auth";
import { etag } from "hono/etag";
import { poweredBy } from "hono/powered-by";
import { prettyJSON } from "hono/pretty-json";

const app = new Hono();

// Mount Builtin Middleware
app.use("*", poweredBy());
// app.use('*', logger())
app.use(
  "/auth/*",
  basicAuth({
    username: "hono",
    password: "acoolproject"
  })
);
app.use("/etag/*", etag());

// Custom Middleware
// Add Custom Header
app.use("/hello/*", async (c, next) => {
  await next();
  c.header("X-message", "This is addHeader middleware!");
});

// Add X-Response-Time header
app.use("*", async (c, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  c.header("X-Response-Time", `${ms}ms`);
});

// Custom Not Found Message
app.notFound((c) => {
  return c.text("Custom 404 Not Found", 404);
});

// Error handling
app.onError((err, c) => {
  console.error(`${err}`);
  return c.text("Custom Error Message", 500);
});

// Routing
app.get("/", c => c.text("Hono!!"));
// Use Response object directly
app.get("/hello", () => new Response("This is /hello"));

// Named parameter
app.get("/entry/:id", (c) => {
  const id = c.req.param("id");
  return c.text(`Your ID is ${id}`);
});

// Nested route
const book = new Hono();
book.get("/", c => c.text("List Books"));
book.get("/:id", (c) => {
  const id = c.req.param("id");
  return c.text(`Get Book: ${id}`);
});
book.post("/", c => c.text("Create Book"));
app.route("/book", book);

// Redirect
app.get("/redirect", c => c.redirect("/"));
// Authentication required
app.get("/auth/*", c => c.text("You are authorized"));
// ETag
app.get("/etag/cached", c => c.text("Is this cached?"));

// Async
app.get("/fetch-url", async (c) => {
  const response = await fetch("https://example.com/");
  return c.text(`https://example.com/ is ${response.status}`);
});

// Request headers
app.get("/user-agent", (c) => {
  const userAgent = c.req.header("User-Agent");
  return c.text(`Your UserAgent is ${userAgent}`);
});

// JSON
app.get("/api/posts", prettyJSON(), (c) => {
  const posts = [
    { id: 1, title: "Good Morning" },
    { id: 2, title: "Good Afternoon" },
    { id: 3, title: "Good Evening" },
    { id: 4, title: "Good Night" }
  ];
  return c.json(posts);
});
// status code
app.post("/api/posts", c => c.json({ message: "Created!" }, 201));
// default route
app.get("/api/*", c => c.text("API endpoint is not found", 404));

// Throw Error
app.get("/error", () => {
  throw new Error("Error has occurred");
});

// @ts-ignore
app.get("/type-error", () => "return not Response instance");

export default app;

src/index.test.ts

import app from "./index";

describe("Example", () => {
  test("GET /", async () => {
    const res = await app.request("http://localhost:8787/");
    expect(res.status).toBe(200);
    expect(res.headers.get("x-powered-by")).toBe("Hono");
  });
});

final test

pnpm run test

Iceship • © 2026