hono-kv-session
v1.0.0
Published
Stateful session middleware for Hono. Works with Cloudflare KV or node-redis.
Downloads
23
Maintainers
Readme
hono-kv-session
Stateful session middleware for Hono. Works on Cloudflare Workers, Node.js, Bun, Deno, etc.
ステートフルなセッションを提供するHonoのミドルウェアです。Cloudflare WorkersやNode.js、Bunなどの環境で動作します。
ToDo
- Support MongoDB
- Support Fastly KV store
- Support AWS DynamoDB
Supported Key-Value stores
- Cloudflare KV
- Redis (with node-redis)
- Deno KV
- New! Cloudflare D1 (sqlite)
Supported Runtimes
| Supported | Runtime | Tested | | --- | --- | --- | | ✔️ | Bun | ✔️ | | ✔️ | Cloudflare Workers | ✔️ | | ✔️ | Cloudflare Pages (Functions) | | | ✔️ | Node.js | ✔️ | | ✔️ | Deno (with Redis) | ✔️ | | ✔️ | Deno KV | ✔️ |
Installation
npm install hono-kv-session
Setup KV
- Cloudflare Workers
- Create KV namespace the bind name
SESSION
.$ wrangler kv:namespace create SESSION
- Set the UUID of the KV namespace generated in
1.
towrangler.toml
.
Like,{ binding = "SESSION", id = "b80d8fc5924d43ba85b56aa6b6dbb1c3" }
- Create KV namespace the bind name
- Bun, Node.js, Deno, etc.
- Just start the Redis server.
For systemd:# systemctl start redis-server
- Just start the Redis server.
- Deno KV
Deno KV is currently experimental
Executing Deno programs with--unstable
flag, as below:$ deno run --allow-net --watch --unstable app.ts
- Cloudflare D1
- Create D1 Database.
$ wrangler d1 create session-db
- Update D1's
database_id
towrangler.toml
.[[ d1_databases ]] binding = "SESSION_DB" database_name = "session-db" database_id = "<Unique ID for Your Database Here>" preview_database_id = "local"
- Run
$ npm run d1:init
- Create D1 Database.
Usage
You can see the sample code in the ./dev
directory in Github.
Mount kv client
Cloudflare Workers, Cloudflare Pages
import { kvClient } from 'hono-kv-session/cloudflare'; app.use('*', kvClient());
Node.js, Bun, Deno (with Redis)
import { kvClient } from 'hono-kv-session/redis'; app.use('*', kvClient()); // or You can set any node-redis's createClient() options app.use('*', kvClient({ url: 'redis://alice:[email protected]:6380' }));
Deno KV
import { kvClient } from 'https://deno.land/x/hono_kv_session/kv/denokv.js'; app.use('*', kvClient());
Cloudflare D1
import { kvClient } from 'hono-kv-session/d1'; app.use('*', kvClient());
Use SessionManager
Set
SessionManager()
middleware.import { SessionManager, createSession, deleteSession } from 'hono-kv-session' // If you are using Deno, replace module name to "npm:hono-kv-session" app.use('*', SessionManager({ // Cookie's id name: 'session_cookie' // Default: 'id' // Secret for Hono's signed cookies secret: 'Strong_Secret_123' // Default: null // Session TTL. Set for both KV and cookies. Minimum 60. ttl: 60, // Default: 604800 (1 week) // Update session TTL for each access. renew: true, // Default: true // Update session ID for each access. regenerate: true, // Default: false }))
secret
is secret of Hono's signed cookies (This feature has untested).
See Hono's Cookie Helper documentation for details.
Get session data
app.get('/', async (c) => { const { value, key, name, status } = c.session; return c.json({ username: value, session_id: key, // Default: crypto.randomUUID()'s uuid cookie_id: name, status, }) })
Deny Access If you don’t use the
denyAccess()
middleware, unauthorized sessions will not be denied and will be able to access the system. By referencingc.session.status = true|false
, you can restrict access to specific routes or HTTP methods.import { denyAccess } from 'hono-kv-session'; // If JSON app.use('*', denyAccess({ type: 'json', // 'json' or 'html' or 'text' status: 401, // status code response: { status: false, message: 'Invalid session' } })) // If HTML app.use('*', denyAccess({ type: 'html', // 'json' or 'html' or 'text' status: 401, // status code response: '<p>Invalid session</p>' }));
Create session
app.post('/login', async (c) => { // Extract client's username from FormData const { user } = await c.req.parseBody() // Create session await createSession(c, user, { secret: 'Strong_Secret_123' // If you are using signed cookie }) return c.redirect('/') })
Renewal session
app.get('/renew', async (c) => { await renewSession(c) return c.redirect('/') })
Delete session
app.post('/logout', async (c) => { await deleteSession(c) return c.redirect('/') })
Session Format
- in Key-Value store:
session:<hostname>:<uuid>
andvalue
Key:session:www.example.com:49b0b962-5b95-43c6-9e00-94ce1313d0ed
Value:user01
- in Cookie:
id=49b0b962-5b95-43c6-9e00-94ce1313d0ed
- in
c.session
c.session = { session: 'user01' // KV value key: `49b0b962-5b95-43c6-9e00-94ce1313d0ed` // KV key name: 'id' // Cookie name }
Dependecies
License
MIT