Express 利用 HTTP 动作提供一套提示性强、有表现力的路由 API。打个比方,如果想要处理某个路径为 /user/12 的账号,我们能像下面这样来定义路由。关联到命名占位符(named placeholders)的值可用 req.params 来访问。
复制代码 代码如下:
app.get('/user/:id', function(req, res){
res.send('user ' + req.params.id);
});
路由是一个在内部被编译为正则的字符串。譬如,当 /user/:id 被编译,一个简化版本的正则表达弄大概如下:
复制代码 代码如下:
// 修改一下官方的这个字符串
/\/user\/([^\/]+)\/?/
正则表达式可以传入应用于复杂的场景。由于通过字面量正则表达式捕获的内容组是匿名的,我们可能直接通过 req.params 来访问它们。因此,我们捕获的第一组内容将是 req.params[0],同时第二组是紧接着的 req.params[1]。
复制代码 代码如下:
app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
res.send(req.params);
});
Curl 针对上述定义路由的请求:
复制代码 代码如下:
$ curl :3000/user
[null,null]
$ curl :3000/users
[null,null]
$ curl :3000/users/1
["1",null]
$ curl :3000/users/1..15
["1","15"]
下面是一些路由的实例,关联到他们可能使用到的路径:
复制代码 代码如下:
"/user/:id"
/user/12
"/users/:id?"
/users/5
/users
"/files/*"
/files/jquery.js
/files/javascripts/jquery.js
"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js
"/user/:id/:operation?"
/user/1
/user/1/edit
"/products.:format"
/products.json
/products.xml
"/products.:format?"
/products.json
/products.xml
/products
"/user/:id.:format?"
/user/12
/user/12.json
举个例子,我们可以使用 POST 发送 json 数据,通过 bodyParser 这个可以解析 json 请求内容(或者其他内容)的中间件来返回数据,并将返回结果存于 req.body 中:
复制代码 代码如下:
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
app.post('https://www.jb51.net/', function(req, res){
res.send(req.body);
});
app.listen(3000);
通常我们可以使用一个像 user/:id 这样,没有(命名)限制的“傻瓜”式的占位符。然而比方说,我们要限制用户 id 只能是数字,那么我们可能使用 /user/:id([0-9]+),这个将仅当占位符是包含至少一位数字时才生效(适配,match)。
八、进路控制(Passing Route Control)
我们可以通过调用第三个参数,next() 函数,来控制下一个适配的路由。如果找不到适配,控制权将会传回给 Connect,同时中间件将会按在 use() 中添加的顺序被依次调用。道理同样适应于多个定义到同一路径的路由,他们将会依次被调用直到其中某个不调用 next() 而决定做出请求响应。
复制代码 代码如下:
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if (id) {
// do something
} else {
next();
}
});
app.get('/users', function(req, res){
// do something else
});
app.all() 方法只调用一次就可以方便地把同样的逻辑到所有 HTTP 动作。下面我们使用它来从伪数据中提取一个用户,将其赋给 req.user。
复制代码 代码如下:
var express = require('express')
, app = express.createServer();
var users = [{ name: 'tj' }];
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('cannot find user ' + req.params.id));
}
});
app.get('/user/:id', function(req, res){
res.send('viewing ' + req.user.name);
});
app.get('/user/:id/edit', function(req, res){
res.send('editing ' + req.user.name);
});
app.put('/user/:id', function(req, res){
res.send('updating ' + req.user.name);
});
app.get('*', function(req, res){
res.send(404, 'what???');
});
app.listen(3000);
九、中间件
使用的 Connect 中间件(属性)通常伴随着你的一个常规 Connect 服务器,被传到 express.createServer() 。如:
复制代码 代码如下:
var express = require('express');