Express提供的大部分功能是通过中间件函数完成的,这些中间件函数在Node.js收到请求的时点和发送响应的时点之间执行。Express的Connect模块提供了中间件框架,可以方便的在全局或路径级别或为单个路由插入中间件功能。Express建立在connect NPM模块上,提供了connect所提供的底层中间件支持。

一、在全局范围内把中间件分配给某个路径

要对所有路由指定中间件,可以在Express app对象上实现use()方法。

use([path],middleware)

path 变量可选,默认为/.意味所有的路径 middleware参数是一个函数,它的语法如下

function(req,res,next)

req:Request对象  res:Response对象  next是要执行的下一个中间件函数

var express=require('express');

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

var app=express();

app.use('/',bodyParser());

每个中间件组件都有一个构造函数,它返回相应的中间件功能。

二、把中间件分配给单个路由

可以通过把一个单独的路由放在path参数后来对其应用body-parser中间件。例如下面的代码:

var express=require('express');

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

var app=express();

app.get('/parsedRoute',bodyParser(),function(req,res))

{

res.send('This request was logged.');

}

三、添加多个中间件函数

可以根据需要在全局范围和路由上分配任意多的中间件函数。

var express=require('express');

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

var cookieParser=require('cookie-parser');

var session=require('cexpress-session');

var app=express();

app.use('/',bodyParser()).use('/',cookieParser()).use('/',session());

在分配函数的顺序就是它们在请求中被应用的顺序,一些中间件函数需要被添加在别的中间件函数前面。

四、使用query中间件

query中间件将一个查询字符串从URL转换为Javascript对象,并将其保存为Request对象的query属性。从Express4.x开始,此功能在内置请求解析器中存在,不需要额外的中间件。

五、提供静态文件服务

static中间件是很常用的Express中间件。static中间件可以直接从磁盘对客户端请求静态文件服务。可以使用static中间件支持不会改变的Javascript文件、CSS文件、图像文件和HTML文件之类的东西。

express.static(path,[options])

path:指定将在请求中引用的静态文件所在的根路径

options允许设置一下属性:

maxage:浏览器缓存maxAge(最长保存时间),以毫秒为单位,默认0.

hidden:true表示启用隐藏文件传输功能。默认false。

redirect:true表示若请求路径是一个目录,则该请求将被重定向到有一个尾随/的路径默认true。

index:根路径的默认文件名。默认为index.html.

var express = require('express');
var app = express();
app.use('/', express.static('./static'), {maxAge: **});
app.use('/images', express.static( '../images'));
app.listen();

上面实现了两个static路径:第一个把路由/映射到指定的名为static的子目录,第二个是把路由/images映射到一个对等的名为images的目录

六、处理POST正文数据

Express的body-parser中间件试图解析请求的正文中的JSON数据,把它们正确的格式化为Request对象的req.body属性。

var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.get('/', function (req, res) {
var response = '<form method="POST">' +
'First: <input type="text" name="first"><br>' +
'Last: <input type="text" name="last"><br>' +
'<input type="submit" value="Submit"></form>';
res.send(response);
});
app.post('/',function(req, res){
var response = '<form method="POST">' +
'First: <input type="text" name="first"><br>' +
'Last: <input type="text" name="last"><br>' +
'<input type="submit" value="Submit"></form>' +
'<h1>Hello ' + req.body.first + '</h1>';
res.type('html');
res.end(response);
console.log(req.body);
});
app.listen();

上面的代码在从浏览器输入地址后走get请求返回响应,提交表单采用post请求,可以通过req.body.first来获取表单数据。

七、发送和接收cookie

Express提供的Cookie-parser中间件使得处理cookie非常简单。cookie-parser中间件从一个请求解析cookie并将它们作为一个Javascript对象存储在req.cookies属性中。  express.cookie-parser([secret])

可选的secret字符串参数利用secret字符串在cookie内部签署来防止cookie的篡改。

要在响应中设置cookie,可以使用res.cookie()方法。

res.cookie(name,value,[options])

具有指定的名称和值参数的一个cookie被添加到响应中。options参数允许你设置cookie中的以下属性:

maxage:cookie过期前的生存时间

httpOnly:true表示cookie只能服务器访问,不能通过客户端Javascript访问

signed:true表示cookie将被签署,需要使用req.signedCookie对象,而不是req.cookie对象来访问它。

path:该cookie应用的路径。

var express = require('express');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser());
app.get('/', function(req, res) {
console.log(req.cookies);
if (!req.cookies.hasVisited){
res.cookie('hasVisited', '',
{ maxAge: **,
httpOnly: true,
path:'/'});
}
res.send("Sending Cookie");
});
app.listen();

八、实现会话

Express中cookie-session中间件提供了对基本会话的支持。cookie-session会话中间件在底层利用cookie-parser中间件,需要在添加cookie-session前先添加cookie-parser。res.cookie([options])

options允许设置以下属性:

key:用于标识会话的cookie名称

secret:用来签署会话cookie的字符串,用来防止cookie窃取

cookie:一个对象,定义cookie设置,包括maxage、path、httponly和signed.默认{path:'/',httpOnly:true,maxage:null}.

proxy:true将导致Express通过x-forwarded-proto设置安全cookie,信任反向代理。

当cookie-session被实现时,会话被存储为req.session对象。你对req.session做的任何更改都会跨越来自同一个浏览器的多个请求流动。

var express = require('express');
var cookieParser = require('cookie-parser');
var cookieSession = require('cookie-session');
var app = express();
app.use(cookieParser());
app.use(cookieSession({secret: 'MAGICALEXPRESSKEY'}));
app.get('/library', function(req, res) {
console.log(req.cookies);
if(req.session.restricted) {
res.send('You have been in the restricted section ' +
req.session.restrictedCount + ' times.');
}else {
res.send('Welcome to the library.');
}
});
app.get('/restricted', function(req, res) {
req.session.restricted = true;
if(!req.session.restrictedCount){
req.session.restrictedCount = ;
} else {
req.session.restrictedCount += ;
}
res.redirect('/library');
});
app.listen();

九、应用基本的HTTP身份验证

Express中间件的另一个常见用途是应用基本的HTTP身份验证。HTTP身份验证使用Authorization标头从浏览器向服务器发送编码后的用户名和密码。如果浏览器中没有存储URL的授权信息,浏览器会自动启动一个基本的登录对话框,让用户输入用户名和密码。

Express的basic-auth-connect中间件函数提供对处理基本的hTTP身份验证的支持。

var basicAuth=require('basic-auth-connect');

express.basicAuth(function(user,pass){});

传递到basic-auth-connect的函数接受用户名和密码。如果是正确的则返回true。通常在数据库中存储用户名密码,在authentication函数中检索要验证的用户对象。

对于单个路由的验证和中间件分配到单个路由是一样的。

var express = require('express');
var basicAuth = require('basic-auth-connect');
var app = express();
app.listen();
app.use(basicAuth(function(user, pass) {
return (user === 'testuser' && pass === 'test');
}));
app.get('/', function(req, res) {
res.send('Successful Authentication!');
});
var express = require('express');
var basicAuth = require('basic-auth-connect');
var app = express();
var auth = basicAuth(function(user, pass) {
return (user === 'user1' && pass === 'test');
});
app.get('/library', function(req, res) {
res.send('Welcome to the library.');
});
app.get('/restricted', auth, function(req, res) {
res.send('Welcome to the restricted section.');
});
app.listen();

十、实现会话身份验证

基于HTTP身份验证的一个主要缺点是只要证书被存储,登录就一直存在,这不是很安全。Express内的session中间件附加一个Session对象req.session到Request对象来提供会话功能。提供了下面几个方法:

regenerate([callback]) :移除并创建一个新的req.session对象,重置会话

destory([callback]):移除req.session对象

save([callback]):保存会话数据

touch([callback]):为会话cookie重置maxage计数

cookie:指定把会话链接到浏览器的cookie对象

var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var crypto = require('crypto');
function hashPW(pwd){
return crypto.createHash('sha256').update(pwd).
digest('base64').toString();
}
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser('MAGICString'));
app.use(session());
app.get('/restricted', function(req, res){
if (req.session.user) {
res.send('<h2>'+ req.session.success + '</h2>' +
'<p>You have entered the restricted section<p><br>' +
' <a href="/logout">logout</a>');
} else {
req.session.error = 'Access denied!';
res.redirect('/login');
}
});
app.get('/logout', function(req, res){
req.session.destroy(function(){
res.redirect('/login');
});
});
app.get('/login', function(req, res){
var response = '<form method="POST">' +
'Username: <input type="text" name="username"><br>' +
'Password: <input type="password" name="password"><br>' +
'<input type="submit" value="Submit"></form>';
if(req.session.user){
res.redirect('/restricted');
}else if(req.session.error){
response +='<h2>' + req.session.error + '<h2>';
}
res.type('html');
res.send(response);
});
app.post('/login', function(req, res){
//user should be a lookup of req.body.username in database
var user = {name:req.body.username, password:hashPW("myPass")};
if (user.password === hashPW(req.body.password.toString())) {
req.session.regenerate(function(){
req.session.user = user;
req.session.success = 'Authenticated as ' + user.name;
res.redirect('/restricted');
});
} else {
req.session.regenerate(function(){
req.session.error = 'Authentication failed.';
res.redirect('/restricted');
});
res.redirect('/login');
}
});
app.listen();

十一、创建自定义中间件

使用Express,可以自己创建中间件。只要提供一个接受Request对象作为第一个参数,Response对象作为第二个参数,next作为第三个参数的函数。next函数是一个通过中间件框架传递的函数,它指向下一个要执行的中间件函数,所以必须在退出自定义函数之前调next(),否则处理程序将永远不会被调用。下面demo就是自定义的一个中间件函数,这个函数在把查询字符串发送到处理程序之前把该字符串从URL中剥离。

var express = require('express');
var app = express();
function queryRemover(req, res, next){
console.log("\nBefore URL: ");
console.log(req.url);
req.url = req.url.split('?')[];
console.log("\nAfter URL: ");
console.log(req.url);
next();
};
app.use(queryRemover);
app.get('/no/query', function(req, res) {
res.send("test");
});
app.listen();

Node.js之Express四的更多相关文章

  1. node.js和express.js安装和使用步骤 [windows]

    PS: NODEJS:https://nodejs.org NPM:https://www.npmjs.com/ 一.node.js安装与配置 到https://nodejs.org/en/downl ...

  2. Node.js基于Express框架搭建一个简单的注册登录Web功能

    这个小应用使用到了node.js  bootstrap  express  以及数据库的操作 :使用mongoose对象模型来操作 mongodb 如果没了解过的可以先去基本了解一下相关概念~ 首先注 ...

  3. node.js之express框架

    之前学习过node.js接触过express框架,最近为了编写一个mock server正好用到了express.下面正好就跟大家介绍一下关于express.今天的内容主要围绕这么几个方面? expr ...

  4. Code Your First API With Node.js and Express: Set Up the Server

    How to Set Up an Express API Server in Node.js In the previous tutorial, we learned what the REST ar ...

  5. Node.js、express、mongodb 实现分页查询、条件搜索

    前言 在上一篇Node.js.express.mongodb 入门(基于easyui datagrid增删改查) 的基础上实现了分页查询.带条件搜索. 实现效果 1.列表第一页. 2.列表第二页 3. ...

  6. Node.js、express、mongodb 入门(基于easyui datagrid增删改查)

    前言 从在本机(win8.1)环境安装相关环境到做完这个demo大概不到两周时间,刚开始只是在本机安装环境并没有敲个Demo,从周末开始断断续续的想写一个,按照惯性思维就写一个增删改查吧,一方面是体验 ...

  7. node.js框架express的安装

    node.js框架express的安装 首先假定你已经安装了 Node.js,接下来为你的应用创建一个目录,然后进入此目录并将其作为当前工作目录. $ mkdir myapp $ cd myapp 通 ...

  8. Node.js系列-express(上)

    前言 Node.js系列的第一篇:http,大概描述了通过使用node.js内置的api创建一个服务并监听request实现简单的增删改查.现在,我们就通过通读express官网及使用express框 ...

  9. node.js,express入门看详细篇

    先最简单的代码 安装 npm install express app.js 代码内容 const express = require('express') const app = express() ...

随机推荐

  1. WPF 自定义快速实现线程等待函数FastTask

    在WPF实现 我们常常需要实现这个目标:线程里面执行复杂的任务,然后主窗体等待动画 我把我最简单的东西给包了一下,更方便使用,大家也可以方便使用 1:添加CommHelper类 FastTask方法 ...

  2. 一个Form表单多个Submit提交按钮!实现提交不同的参数!

    给 submit 的按钮加onclick 方法来自定义预处理参数,比如<script type="text/javascript">function submitFun ...

  3. Jmeter——参数化的9种方法

    本文由作者张迎贞授权网易云社区发布. 一.用户定义的变量 1.右键快捷菜单中选择 添加-配置元件-用户自定义变量. 用户自定义变量中的定义的所有参数的值在测试计划的执行过程中不能发生取值的改变,因此一 ...

  4. HDU4622 Reincarnation

    题目链接:戳我 因为对应的很多询问,所以我们一定要将每一种询问先处理出来,然后O(1)查询. 至于怎么处理出来子串的子串呢? 我们固定左端点,然后依次加入子串即可.然后统计的时候直接统计last那一个 ...

  5. SpingBoot的认识和基本使用

    认识SpingBoot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程. -使用springboot以后,搭建一个spring应 ...

  6. 点分治&&动态点分治学习笔记

    突然发现网上关于点分和动态点分的教程好像很少……蒟蒻开篇blog记录一下吧……因为这是个大傻逼,可能有很多地方写错,欢迎在下面提出 参考文献:https://www.cnblogs.com/LadyL ...

  7. jzoj5832. 【省选模拟8.20】Emotional Flutter

    tj:我們發現,每一次走過的步長都是k,設當前走的步數是x,走到了一個白條 那麼,每一次走就是把所有黑條都向前移k位,我們可以考慮把所有黑條的左邊界不斷的向前移動k,直到下一次移動時,其左邊界小於0, ...

  8. Python(多进程multiprocessing模块)

    day31 http://www.cnblogs.com/yuanchenqi/articles/5745958.html 由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分 ...

  9. linux下各个目录里面都装了什么

    文章来源:http://blog.csdn.net/sunstars2009918/article/details/7038772 搞电脑的人总想知道自己的系统里到底有些什么东西,于是我就在Linux ...

  10. 【bug】使用微信分享SDK,配置成功但分享信息异常

    使用微信JSD做H5分享功能时,显示配置成功,但分享出去的信息并不是配置中的信息.(p.s. ios 分享后只有一个当前的链接,androd连分享的图标都没有), 最终找的的原因是:分享的链接中,参数 ...