简介
将其它应用程序作为中间件挂载,传递给 mount()
函数的路径参数暂时从 URL
里剥离出来,直到堆栈释放。对于创建不管用于那个路径且功能正常的整个 app
或 中间件是很有用。
安装
$ npm install koa-mount
挂载应用程序
把整个应用程序挂载到一个特定的路径上,例如,你可以在/blog
目录挂载一个博客程序,博客程序使用一个匹配如/
、/posts
的路由,挂载后,这些路由将恬当地表现为/blog/
、/blog/posts
。
const mount = require('koa-mount');
const Koa = require('koa');
// hello
const a = new Koa();
a.use(async function (ctx, next){
await next();
ctx.body = 'Hello';
});
// world
const b = new Koa();
b.use(async function (ctx, next){
await next();
ctx.body = 'World';
});
// app
const app = new Koa();
app.use(mount('/hello', a));
app.use(mount('/world', b));
app.listen(3000);
console.log('listening on port 3000');
尝试下面的请求:
$ GET /
Not Found
$ GET /hello
Hello
$ GET /world
World
挂载中间件
把中间件挂载到一个特定的路径上,中间件独立于这个路径动作。
const mount = require('koa-mount');
const Koa = require('koa');
async function hello(ctx, next){
await next();
ctx.body = 'Hello';
}
async function world(ctx, next){
await next();
ctx.body = 'World';
}
const app = new Koa();
app.use(mount('/hello', hello));
app.use(mount('/world', world));
app.listen(3000);
console.log('listening on port 3000');
可选的路径
挂载函数mount()
的路径参数是可选的,默认值是/
app.use(mount(a));
app.use(mount(b));
调试
把DEBUG
环境变量添加到koa-mount
白名单调试输出:
$ DEBUG=koa-mount node myapp.js &
$ GET /foo/bar/baz
koa-mount enter /foo/bar/baz -> /bar/baz +2s
koa-mount enter /bar/baz -> /baz +0ms
koa-mount enter /baz -> / +0ms
koa-mount leave /baz -> / +1ms
koa-mount leave /bar/baz -> /baz +0ms
koa-mount leave /foo/bar/baz -> /bar/baz +0ms
示例
下面这个例子阐述了挂载几个应用程序,你如何实现串联效果。
/**
* This example illustrates how you may
* implement a cascading effect using
* several mounted applications that
* are not aware of where they are mounted:
*
* GET /foo
* GET /foo/bar
* GET /foo/bar/baz
*/
const mount = require('koa-mount')
const Koa = require('koa')
const app = new Koa()
const a = new Koa()
const b = new Koa()
const c = new Koa()
a.use(async function (ctx, next) {
await next()
if (!ctx.body) ctx.body = 'foo'
})
b.use(async function (ctx, next) {
await next()
if (!ctx.body) ctx.body = 'bar'
})
c.use(async function (ctx, next) {
await next()
ctx.body = 'baz'
})
app.use(mount('/foo', a))
a.use(mount('/bar', b))
b.use(mount('/baz', c))
app.listen(3000)
console.log('listening on port 3000')
下面示例说明以便集中地记录日志等等,应用程序错误如何向上游传播。
/**
* This example illustrates how application
* errors propagate upstream for
* centralized logging etc.
*/
const mount = require('koa-mount')
const Koa = require('koa')
const a = new Koa()
const b = new Koa()
const c = new Koa()
a.use(async function (ctx, next) {
await next()
})
b.use(async function (ctx, next) {
await next()
})
c.use(async function (ctx, next) {
await next()
throw new Error('tobi escaped!')
})
a.use(mount(b))
b.use(mount(c))
// suppress stderr output if you want
a.outputErrors = false
// errors will propagate to the upstream app,
// however you can still use the "error" listener
// in subapps more specific behaviour, just keep
// in mind that it should be used in an unobtrusive way,
// since most decisions should be made by the parent app.
a.on('error', function (err, ctx) {
console.log('%s %s: sending error "%s" to alert service',
ctx.method,
ctx.path,
err.message)
})
a.listen(3000)
console.log('listening on port 3000')
错误将向上游程序传播。但是,你仍然可以在子程序中使用error
侦听更具体的行为。请记住,在子程序中它应该以一种不引人注目的方式使用,因为大多数决策都应该由父应用程序作出。
下面这个例子阐述了如何像挂载应用程序一样挂载中间件。
/**
* This example illustrates how middleware
* may be mounted just like applications.j
*/
const mount = require('koa-mount')
const Koa = require('koa')
async function hello (ctx, next) {
await next()
ctx.body = 'Hello'
}
async function world (ctx, next) {
await next()
ctx.body = 'World'
}
const app = new Koa()
app.use(mount('/hello', hello))
app.use(mount('/world', world))
app.listen(3000)
console.log('listening on port 3000')
下面这个例子阐述了如果你只想结合行为,在没有路径时如何挂载应用程序。
/**
* This example illustrates how applications
* may be mounted without a pathname prefix
* if you simply wish to combine behaviours.
*/
const mount = require('koa-mount')
const Koa = require('koa')
// GET /hello
const a = new Koa()
a.use(async function (ctx, next) {
await next()
if (ctx.path === '/hello') ctx.body = 'Hello'
})
// GET /world
const b = new Koa()
b.use(async function (ctx, next) {
await next()
if (ctx.path === '/world') ctx.body = 'World'
})
// app
const app = new Koa()
app.use(mount(a))
app.use(mount(b))
app.listen(3000)
console.log('listening on port 3000')
下面示例阐述的是将应用程序挂载到给定路径的典型模式。
/**
* This example illustrates the typical
* pattern of mounting an application
* to a given pathname prefix.
*
* GET /hello
* GET /world
*/
const mount = require('koa-mount')
const Koa = require('koa')
// hello
const a = new Koa()
a.use(async function (ctx, next) {
await next()
ctx.body = 'Hello'
})
// world
const b = new Koa()
b.use(async function (ctx, next) {
await next()
ctx.body = 'World'
})
// app
const app = new Koa()
app.use(mount('/hello', a))
app.use(mount('/world', b))
app.listen(3000)
console.log('listening on port 3000')