-
Notifications
You must be signed in to change notification settings - Fork 9
Creating a custom storage driver
In most cases, hono_sessions
storage drivers should consist of just a single file. You can either create a driver just for use in your own application, or you can create a package for the driver and share it with the community!
As an example, let's create a driver for MongoDB. I'm going to use the Deno runtime for this because it's the simplest and is what I'm most familiar with 😄
First, let's get an instance of MongoDB running on our local machine using Docker. The following command will create an instance of Mongo then delete it automatically after we're done:
docker run --rm -p 27017:27017 --name mongo-sessions mongo:latest
Somewhere in your project, we'll need to create a .ts
file that extends the Store
interface. Let's create a file called MongoStore.ts
in our project root:
import { Store, SessionData } from 'npm:hono-sessions' // Import hono-sessions types
import { Db, Collection } from 'npm:mongodb' // Import MongoDB types
class MongoStore implements Store {
db: Db
sessions: Collection
constructor(db: Db, collectionName = 'sessions') {
this.db = db
this.sessions = db.collection(collectionName)
}
async getSessionById(sessionId: string) {
const session = await this.sessions.findOne({ id: sessionId })
return session ? session.data : null
}
async createSession(sessionId: string, initialData: SessionData) {
await this.sessions.replaceOne(
{
id: sessionId
},
{
id: sessionId,
data: initialData
},
{
upsert: true
}
)
}
async persistSessionData(sessionId : string, sessionData : SessionData) {
await this.sessions.replaceOne(
{ id: sessionId },
{
id: sessionId,
data: sessionData
},
{ upsert: true }
)
}
async deleteSession(sessionId : string) {
await this.sessions.deleteOne({ id: sessionId })
}
}
export default MongoStore
Now, we'll create a new Hono app called app.ts
that uses our new storage driver:
import { Hono } from 'npm:hono'
import { html } from 'npm:hono/html'
import { sessionMiddleware, Session } from 'npm:hono-sessions'
import MongoStore from './MongoStore.ts'
import { MongoClient } from 'npm:mongodb'
// Create new Mongo client or use an existing client
const client = new MongoClient('mongodb://localhost:27017')
await client.connect()
// Create a Mongo database, or use an existing db
const db = client.db('sessions-mongo')
// Create a store using our new storage driver
const store = new MongoStore(
db
)
type SessionDataTypes = {
'counter': number
}
const app = new Hono<{
Variables: {
session: Session<SessionDataTypes>,
session_key_rotation: boolean
}
}>()
app.use('*', sessionMiddleware({
store,
encryptionKey: 'password_at_least_32_characters_long', // Required for CookieStore, recommended for others
expireAfterSeconds: 900, // Expire session after 15 minutes of inactivity
cookieOptions: {
sameSite: 'Lax', // Recommended for basic CSRF protection in modern browsers
path: '/', // Required for this library to work properly
httpOnly: true, // Recommended to avoid XSS attacks
},
}))
app.get('/', (c) => {
const session = c.get('session')
session.set('counter', (session.get('counter') || 0) + 1)
return c.html(`<h1>You have visited this page ${ session.get('counter') } times</h1>`)
})
Deno.serve(app.fetch)
That's it! Let's test it by running the script with Deno. In a separate terminal from the Mongo process, run this command:
deno run -A app.ts
Now, visit http://localhost:8000
and you should see a visit counter that increments by 1 every time you refresh the page!