OnceIO是OnceDoc系统的底层Web框架,它可以实现模板文件、静态文件的全缓存,运行起来完全不需要I/O操作,并且支持客户端缓存优化,GZIP压缩等(只在第一次压缩),拥有非常好的性能,为您节约服务器成本。它可以让你对Web进行分布式存储,即一个扩展包里即可包含前端、后端和数据库定义,只需通过添加/删除目录的方式就可实现功能删减,实现真正的模块化扩展。这里是介绍如何使用OnceIO的一系列文章。
OnceIO 是一个自身功能极简,完全由路由、中间件和Handler构成的 web 开发框架:一个 OnceIO 应用本质上就是在调用各种中间件和Handler。
中间件是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)),并将应用的请求-响应循环传向下一个中间件。
一个应用的请求-响应循环如下图所示,由请求对象、响应对象、中间件和 handler 构成:
Handler 针对请求发出响应,循环终结于此,一个请求-响应循环只会由一个 handler处理;但每个请求在到达 handler 之前会依次经过许多中间件,如Session、Securty(登录认证)、表单解析等都是典型的中间件,NoceJS中的MiddlerWare与Java中的Filter和.NET中的HttpModule概念类似。一个请求-响应循环也可以不经过中间件,比如说静态CSS/JS文件就没有执行Session、认证中间件的必要。
中间件的功能包括:
- 执行任何代码。
- 修改请求和响应对象。
- 终结请求-响应循环。
- 调用堆栈中的下一个中间件。
如果当前中间件没有终结请求-响应循环,则必须调用 req.filter.next() 将控制权交给下一个中间件,否则请求就会挂起。
下面我们将以 Lesson 1 中简单的 'Hello World' 应用为例,为其增加两个中间件:能在终端输出一条简单消息的 myLogger 和能在网页上显示 HTTP 请求的时间戳的 requestTime.
var onceio = require('../onceio/onceio')
var app = onceio()
app.get('/', function(req, res) {
res.end('Hello World!')
})
中间件函数 myLogger
myLogger 函数会在 request 经过它时在 console 界面输出“LOGGED”。myLogger 函数的代码如下:
var myLogger = function(req, res) {
console.log('LOGGED')
req.filter.next()
}
//or
var myLogger = function(req, res, next) {
console.log('LOGGED')
next()
}
把 myLogger 添加到应用中:
var onceio = require('../onceio/onceio')
var app = onceio()
var myLogger = function(req, res) {
console.log('LOGGED')
req.filter.next()
}
app.use(myLogger)
app.get('/', function(req, res) {
res.end('Hello World!')
})
每当应用收到请求时,它都会在终端输出“LOGGED”:
中间件的加载顺序很重要:中间件必须要被首先加载并且被首先执行,否则在请求到达中间件之前请求-响应循环就被终止了,中间件将不被执行。
中间件函数 requestTime
接下来,我们创建一个叫做 requestTime 的中间件函数:
var requestTime = function(req, res) {
req.requestTime = Date.now()
req.filter.next()
}
把 requestTime 添加到应用中:
var onceio = require('../onceio/onceio')
var app = onceio()
var requestTime = function(req, res) {
req.requestTime = Date.now()
req.filter.next()
}
app.use(requestTime)
app.get('/', function(req, res) {
var responseText = 'Hello World!<br>';
responseText += '<small>Requested at: ' + req.requestTime + '</small>';
res.send(responseText);
})
每当应用收到请求时,它都会在浏览器显示请求的时间戳:
我们在这里只演示了两个简单的中间件,事实上中间件的种类和功能非常多样,例如,app.use() 函数可以有多达三个参数:
app.use('/file', function(req, res) {
var user = req.session.get('user')
if (!user || !user.username) {
res.end('No permission')
return
}
res.cache(0)
req.filter.next()
}, { session: true })
其中第一个参数指定所有以“/file”开头的 URL(发起的请求)都会经过这个中间件;第三个参数指定这个中间件需要session支持。因为onceio的session对象可能是存放在数据库中的,从数据库获取session会有一定的性能损失,所以在设计时您可根据情况,比如说在用户界面、管理后台添加session解析支持。
中间件能访问请求对象、响应对象、堆栈中下一个中间件和整个 OnceIO API,因此它的用法拥有无限的可能性。
OnceIO地址: https://github.com/OnceDoc/onceio