Hono Basic
[!info] hono example basic을 참고로 작성되었습니다.
[!tip] 관련 소스는 github에서 확인할 수 있습니다.
시작
pnpm create hono@latestpnpm create hono@latestcreate-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 filesGet started with: cd basicbiome
우선 biome 설정
pnpm add -D -E @biomejs/biomepnpm exec biome initvscode에 biome extension 설치
vitest
pnpm add -D vitestvitest.config.ts 생성
import { defineConfig } from 'vitest/config'
export default defineConfig({ test: { globals: true }})package.json에 추가
"test": "vitest"types
pnpm run cf-typegentsconfig.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 Middlewareapp.use('*', poweredBy())// app.use('*', logger())app.use( '/auth/*', basicAuth({ username: 'hono', password: 'acoolproject' }))app.use('/etag/*', etag())
// Custom Middleware// Add Custom Headerapp.use('/hello/*', async (c, next) => { await next() c.header('X-message', 'This is addHeader middleware!')})
// Add X-Response-Time headerapp.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 Messageapp.notFound((c) => { return c.text('Custom 404 Not Found', 404)})
// Error handlingapp.onError((err, c) => { console.error(`${err}`) return c.text('Custom Error Message', 500)})
// Routingapp.get('/', (c) => c.text('Hono!!'))// Use Response object directlyapp.get('/hello', () => new Response('This is /hello'))
// Named parameterapp.get('/entry/:id', (c) => { const id = c.req.param('id') return c.text(`Your ID is ${id}`)})
// Nested routeconst 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)
// Redirectapp.get('/redirect', (c) => c.redirect('/'))// Authentication requiredapp.get('/auth/*', (c) => c.text('You are authorized'))// ETagapp.get('/etag/cached', (c) => c.text('Is this cached?'))
// Asyncapp.get('/fetch-url', async (c) => { const response = await fetch('https://example.com/') return c.text(`https://example.com/ is ${response.status}`)})
// Request headersapp.get('/user-agent', (c) => { const userAgent = c.req.header('User-Agent') return c.text(`Your UserAgent is ${userAgent}`)})
// JSONapp.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 codeapp.post('/api/posts', (c) => c.json({ message: 'Created!' }, 201))// default routeapp.get('/api/*', (c) => c.text('API endpoint is not found', 404))
// Throw Errorapp.get('/error', () => { throw Error('Error has occurred')})
// @ts-ignoreapp.get('/type-error', () => 'return not Response instance')
export default appsrc/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