Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] Hono - Helpers

Updated
5 min readView as Markdown
[ 살펴보기 ] Hono - Helpers
C

A developer living in Busan, Korea

Hono는 application 운영에 필요한 기능을 다양한 helpers function을 통해 제공한다. 전체 helper list는 documentation에서 확인할 수 있으며 그 중 일부를 살펴보자.

Accepts

Request header중 accept 관련 header를 관리할 때 사용할 수 있는 helper다. 예를 들어 client request Accept-Language header의 값이 accepts helper option중 supports language에 포함되어 있는 language이면 해당 langauge를 return하고 그렇지 않으면 default로 설정한 값을 return한다.

...
import { accepts } from "hono/accepts";

const app = new Hono();

app.get('/items', (c) => {
  const accept = accepts(c, {
    header: 'Accept-Language',
    supports: ['en', 'ko', 'fr'],
    default: 'en',
  })
  return c.json({ lang: accept })
})

예를 들어 코드가 위와 같을 때 request Accept-Language header의 값이 supports에 설정한 language에 포함되어 있으면 해당 language를 return하고 그렇지 않으면 default에 선언한 en을 return한다.

Accept-Language이외에 다음 Accept 관련 header역시 accepts helper를 통해 filter할 수 있다.

export type AcceptHeader =
  | 'Accept'
  | 'Accept-Charset'
  | 'Accept-Encoding'
  | 'Accept-Language'
  | 'Accept-Patch'
  | 'Accept-Post'
  | 'Accept-Ranges'

Adapter

adapter helper에서 제공하는 env function을 통해 environment variable에 접근할 수 있다. 만약 .env 파일을 통해 application environment variable을 관리중이라면 다음 package를 추가로 설치해준다. ( NodeJS runtime 기준 )

npm install dotenv

.env

DATABASE_NAME=mydb

index.ts

...
import "dotenv/config";
import { env } from "hono/adapter";

type Env = {
  DATABASE_NAME: string;
};

const app = new Hono();

app.get("/items", async (c) => {
  const { DATABASE_NAME } = env<Env>(c, "node");
  return c.json({ message: "hello world" });
});

...

application을 운영하는 runtime에 따라 env function이 포함하는 범위에 다소 차이가 있으니 해당 사항은 documentation을 통해 확인할 수 있다. ( Reference - Supported Runtimes, Serverless Platforms and Cloud Services )

Adaptor helper에서 제공하는 getRuntimeKey function을 통해 현재 application이 운영되는 runtime name을 조회할 수 있다.

...
import { env, getRuntimeKey } from "hono/adapter";

const app = new Hono();

app.get("/items", async (c) => {
  const { DATABASE_NAME } = env<Env>(c, "node");
  const runtimeName = getRuntimeKey();
  return c.json({ message: "hello world" });
});

ConnInfo

client ip address나 ip type과 같은 connection 정보를 확인할 수 있는 function을 제공한다.

...
import { getConnInfo } from 'hono/cloudflare-workers'

const app = new Hono();

app.get('/items', (c) => {
  const info = getConnInfo(c) 
  const { remote } = info;
  return c.text(`remote address : ${remote.address}`)
})

cookie를 조회하거나, 설정, 삭제를 수행할 수 있는 function을 제공한다. 다음은 cookie helper가 제공하는 function을 통해 cookie를 조회하는 예제다.

...
import { getCookie } from 'hono/cookie'

const app = new Hono();

app.get("/items", async (c) => {
  const allCookies = getCookie(c);
  const mysnackCookie = getCookie(c, "mysnack");
  return c.json({ message: "hello world" });
});

cookie를 설정하여 response header에 포함할 때는 setCookie function을 사용한다.

...
import { setCookie } from "hono/cookie";

const app = new Hono();

app.get("/items", async (c) => {
  setCookie(c, "yoursnack", "grape");
  return c.json({ message: "hello world" });
});

response header의 특정 cookie를 삭제하고 싶다면 deleteCookie function을 사용한다.

...
import { deleteCookie } from "hono/cookie";

const app = new Hono();

app.get("/items", async (c) => {
  deleteCookie(c, "mysnack");
  return c.json({ message: "hello world" });
});

cookie을 설정할 때 cookie의 option은 다음과 같이 설정할 수 있다.

setCookie(c, 'yoursnack', 'grape', {
  path: '/',
  secure: true,
  domain: 'example.com',
  httpOnly: true,
  maxAge: 1000,
  sameSite: 'Strict',
})

Hono cookie helper를 통해 cookie를 parse할 때 다음 상황에서 error가 throw된다.

  • cookie name이 __Secure- prefix로 시작하지만 cookie에 secure option 설정되지 않았을 때

  • cookie name이 __Host- prefix로 시작하지만 cookie에 secure option이 설정되지 않았을 때

  • cookie name이 __Host- prefix로 시작하지만 cookie의 path가 /가 아닐 때

  • cookie name이 __Host- prefix로 시작하지만 cookie의 domain option이 설정되어 있을 때

  • maxAge option이 400일 이상으로 설정되었을 때

  • expires option이 400일 이상으로 설정되었을 때

html

html helper에서 제공하는 function을 통해 Javascirpt template literal안에 html code를 작성해 response로 전달할 수 있다.

...
import { html } from "hono/html";

const app = new Hono();

app.get("/items", async (c) => {
  return c.html(html`<html>
    <head>
      <title>Item page</title>
    </head>
    <body>
      <h1>Item Page</h1>
    </body>
  </html>`);
});

다음과 같이 functional component 형식과 같이 구성하여 render할 수도 있다. html helper에서 제공하는 html function은 HtmlEscapeString을 return 하므로 jsx, tsx extension을 사용할 필요는 없다.

views/layout.ts

import { html } from "hono/html";
import type { HtmlEscapedString } from "hono/utils/html";

type Props = {
  title: string;
  mainContent: HtmlEscapedString | Promise<HtmlEscapedString>;
};

const Layout = ({ mainContent, title }: Props) =>
  html`<html>
    <head>
      <title>${title}</title>
    </head>
    <body>
      ${mainContent}
    </body>
  </html>`;

export default Layout;

views/main.ts

import { html } from "hono/html";

const MainPage = () =>
  html`<main>
    <div>Main Page</div>
  </main>`;

export default MainPage;

index.ts

import Layout from "./views/Layout.js";
import MainPage from "./views/MainPage.js";
...

const app = new Hono();

app.get("/items", async (c) => {
  return c.html(<Layout title="main page" mainContent={<MainPage />} />);
});

JWT

JSON Web Token을 decode 하거나 sign, verify할 때 필요한 function을 제공한다.

JWT helepr에서 제공하는 sign function을 통해 token을 생성할 수 있다.

...
import { sign } from "hono/jwt";

const app = new Hono();

const payload = {
  sub: "testUser",
  role: "user",
  exp: Math.floor(Date.now() / 1000) + 60 * 30, // Token expires in 30 minutes
};

const secret = "secretKey";

app.get("/items", async (c) => {
  const token = await sign(payload, secret);
  return c.json({ token });
});

verify function을 통해 전달받은 token이 유효한 token인지 검사한다.

...
import { sign, verify } from "hono/jwt";

...

app.get("/items", async (c) => {
  const authorization = c.req.header("authorization");
  const token = authorization ? authorization.split(" ")[1] : "";
  try {
    const result = await verify(token, secret);
    return c.json({ token });
  } catch (err) {
    return c.json({ error: "Invalid Token"}, 401);
  }
});

decode function을 통해 JSON web token을 decode할 수 있다.

...
import { decode, sign, verify } from "hono/jwt";

...

app.get("/items", async (c) => {
  const authorization = c.req.header("authorization");
  const token = authorization ? authorization.split(" ")[1] : "";
  try {
    const result = decode(token);
    return c.json({ token });
  } catch (err) {
    return c.json({ error: "Invalid Token" }, 401);
  }
});

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts