Express中method-override模块详解(一): 使用

*注意,如果你在使用Node.js实战(Mike Catelon)这本书,一定注意下书中所用的connect和experss版本。总的来说,这个两个版本都太老了,学习时最好使用最新的版本。因为很多开源框架都是基于新版本而来,你会发现书中的api在很多实际项目已经不能用了。

在本博文中,我使用的express版本为4。method-override版本为2.2.0.


1. 为什么需要method-override

这个需求主要来自前端的form。比如我们在后端提供一个针对HTTP PUT的API, 前端的数据提交时,我们自然希望FORM能够产生一个PUT请求。然而,浏览器的FORM只能GET或者POST。怎么办? 改变后端的API吗?如果这个API是别的服务商提供,我们无权更改呢?这时,我们就需要method-override来帮助我们。

先看一个例子吧 。

var express = require('express'),
	bodyParser = require('body-parser');

	function edit (req,res,next) {
		if(req.method !== 'GET') {
			return next();
		}
		res.setHeader('Content-Type','text/html');
		res.write('<form method="put">');
		res.write('<input type="text" name=user[name] value="Tobi"/>');
		res.write('<input type="submit" value="Update"/>')
		res.write('</form>');
		res.end();
	}

	function update(req,res,next) {
		if(req.method !== 'PUT') return next();
		res.end('update ' + req.body.user.name);
	}

	var app = express();
		app.use(bodyParser())
			.use(edit)
			.use(update)
			.listen(3000,function(){
				console.log('start on port 3000');
			});
访问http://localhost:3000, 点击Update。 什么也没有发生,因为浏览器将PUT 转换成了GET请求。 怎么办?这时我们就需要用到method-override了


2. 怎么使用method-override

2.1 使用隐藏控件

从上面的例子可以看到,由于在FORM中我们只能发送GET或者POST请求,限制了我们使用其他谓词比如PUT,DELETE等,因此我们需要同过method-override将GET或者POST改成其他谓词PUT,DELETE等。

针对上面的例子,介绍一种常规的处理方法。可以在FORM中加入一个名为_method(别的名字也可以)的隐藏输入控件,让这个控件承载我们实际需要的谓词。然后在服务器端用这个控件的谓词进行方法改写。

代码如下:

var express = require('express'),
	bodyParser = require('body-parser'),
	methodOverride = require('method-override');

	function edit (req,res,next) {
		if(req.method !== 'GET') {
			return next();
		}
		res.setHeader('Content-Type','text/html');
		res.write('<form method="post">');
		res.write('<input type="hidden" name="post_to_put" value="put"/>');
		res.write('<input type="text" name=user[name] value="Tobi"/>');
		res.write('<input type="submit" value="Update"/>')
		res.write('</form>');
		res.end();
	}

	function update(req,res,next) {
		if(req.method !== 'PUT') return next();
		res.end('update ' + req.body.user.name);
	}

	var app = express();
		app.use(bodyParser())
			.use(methodOverride(function(req,res){
				if(req.body && typeof req.body === 'object' && 'post_to_put' in req.body){
					var method = req.body.post_to_put;
					delete req.body.post_to_put;
					return method.toUpperCase();
				}
			}))dai
			.use(edit)
			.use(update)
			.listen(3000,function(){
				console.log('start on port 3000');
			});

分析代码,我们看到,FORM提交还是使用POST, 不过我们在FORM中增加了一个隐藏输入,名为POST_TO_PUT,值为PUT。然后在服务器端,我们提供了自定义的改写规则:

1 从request中获取body数据(因此body-parser需要在此前使用),BODY数据里面包含着POST_TO_PUT

2 从body数据中拿到名为POST_TO_PUT的值, 这个值就是我们提供的实际谓词,这里是PUT

3 从body数据中删除POST_TO_PUT属性 (后续使用body数据,就无需考虑这个POST_TO_PUT属性了,它已完成了使命)

4  返回POST_TO_PUT属性值得大写格式

好了,跑一下代码,再次访问http://localhost:3000,提交数据。这次,服务器终于正确返回值了。点击这里,在线运行程序

2.2 使用查询更改

通过2.1介绍的方法,我们可以使用一个非常规则的RESTful API从而达到方法改写的目的。然而这个方式需要在前端引入冗余代码(前端需要编写专门为方法改写而增加的影藏控件)。现在,介绍另一种方法,同过查询URL改写。

1. 首先我们需要为method-override提供一个key以便用得到改写的方法。

app.use(methodOverride('_method')

这里我们提供的键值是_method。当然也可以是其他字符串,但是这个字符串不能以 X- 开始。

2.修改前端代码

<form method="post" action='?_method=PUT'>
这样就好了。点击这里,在线运行程序


接下来,我们要深入method-override源码,仔细探究其中的奥秘

阅读更多
个人分类: nodejs
上一篇在connect中编写自己的路由器及最佳实践
下一篇Express中method-override模块详解(一): 源码
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭