x/oak_sessions@v3.5.2
Use cookie-based web sessions with the Oak framework. Supports flash messages - session data that is deleted after it's read.
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session } from "https://deno.land/x/oak_sessions/mod.ts";
type AppState = {
session: Session
}
const app = new Application<AppState>()
app.addEventListener('error', (evt) => {
console.log(evt.error)
})
const router = new Router<AppState>();
// Instantiate session
const session = new Session()
// Apply sessions to your Oak application. You can also apply the middleware to specific routes instead of the whole app.
app.use(session.initMiddleware())
router.post('/login', async (ctx) => {
const form = await ctx.request.body({type: 'form'}).value
if(form.get('password') === 'correct') {
// Set persistent data in the session
await ctx.state.session.set('email', form.get('email'))
await ctx.state.session.set('failed-login-attempts', null)
// Set flash data in the session. This will be removed the first time it's accessed with get
await ctx.state.session.flash('message', 'Login successful')
} else {
const failedLoginAttempts = (await ctx.state.session.get('failed-login-attempts') || 0) as number
await ctx.state.session.set('failed-login-attempts', failedLoginAttempts+1)
await ctx.state.session.flash('error', 'Incorrect username or password')
}
ctx.response.redirect('/')
})
router.post('/logout', async (ctx) => {
// Clear all session data
await ctx.state.session.deleteSession()
ctx.response.redirect('/')
})
router.get("/", async (ctx) => {
const message = await ctx.state.session.get('message') || ''
const error = await ctx.state.session.get('error') || ''
const failedLoginAttempts = await ctx.state.session.get('failed-login-attempts')
const email = await ctx.state.session.get('email')
ctx.response.body = `<!DOCTYPE html>
<body>
<p>
${message}
</p>
<p>
${error}
</p>
<p>
${failedLoginAttempts ? `Failed login attempts: ${failedLoginAttempts}` : ''}
</p>
${email ?
`<form id="logout" action="/logout" method="post">
<button name="logout" type="submit">Log out ${email}</button>
</form>`
:
`<form id="login" action="/login" method="post">
<p>
<input id="email" name="email" type="text" placeholder="you@email.com">
</p>
<p>
<input id="password" name="password" type="password" placeholder="password">
</p>
<button name="login" type="submit">Log in</button>
</form>`
}
</body>`;
})
app.use(router.routes());
app.use(router.allowedMethods());
app.listen({ port: 8002 });
You can specify the storage layer used to store session data. Here are the supported storage layers:
By default, MemoryStorage
is the storage driver, but you can (and should in production) use a more robust and persistent storage driver.
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, CookieStore } from "https://deno.land/x/oak_sessions/mod.ts";
const app = new Application();
const store = new CookieStore('very-secret-key')
// Attach sessions to middleware
const session = new Session(store);
// ...
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, SqliteStore } from "https://deno.land/x/oak_sessions/mod.ts";
import { DB } from 'https://deno.land/x/sqlite@v3.4.0/mod.ts'
const app = new Application();
const sqlite = new DB('./database.db')
// Pass DB instance into a new SqliteStore. Optionally add a custom table name as second string argument, default is 'sessions'
const store = new SqliteStore(sqlite, 'optional_custom_table_name')
// Attach sessions to middleware.
const session = new Session(store);
// ...
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, PostgresStore } from "https://deno.land/x/oak_sessions/mod.ts";
import postgres from 'https://deno.land/x/postgresjs@v3.1.0/mod.js'
const app = new Application();
// Create a postgres connection, or use an existing one
const sql = postgres({
host: 'localhost',
port: 26257,
database: 'defaultdb',
user: 'root',
password: '',
})
// Pass postgres connection into a new PostgresStore. Optionally add a custom table name as second string argument, default is 'sessions'
const store = new PostgresStore(sql, 'optional_custom_table_name')
// Initialize sessions table. Will create a table if one doesn't exist already.
await store.initSessionsTable()
// Attach sessions to middleware
const session = new Session(store)
// ...
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, RedisStore } from "https://deno.land/x/oak_sessions/mod.ts";
// import the Redis library
import { connect } from 'https://deno.land/x/redis@v0.25.0/mod.ts'
const app = new Application();
// Create a redis connection
const redis = await connect({
hostname: '0.0.0.0',
port: 6379
})
// pass redis connection into a new RedisStore. Optionally add a second string argument for a custom database prefix, default is 'session_'
const store = new RedisStore(redis)
// Attach sessions to middleware
const session = new Session(store);
// ...
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, MongoStore } from "https://deno.land/x/oak_sessions/mod.ts";
import { MongoClient } from "https://deno.land/x/mongo@v0.29.4/mod.ts";
const app = new Application();
// Create mongo connection or use an existing one
const client = new MongoClient();
const db = client.database('default');
// Pass mongo connection into a new MongoStore. Optionally add a custom collection name as second string argument, default is 'sessions'
const store = new MongoStore(db, 'optional_custom_collection_name');
// Attach sessions to middleware
const session = new Session(store);
// ...
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session, WebdisStore } from "https://deno.land/x/oak_sessions/mod.ts";
const app = new Application();
const store = new WebdisStore({
url: 'http://127.0.0.1:7379',
});
// Attach sessions to middleware
const session = new Session(store);
// ...
More stores will be added over time.