Search code examples
expressmigrationmiddlewareelysiajs

Express JS's request object equivalent in Elysia JS?


I have a middleware written in Express JS which authenticates the JWT sent from the client and if the token is valid, return its payload which is the encoded user:

const authenticateToken = async (req, res, next) => {
    try {
        const token = req.headers.authentication?.replace('Bearer ', '')
        if (!token) return res.status(401).json('Authentication required')

        const response = await verifyUserJWT(token)
        if (response.status !== 200)
            return res.status(response.status).json(response.item)
        req.user = response.item
        next()
    } catch (err) {
        return res.status(500).json(err)
    }
}

I'm trying to migrate this code from Express to Elysia which is still pretty new and there's not much information about it on the internet.

Here's my progress so far:

const authenticateToken = async ({headers, set}: any) => {
    try {
        const token = headers.authentication?.replace('Bearer ', '')
        if (!token) {
            set.status = 401
            return 'Authentication required'
        }
        const response = await verifyUserJWT(token)
        if (response.status !== 200) {
            set.status = response.status
            return response.item
        }
    } catch (err) {
        set.status = 500
        return err
    }
}

Elysia uses hooks instead of middlewares (kind of the same thing) so I'm using it as a local hook to authenticate the token before proceeding with the handler of the route:

import { Elysia } from 'elysia'
const app = new Elysia()
const PORT: string | 5000 = Bun.env.PORT || 5000

app.get('/', () => return 'Hello, World!', {
    beforeHandle: ({set, headers}: any) => {
        authenticateToken()
    }
})
// Expected result: If authenticateToken() fails, return the error message
// Otherwise proceed with the handler which then returns "Hello, World!"

.listen(PORT)

console.log(
    `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
)

Most of the migration work was pretty straight forward, except for the part where I needed to save the user acquired from the token so that next time I can just reuse it (e.g calling req.user) without having to decode the token again. It kind of defeats the whole purpose of being fast if you have to do the same stuff multiple times in the same process.

To better demonstrate what I mean, here's my other middleware which executes right after the first one if everything goes through:

const authorizeAdmin = async (req, res, next) => {
    try {
        if (!req.user) {
            return res.status(401).json('Please login first.')
        }

        if (req.user.role !== 1) {
            return res.status(403).json('Unauthorized access.')
        }

        next()
    } catch (err) {
        return res.status(500).json(err)
    }
}

Since I've already defined req.user in the first one, I can just reuse it here.

I haven't found any way to achieve the same results in Elysia because the documentation isn't that great. ChatGPT and other AI chat models didn't have any information either because the technology is still pretty new. Even googling didn't help.

Do you guys know any equivalent for req.user for Elysia or any alternatives to go about this?


Solution

  • Nevermind, it's actually very simple. Just use request like req in Express

    app.get('/', ({ request }: any) => request.phrase, {
        beforeHandle: ({ request }: any) => {
            request.phrase = 'Hello, World!'
        },
    })