1、我们原生的创建服务,设置监听,处理请求之前已经写过。这里介绍的express可以理解是基于基础之上的一个框架,既然是框架,里面肯定封装了很多东西,我们用的时候会方便很多,到底方便在哪里,我们写个例子就知道了。
——第一步,到我们的项目目录里面安装express这个第三方模块,使用npm install express。安装结束后,在我们的nodetest项目里面,就会有一个node_modules文件夹,这个项目需要安装的模块都会在这边,这个之前讲过。这里面除了express之外,还下载安装了一大推它的依赖。
——这里我们还安装了一个东西,就是express的一个中间件,用来处理静态文件请求的,npm install express-static。什么意思呢?一般情况下我们的请求要么是一个符合RESTFUL的接口,有时候它会是一个文件,比如html或css或png等。这个时候,我们判断路径那么会比较费力,如果能直接判断一下它是否是静态文件,如果是,直接去我们指定的文件夹里面去找,这样我们就不用判断路径然后处理这一类的请求了。
注意:我们直接安装express-static的话,运行有可能报这个错误:
'The header content contains invalid characters'原因不太清楚,但换一个版本就可以了。我们如果已经安装了最新的版本,卸载它,此时最新的貌似是1.2.4。然后安装特定的版本:
npm install express-static@1.1.0一个登陆的例子:
const express = require('express'); const expressStatic = require('express-static'); const bodyParser = require('body-parser'); const multer = require('multer'); var server = express(); server.listen(1337); server.use(bodyParser.json()); // for parsing application/json // 只有加了下面这句,req.body里面才有数据,不然那默认是undefined server.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded //server.use(multer()); // for parsing multipart/form-data // 除了use,还有get和post和delete等,当然use是全部都会响应 server.post('/login',function(req,res){ // send比write强大的地方在于,write只能发String或Buffer,send还能发送json等 res.send("success"); // 如果是get请求,那么直接用req.query下面就能获得一个字典,直接用req.query.username就能获得username参数的值 // post请求需要解析body,{ username: 'aaa', pwd: 'aaa' } console.log(req.body.username); // aaa res.end(); }); server.use(expressStatic('./www'));注:上面如果报这个错误:
'app.use() requires middleware functions'一般是multer的版本有问题,暂时先不管里面为什么有冲突,我们换一个版本即可,卸载之前的,然后安装下面特定的版本:
npm install multer@0.1.82、在sublime里面,直接可以用ctrl + b编译执行。
3、我们再来看一下链式操作。链式操作也就是我们使用server.use()的时候能够执行多个。怎么才能执行多个,就需要用到next()去放行。我们来看个例子,静态文件仍然是个登录的表单,post请求。
const express = require('express'); const expressStatic = require('express-static'); const querystring = require('querystring'); var server = express(); server.listen(1337); // 这个use里面没有第一个参数,所以默认是拦截所有的请求 // 多了一个next参数,就是用来放行到下一步的,可以不加这个next // 但是中间件的话,一般都有这个next,因为中间件只是在中间拦截做了一些操作而已,最终还要放行继续执行后面代码的 server.use(function(req,res,next){ var str = ''; req.on('data',function(data){ str += data; }); req.on('end',function(){ // 这里给req一个body属性,会继续传下去,只要下面还用的是同一个req,就能拿到里面的body属性 req.body = querystring.parse(str); // 放行,这就是链式操作的精华 next(); }); }); server.use('/login',function(req,res){ console.log(req.body); res.end(); }); server.use(expressStatic('./www'));——这里的第一个server.use()基本拦截一切,拦截完并不是直接结束,它最终利用next()放行,让后面的满足server.use()的继续拦截。这就是链式操作。
4、我们继续看上面的,上面的输出结果是:
{ username: 'aaa', pwd: 'aaa' }这个结果就是我们使用body-parser这个(中间件)处理得到的结果,效果是一样的。其实在上面,我们模仿写了一个中间件。只不过我们没有把这段代码放在单独的js文件里、发布、下载安装、引用而已。
——至此,我们应该知道,为什么不加server.use(bodyParser.urlencoded({ extended: true }));的时候,我们用req.body是个undefined,因为根本req下面根本没有body这个属性。加了那一行代码之后,相当于利用中间件处理了一遍,处理的时候,它给我们的req加了一个body的属性,所以我们在后面才能用body这个属性。
5、接下来,我们看看比较重要的cookie和session。
——写一个cookie就是这么简单,直接用res.cookie()就行。里面的几个参数需要注意一下就行。
const server = require('express')(); const expressStatic = require('express-static'); server.listen(1337); server.use('/',function(req,res,next){ // path表示哪个路径下可以读取这个cookie,后面的参数是过期时间,毫秒 res.cookie('username','erci',{path:'/',maxAge:30*24*3600*1000}); res.send('ok'); }); server.use(expressStatic('./www'));——我们读取cookie的话,也用一个中间件吧,安装cookie-parser。
const server = require('express')(); const expressStatic = require('express-static'); // 先安装cookie-parser const cookieParser = require('cookie-parser'); server.listen(1337); // 这一步本质上相当于给req增加了一个cookies属性,我们后面可以直接拿到这个属性,这个属性就是我们浏览器保存的cookie server.use(cookieParser()); server.use('/',function(req,res,next){ console.log(req.cookies); res.send('ok'); }); server.use(expressStatic('./www'));控制台的打印结果如下,好吧,它把我们之前localhost下面的都输出来了:
{ 'yncTech.LoginNo': 'admin', _ga: 'GA1.1.1121877435.1500283703', username: 'erci' }6、我们可以对cookie进行签名,签名之后的话,值已经不是一个纯粹的值了,而是被签名后的值了。用法如下:
——当然,我们如果还用req.cookies的话,得到的值就是签名后的值,但是我们想要的是那个被签名之前的值,比如eric,那么久需要用req.signedCookies。
const server = require('express')(); const expressStatic = require('express-static'); const cookieParser = require('cookie-parser'); server.listen(1337); // 如果cookie的值被签名过的话,我们直接获取只能拿到签名后的一串值,如果要原始的值,那么解析的时候也要给相同的签名 server.use(cookieParser('my_secret_key_is_123456')); server.use('/',function(req,res,next){ // 因为上面cookie解析的时候已经加了加密key,所以其实它默认帮我们生成了下面这句代码,可以省略 // req.secret='my_secret_key_is_123456'; res.cookie('username','eric',{ path:'/',maxAge:30*24*3600*1000,signed:true}); // 如果cookie是被签名果的,那么我们获取的时候不能直接用req.cookies(它是空的),所有的数据在req.signedCookies里面 console.log(req.signedCookies); res.send('ok'); }); server.use(expressStatic('./www'));7、清除cookie的代码是:
req.clearCookie["xxx"];8、安装cookie-session。然后下面一段代码。
const server = require('express')(); const expressStatic = require('express-static'); const cookieSession = require('cookie-session'); server.listen(1337); // 初始化一个keys var keyArr = [] for (var i = 0; i < 10000; i++) { keyArr.push('sig_' + Math.random()); } server.use(cookieParser()); server.use(cookieSession({ // 存在浏览器端的cookie的名字 name:'mySess', keys:keyArr, maxAge:30*24*3600*1000 })); server.use('/',function(req,res){ if (req.session['username']==null) { req.session['username']='eric'; res.send('第一次登录'); }else{ res.send('你已经登录了'); } }); server.use(expressStatic('./www'));——第一次执行请求的时候,界面是第一次登录,我们看一下cookie里面有2个,一个是我们存的sessionId之类的,一个是安全保护之类用的,具体的这里不展开。
9、最后,我们要删除session的话,用这个代码:
delete req.session['xxx'];