Last active
August 6, 2020 14:57
-
-
Save andywer/1571a022fca1d17039b073c3c066f259 to your computer and use it in GitHub Desktop.
Koa: Passing data from middleware to route handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Description: | |
* | |
* There are times when we want to re-use some data created/derived in a middleware later in a route handler. | |
* | |
* The default Koa way of doing so would be using `context.state`. Unfortunately `context.state` is hard to type and | |
* quite implicit, since it's an object shared and potentially mutated by all middlewares and the route handler. | |
*/ | |
/* | |
* Option 1: Default approach | |
*/ | |
import createError from "http-errors" | |
import JWT from "jsonwebtoken" | |
import Koa from "koa" | |
import Router from "koa-router" | |
import logger from "./logger" | |
import { findProductsByUserId } from "./models/product" | |
function authenticate() { | |
return (context: Koa.Context, next: (ctx: Koa.Context) => Promise<any>) => { | |
try { | |
const user = JWT.verify(context.request.getHeader("Authorization"), "secret") | |
// Put user data into context state | |
context.state.user = user | |
} catch (error) { | |
logger.error(error) | |
throw createError(401) | |
} | |
await next(context) | |
} | |
} | |
const app = new Koa() | |
const router = new Router() | |
router.get("/products", authenticate(), async ({ response, state }) => { | |
response.body = await findProductsByUserId(state.user.id) | |
}) | |
app.use(router.routes()) | |
app.use(router.allowedMethods()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Option 2: Don't re-use, parse auth token a 2nd time | |
* | |
*/ | |
import createError from "http-errors" | |
import JWT from "jsonwebtoken" | |
import Koa from "koa" | |
import Router from "koa-router" | |
import logger from "./logger" | |
import { findProductsByUserId } from "./models/product" | |
function authenticate() { | |
return (context: Koa.Context, next: (ctx: Koa.Context) => Promise<any>) => { | |
try { | |
JWT.verify(context.request.getHeader("Authorization"), "secret") | |
// Do not even put user data into context state | |
} catch (error) { | |
logger.error(error) | |
throw createError(401) | |
} | |
await next(context) | |
} | |
} | |
function getUserFromRequest (request: Koa.Request) { | |
try { | |
const user = JWT.verify(request.getHeader("Authorization"), "secret") | |
return user | |
} catch (error) { | |
logger.error(error) | |
throw createError(401) | |
} | |
} | |
const app = new Koa() | |
const router = new Router() | |
router.get("/products", authenticate(), async ({ request, response }) => { | |
// Parse JWT again | |
const user = getUserFromRequest(request) | |
response.body = await findProductsByUserId(user.id) | |
}) | |
app.use(router.routes()) | |
app.use(router.allowedMethods()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment