Reputation: 283043
I read the docs, but I still don't understand how I'm supposed to split my routes so that only some plugins apply to them.
Here's what I've got:
import fastify from 'fastify'
import bookingsRoutes from './routes/bookings'
const server = fastify({
logger: process.env.NODE_ENV !== 'production',
trustProxy: '64.225.88.57', // DigitalOcean load balancer
})
server.get('/health', (_, reply) => {
reply.send("OK")
})
server.register(bookingsRoutes)
server.listen(process.env.PORT || 3000, '0.0.0.0', (err, address) => {
if (err) {
server.log.error(err)
process.exit(1)
}
server.log.info(`Server listening at ${address}`)
})
// ...
const plugin: FastifyPluginAsync = async api => {
await Promise.all([
api.register(dbPlugin),
api.register(authPlugin),
])
const {db,log} = api
api.route<{Body:BookingRequestType,Reply:BookingType}>({
url: '/bookings',
method: 'POST',
async handler(req, res) {
console.log('got user',req.user)
}
})
}
export default fp(plugin, '3.x')
I thought by registering dbPlugin
and authPlugin
inside the booking routes plugin that it would only apply to those routes, but that doesn't seem to be right. It seems to be applying to /health
too.
Also not sure if I should be await
ing the 2 register functions like that but they return promises and that seems to be the only way to get the db
object back out of them...
What's the proper way to do this?
Upvotes: 2
Views: 3370
Reputation: 12900
Start from this snippet:
const fastify = require('fastify')({ logger: true })
fastify.register(async function plugin (privatePlugin, opts) {
privatePlugin.addHook('onRequest', function hook (request, reply, done) {
if (request.headers['x-auth'] === '123') {
done()
} else {
done(new Error('wrong auth'))
}
})
privatePlugin.get('/', async (request, reply) => {
return { private: 'private' }
})
})
fastify.register(async function plugin (publicPlugin, opts) {
publicPlugin.get('/', async (request, reply) => {
return { public: 'public' }
})
})
fastify.listen(8080)
This shows how to create a:
all the routes registered to the privatePlugin
will inherit the onRequest
hook - the authentication check.
The publicPlugin
will not because it is a privatePlugin
's sibling. Read here for more detail
Why isn't fastify smart enough to tell which plugin has already been included so that I can list all the dependencies explicitly?
Because in Fastify you can register multiple times the same plugins with different configurations but you must check if:
fastify-mongodb
does within the namespace
configuration)It is a design choice, otherwise, it would be much more confusing in complex applications.
Edit after comments:
The auth plugin should focus on authorization only and it should not care about the database.
In this case I would change your code like so:
// auth-plugin.js
const fp = require("fastify-plugin");
const plugin = async (api, options) => {
api.addHook("preHandler", async (req, reply) => {
if (!req.user) {
throw new Error("Must be logged in");
}
});
};
module.exports = fp(plugin, {
name: 'org-auth-plugin',
dependencies: ['foo-db-plugin']
})
and
const fp = require("fastify-plugin");
const plugin = async (api, options) => {
api.decorate("db", "I'm a database");
// TODO: create/connect to database
};
module.exports = fp(plugin, {
name: 'foo-db-plugin'
})
In this way you will be warned during the startup that your org-auth-plugin
needs the db plugin to work correctly.
Upvotes: 4