Connect自带的中间件

中间件组件介绍
cookieParser()为后续中间件提供req.cookies和req.signedCookies
bodyParser()为后续中间件提供req.body和req.files
limit()基于给定字节长度限制请求主体的大小,必须用在bodyParser中间件之前
query()为后续中间件提供req.query
logger()将HTTP请求的信息输出到stdout或日志文件之类的流中
favicon()响应/favicon.ico HTTP请求。通常放在中间件logger前面,这样它就不会出现在你的日志文件中了
methodOverride()可以替不能使用正确请求方法的浏览器仿造req.method,依赖于bodyParser
vhost()根据指定的主机名使用给定的中间件和/或HTTP服务器实例
session()为用户设置一个HTTP会话,并提供一个可以跨越请求的持久化req.session对象。依赖于cookieParser
basicAuth()为程序提供HTTP基本认证
csrf()防止HTTP表单中的跨站请求伪造攻击,依赖于session
errorHandler()当出现错误时把堆栈跟踪信息返回给客户端。在开发时很实用,不过不要用在生产环境中
static()把指定目录中的文件发给HTTP客户端。跟Connect的挂载功能配合得很好
compress()用gzip压缩优化HTTP响应
directory()为HTTP客户端提供目录清单服务,基于客户端的Accept请求头提供经过优化的结果

 
 

下面的代码只做参考用,版本太旧

/* cookieParser()的基本用法 */
var connect = require('connect');
var app = connect()
    .use(connect.cookieParser('tobi is a cool ferret'))
    .use(function(req, res) {
        console.log(req.cookies);
        console.log(req.signedCookies);
        // 设定出站cookie
        res.setHeader('Set-Cookie', 'foo=bar');
        // 设定cookie的有效期
        res.setHeader('Set-Cookie', 'tobi=ferret; Expires=Tue, 08 Jun 2021 10:18:14 GMT');
        res.end('hello\n');
    }).listen(3000);

/* bodyParser():解析表单的POST请求主体 */
app.use(connect.bodyParser())
    .use(function(req, res) {
        // 基本用法
        console.log(req.body.username);
        // 解析MULTIPART <FORM>数据
        console.log(req.body);
        console.log(req.files);
        res.end('bodyParser!');
    });

/* limit():请求主体的限制 */
// 基本用法
var app = connect()
    .use(connect.limit('32kb'))
    .use(connect.bodyParser())
    .use(hello);
http.createServer(app).listen(3000);

// 改进做法
function type(type, fn) {
    return function(req, res, next) {
        var ct = req.headers['content-type'] || '';
        if (0 != ct.indexOf(type)) {    // 检查content-type
            return next();
        }
        fn(req, res, next);
    }
}

var app = connect()
    .use(type('application/x-www-form-urlencoded', connect.limit('64kb')))
    .use(type('application/json', connect.limit('32kb')))
    .use(type('image', connect.limit('2mb')))
    .use(type('video', connect.limit('300mb')))
    .use(connect.bodyParser())
    .use(hello);

/* query():查询字符串解析,解析GET请求 */
var app = connect()
    .use(connect.query())
    .use(function(req, res, next) {
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify(req.query));
    });



/********************************************************
* 实现Web程序核心功能的中间件
********************************************************/
/* logger():记录请求 */
var connect = require('connect');
var app = connect()
    .use(connect.logger())      // 没有参数,使用默认的logger选项
    .use(hello)
    .listen(3000);

// 定制日志格式
var app = connect()
        .use(connect.logger(':method :url :response-time ms'))
        .use(hello);
/****************************** 
信令
:req[头名称]   比如::req[Accept]
:res[头名称]   比如::res[Content-Length]
:http-version
:response-time
:remote-addr
:date
:method
:url
:referrer
:user-agent
:status
*******************************/
// 定制信令:只需要给connect.logger.token函数提供信令名称和回调函数
var url = require('url');
connect.logger.token('query-string', function(req, res) {
    return url.parse(req.url).query;
});

// STREAM选项
var fs = require('fs');
var log = fs.createWriteStream('/var/log/myapp.log', {flag = 'a'});
var app = connect()
    .use(connect.logger({ format: ':method :url', stream: log}))
    .use(hello);

// immediate选项:一收到请求就写日志
var app = connect()
    .use(connect.logger({immediate: true}))
    .use(hello);

// buffer选项:接受一个数值,以毫秒为单位指定缓冲区刷新的时间间隔,或者只传入true使用默认间隔


/* favicon(): 提供favicon */
// 还可以传入一个maxAge参数,指明浏览器应该把favicon放在内存中缓存多长时间
connect()
    .use(connect.favicon(__dirname + '/public/favicon.ico'))
    .use(function(req, res) {
        res.end('Hello World!\n')
    });


/* methodOverride():伪造HTTP方法 */
// HTML输入控件默认的名称是_method,但是可以给methodOverride()传入一个定制值,connect.use(connect.methodOverride('__method__'))
var connect = require('connect');

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

function update(req, res, next) {
    // 访问原始的req.method属性
    console.log(req.originalMethod);
    if ('PUT' != req.method) return next();
    res.end('Updated name to ' + req.body.user.name);
}

var app = connect()
    .use(connect.logger('dev'))
    .use(connect.bodyParser())
    .use(connect.methodOverride())
    .use(edit)
    .use(update)
    .listen(3000);


/* vhost():虚拟主机 */
// 通过请求头Host路由请求
// 两个参数:第一个是主机名,vhost实例会用它进行匹配;第二个是http.Server实例
var app = require('./sites/expressjs.dev');
server.use(connect.vhost('expressjs.dev', app));

// 从文件系统中生成一个主机列表
var connect = require('connect');
var fs = require('fs');
var app = connect();
var sites = fs.readdirSync('source/sites');

sites.forEach(function(site) {
    console.log(' ...%s', site);
    app.use(connect.vhost(site, require('./sites/' + site)));
});
app.listen(3000);


/* session():会话管理 */
// session()需要用签名cookie,所以应该在它上面使用cookieParser(),并传给它一个秘钥
var connect = require('connect');
var app = connect()
    .use(connect.favicon())
    .use(connect.cookieParser('keyboard cat'))
    .use(connect.session())
    .use(function(req, res, next) {
        var sess = req.session;
        if (sess.views) {
            res.setHeader('Content-Type', 'text/html');
            res.write('<p>views: ' + sess.views + '</p>');
            res.end();
            sess.views++;
        } else {
            sess.views = 1;
            res.end('welcome to the session demo. refresh!');
        }
    });
app.listen(3000);

// 设定会话有效期
var hour = 3600000;
var sessionOpts = {
    key: 'myapp_sid',   // 配置会话的名称
    cookie: {maxAge: hour * 24, secure: true}   // 24小时后过期,只有在HTTPS时才发送会话cookie
};
app.use(connect.cookieParser('keyboard cat'));
app.use(connect.session(sessionOpts));

// 处理会话数据
// 赋给req.session对象的所有属性都会被保存下来;当相同的用户(浏览器)再次发来请求时,会加载它们
req.session.cart = {items: [1, 2, 3]};
req.session.cart.items.push(4);

// 操纵会话cookie
res.write('<p>views: ' + sess.views + '</p>');
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
res.write('<p>httpOnly: ' + sess.cookie.httpOnly + '</p>');
res.write('<p>path: ' + sess.cookie.path + '</p>');
res.write('<p>domain: ' + sess.cookie.domain + '</p>');
res.write('<p>secure: ' + sess.cookie.secure + '</p>');



/********************************************************
* 处理Web程序安全的中间件
********************************************************/
/* basicAuth():HTTP基本认证 */
// 第一种方法,传入用户名和密码
var app = connect()
    .use(connect.basicAuth('tj', 'tobi'));

// 第二种方法,提供回调函数
var users = {
    tobi: 'foo',
    loki: 'bar',
    jane: 'baz'
};
var app = connect()
    .use(connect.basicAuth(function(user, pass) {
        return users[user] == pass;
    });

// 第三种方法:提供异步回调函数
var app = connect();
app.use(connect.basicAuth(function(user, pass, callback) {
    // 执行数据库验证函数,当数据库响应完成时,运行异步回调函数
    User.authenticate({user: user, pass: pass}, gotUser);
    function gotUser(err, user) {
        if (err) return callback(err);
        callback(null, user);
    }
}));


/* csrf():跨站请求伪造防护 */
// 必须确保csrf()添加在了bodyParser()和session()的下面
connect()
    .use(connec.bodyParser())
    .use(connect.cookieParser('secret'))
    .use(connect.session())
    .use(connect.csrf());


/* errorHandler():开发错误处理 */
// 可以基于请求头域Accept提供详尽的HTML、JSON和普通文本错误响应
var app = connect()
    .use(connect.logger('dev'))
    .use(function(req, res, next) {
        setTimeout(function() {
            next(new Error('something broke!'));
        }, 500);
    })
    .use(connect.errorHandler());



/*******************************************************
* 提供静态文件服务的中间件
*******************************************************/
/* static():静态文件服务 */
// 基本用法
// static 会根据请求的URL检查./public/中的普通文件,如果文件存在,响应中的Content-Type域的值默认会根据文件的扩展名设定,并传输文件中的数据,如果请求的路径不是文件,则调用next(),让后续的中间件处理该请求
// curl http://localhost/foo.js -i
app.use(connect.static('public'));

// 使用带挂载的static()
// curl http://localhost/app.files/foo.js
app.use('/app/files', connect.static('public'));
// 使用绝对路径指定根目录
app.use('/app/files', connect.static(__dirname + '/public'));

// 请求目录时返回index.html:当请求的是目录,并且那个目录下有index.html时,它可以返回这个文件作为响应


/* compress():压缩静态文件 */
// compress()组件通过请求头域Accept-Encoding自动检测客户端可接受的编码,如果请求头中没有该域,则不会对响应做处理
// 基本用法
var connect = require('connect');
var app = connect()
    .use(connect.compress())
    .use(connect.static('source'));
app.listen(3000);

// 使用定制的过滤器函数
// 只压缩普通文本
function filter(req) {
    var type = req.getHeader('Content-Type') || '';
    return 0 == type.indexOf('text/plain');
}

connect()
    .use(connect.compress({filter: filter}));

// 指定压缩及内存水平
// 下面这个例子level被设为3,压缩水平更低但更快,memLevel被设为8,使用更多内存加快压缩速度
connect()
    .use(connect.compress({level: 3, memLevel:8}));


/* directory():目录列表 */
// 这个组件要配合static()使用,由static()提供真正的文件服务,而directory()只是提供列表
var connect = require('connect');
var app = connect()
    .use(connect.directory('public'))
    .use(connect.static('public'));
app.listen(3000);

// 使用带挂载的directory()
// 这里的选项icons用来启用图标,hidden表明两个组件都可以查看并返回隐藏文件
var app = connect()
    .use('/files', connect.directory('public', {icons: true, hidden: true}))
    .use('files', connect.static('public', {hidden: true}));
app.listen(3000);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值