[ 살펴보기 ] Hono - Helpers
![[ 살펴보기 ] Hono - Helpers](https://cdn.hashnode.com/res/hashnode/image/upload/v1730520220043/92ce0a81-87ca-4121-b004-e06d5a0f44e9.jpeg)
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
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);
}
});
![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)