Public Lunch Week Page
Adding a Public Lunch Week Page
The purpose of our application is to publish a weekly lunch menu for the public to access. To that end, we are going to use what we've learned so far and build a Lunch Menu View page with a public Express endpoint for the data. Here's what the page will look like:

Our front-end route will use the convention /lunch-menu/<school-name>/<yyyy-MM-dd>
, e.g., /lunch-menu/pinewood-elementary/2020-11-16
so we can pull the school database name and week of from the front-end route and send it as a GET to the backend API.
Let's get start with the backend API endpoint. Create a new file in the /routes
directory called lunch-week-public.js
with a simple version of the endpoint:
const express = require('express')
const router = express.Router()
// let tenantKnex
router.get('/:schoolName/:weekOf', async function (req, res) {
try {
const weekOf = req.params.weekOf
res.send({ weekOf })
} catch (e) {
console.log(e)
res
.status(500)
.send({ message: 'Error getting lunch week', error: e.toString() })
}
})
module.exports = router
Then import the route file into app.js
and register it with the router. In this case we want the endpoint to be public, so we won't use the JWT or Knex middleware:
// IMPORT THE NEW ROUTE
const lunchWeekPublicRouter = require('./routes/lunch-week-public')
const router = express.Router()
router.use('/', indexRouter)
router.use('/users', usersRouter)
router.use('/lunch-week-public', lunchWeekPublicRouter) // ADD THE NEW ROUTE HERE
router.use('/lunch-week', [authenticateJwt, passKnex], lunchWeekRouter)
app.use('/api', router)
Test this in Postman and make sure the endpoint is working. Here is an example API route: localhost:3000/api/lunch-week-public/pinewood-elementary/2020-11-16
. You should see a response that looks like this:

Passing Knex to the Public Route#
Now that we have the basic endpoint working, let's actually wire it up to the database. Earlier, we used a dynamic-knex
module to cache and return Knex instances based on JWTs for our secured routes. In this case, we have a public route without a JWT and we have the database name as part of the route's URL convention.
Working again with the dynamic-knex
module, add a new middleware function called passKnexPublic
:
const passKnexPublic = (req, res, next) => {
const schoolName = req.params.schoolName
const schoolDatabase = schoolName.replace(/-/g, '_')
req.knex = getKnex(schoolDatabase)
next()
}
At the same time, change the name of the original passKnex
function to passKnexSecured
to make it more obvious that one is a unsecured way of passing Knex and the other one is a secured way:
const passKnexSecured = (req, res, next) => {
const schoolDatabase = req.user['https://school-lunch/school_database']
req.knex = getKnex(schoolDatabase)
next()
}
Last, change the module.exports
to export both middleware functions:
module.exports = { passKnexSecured, passKnexPublic }
Since we changed the name of passKnex
and the export style, we need to update app.js
:
// THE OLD WAY
// const passKnex = require('./database/dynamic-knex')
// THE NEW WAY
const { passKnexSecured } = require('./database/dynamic-knex')
// UPDATE THE ROUTE
router.use('/lunch-week', [authenticateJwt, passKnexSecured], lunchWeekRouter)
Next, we need to apply the new passKnexPublic
middleware. For consistency, it would be nice if we could use it in app.js
, but unfortunately since it depends on req.params.schoolName
, we cannot - req.params
are not parsed by Express until after the router.use
calls.
This page is a preview of Fullstack Svelte