目前使用node.js搭建web服务,可以使用原生的http模块进行搭建,也有express、restify和fastify。fastify框架相对于前两中框架,更加轻巧、数据解析能力更强。先用fastify框架搭建一个web服务。
搭建之前先说下将要使用到的API。
在fastify框架中,它将一切资源都认为是一个插件,包括静态资源、路由、服务等。register将会创建一个新的作用域,如果你需要在register中使用decorate,这个变化将不会在register实例上展现。下文将讲述,如何处理这种情况。
使用decorate可以对register实例的属性进行修改。
//app.js
const fastify = require('fastify')();
fastify.addHook('onRequest', (req, res, next) => {
console.log(req.url);
next();
})
fastify.register(require('./route/our-db-connector'), {
url: 'mongodb://***'
});
fastify.register(require('./route/our-first-route'),{ prefix: '/v1' });
fastify.listen(3000, function (err) {
if (err) throw err
fastify.log.info(`server listening on ${fastify.server.address().port}`)
})
//our-db-connector.js
const fp = require('fastify-plugin')
const MongoClient = require('mongodb').MongoClient;
async function db (fastify, options) {
const url = options.url
delete options.url
const db = await MongoClient.connect(url, options)
fastify.decorate('mongo', db)
}
module.exports = fp(db)
在这里需要注意的是decorate这个API的使用,因为register会创建新的作用域,但同时需要在fastify实例(即app.js)上绑定db对象。如果想要在register中使用decorate扩展基础服务中的fastify,你需要告诉fastify不再创建新的作用域,这里有两种解决方案。
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, next) {
fastify.decorate('utility', () => {})
next()
}, '0.x')
function yourPlugin (fastify, opts, next) {
fastify.decorate('utility', () => {})
next()
}
yourPlugin[Symbol.for('skip-override')] = true
module.exports = yourPlugin
在这里推荐使用方案一,便于维护。本文使用的是方案一。
//our-first-route.js
let opts = {
name:{
schema:{
body:{
type:'string',
}
}
}
}
async function routes (fastify,options,next) {
const collection = fastify.mongo.collection('user')
fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})
fastify.get('/name/:name',opts.name,async (request,reply) =>{
return {name:name}
})
}
module.exports = routes
node app.js
打开浏览器,在地址栏输入127.0.0.1:3000/v1。
为什么是v1?这是在app.js中有设置前置的原因,fastify.register(require(‘./route/our-first-route’),{ prefix: ‘/v1’ });