一个HTTP服务器就是用来接收来自用户的HTTP请求和响应用户请求的,Express通过路由实现了不同HTTP请求方法的接收,在响应用户请求之前,服务器可能需要根据用户传递的参数不同而已。
1. Express路由定义与参数接收
1.1 Express路由定义
router.all()
在Express中,可以使用router.all()方法定义一个用于所有类型HTTP请求方法的路由:
router.all(path, [callback, ...] callback)
通过router.all()方法定义的路由,可以在所有HTTP请求方法中使用。利用这一特点,在“全局化”匹配指定路径或部分路径或作意匹配时非常有用。在router.all()路由中,可做一些通用的操作(如:验证用户身份等),并可以通过调用netx()方法进行后续路匹配。
如,在以下示例中requireAuthentication和loadUser分别用于验证用户身份和加载用户信息。我们需要在用户所有类型的HTTP请求和所有的请求路径中进行这两项操作:
router.all('*', requireAuthentication, loadUser);
等价于:
router.all('*', requireAuthentication)
router.all('*', loadUser);
有时候只需要在部分URL中做一些处理,如在/api开头的路由中进行匹配和处理:
router.all('/api/*', requireAuthentication);
router.METHOD()
Express中针对某一种HTTP请求方法设置路由,使用router.METHOD()方法:
router.METHOD(path, [callback, ...] callback)
router.METHOD()设置某一种HTTP请求方法的路由,METHOD表示HTTP请求方法,使用如GET、PUT、POST等请求方式小写表示,分别表示为router.get()、router.put()、 router.post():
router.get('/', function(req, res){
res.send('hello world');
});
定义路由时,可以使用正则表达式。如,要匹配GET /commits/71dbb9c和GET /commits/71dbb9c..4c084f9的路由形式,匹配规则如下:
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function(req, res){
var from = req.params[0];
var to = req.params[1] || 'HEAD';
res.send('commit range ' + from + '..' + to);
});
1.2 参数接收
在Express.js中,接收用户参数有三种形式:路由(路径)参数、URL 查询字符串参数、body(HTTP请求体)参数。
路由(路径)参数
设置如下一下路由:
router.get('/user/:id', function(req, res, next){
// 接收路由参数
req.params.id
});
路由参数通过req.params取值。在上面示例中,/user/:id路由中的:id参数是一个变量,可以通过req.params.id接收这个变量的值。
URL 查询字符串参数
URL 查询字符串参数是在指在URL中传递的参数,这些参数不需要在路由中设置,接收查询字符串参数使用req.query对象。当我们发送一个GET /user?id=1&name=myName请求时,接收这个对象使用如下方法:
console.log(req.query); // {id:'1', name:'myName'}
body(HTTP请求体)参数
body参数通过req.body(需要body-parser模块处理)对象接收,body参数是指HTTP请求体中的参灵敏。在HTTP请求方法中,只有POST、PUT、PATCH三种方法存在请求体,在其它请求方法中req.body是一个空对象({})。
POST使用最多的是form表单数据的接收(form表单只能使用GET、POST两种请求方式),而PUT和PATCH方法一般用于一些REST标准的API中。
req.body; // 接收HTTP请求体中的参数
2. 不同HTTP请求方法中的参数接收
接下来我们会使用GET、HEAD、 POST、PUT、DELETE、 CONNECT、OPTIONS、TRACE、PATCH9种HTTP请求方法来访问Express.js应用,目的是测试Express.js对各类HTTP请求的支付情况和各种HTTP请求方式的参数接收情况。
2.1 定义路由和客户端代码
使用request来实现一个HTTP客户端,我们会在这个客户端中分别添加:路由参数、URL查询字符串参数和body 参数,通过变更options.method参数分别实现了不同方式的HTTP请求:
var request = require('request');
/**
* 请求的URL中包含一个query参数和一个params参数
* 请求方法分别使用:'GET'|'HEAD'|'POST'|'PUT'|'DELETE'|'CONNECT'|'OPTIONS'|'TRACE'|'PATCH'
*/
var options ={
uri: 'http://127.0.0.1:3000/node?q='+encodeURIComponent('IT笔录'),
method: 'GET',
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
body: 'form=niefengjun.cn' // 一个body参数
}
request(options, callback)
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log(info);
}
}
在Express应用中,定义如下一个路由,客户所有的类型的HTTP请求都会发送到这个路由中。这个路由使用router.all()
/* 一个处理所有请求的中间件 */
router.all('/:path', function(req, res, next){
// 客户端请求使用的HTTP方法
var method = req.method;
// URL 查询字符串参数
var query = req.query;
// body(HTTP请求体)参数
var body = req.body;
// 路由(路径)参数
var params = req.params;
console.log(method);
console.log('query:', query);
console.log('body:', body);
console.log('params:', params);
next();
});
2.2 HTTP请求的接收
下面是HTTP客户端发送不同类型HTTP请求后,Express应用对各种请求的方式的参数接收情况:
GET请求
GET
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
GET /node?q=IT%E7%AC%94%E5%BD%95
HEAD请求
HEAD
query:{ q: 'IT笔录' }
body:{}
params:{ path: 'node' }
HEAD /node?q=IT%E7%AC%94%E5%BD%95
HEAD请求时,客户端不能包含body参数,否则会报错。
POST请求
POST
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
POST /node?q=IT%E7%AC%94%E5%BD%95
PUT请求
PUT
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
PUT /node?q=IT%E7%AC%94%E5%BD%95
DELETE请求
DELETE
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
DELETE /node?q=IT%E7%AC%94%E5%BD%95
CONNECT请求
// 无返回,request模块不支付
OPTIONS请求
OPTIONS
query:{ q: 'IT笔录' }
body: { from: 'niefengjun.cn' }
params:{ path: 'node' }
OPTIONS /node?q=IT%E7%AC%94%E5%BD%95
TRACE请求
TRACE
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
TRACE /node?q=IT%E7%AC%94%E5%BD%95
PATCH请求
PATCH
query:{ q: 'IT笔录' }
body:{ from: 'niefengjun.cn' }
params:{ path: 'node' }
PATCH /node?q=IT%E7%AC%94%E5%BD%95
2.3 总结
经过上面的测试我们可以得出以下结论:
Experss与HTTP标准不尽一致,除HEAD、CONNECT请求方法外,其它请求方式均支付三种参数接收方式。Express在处理各类HTTP请求时没有严格按HTTP标准执行,在HTTP标准中只有POST、PUT、PATCH三种请求方式中存在HTTP请求体(即:body参数),但在Express及其中间件解析时,除HEAD方法外并没有区分body参数- 除不被支持的
CONNECT方法外,其它所有接收方式均支付URL查询字符串参数和路由参数。
在使用Express应用和Express路由及中间件时,建议按HTTP标准进行处理和参数传递。尤其是body参数,在标准中只有POST、PUT、PATCH三种方式可以传递body HTTP请求体,除这三种方式外,建议不要使用req.body方法。
