我们要想真正用好ExpressJS开发框架,应该对其源代码有所研究,才能真正掌握灵活而深入的使用方法。
可以进入 http://github.com/visionmedia/express/tree/master/lib/ 查看相关源代码,源代码会不断更新,我会逐行讲解各种用法。
index.js 源代码讲解
/*
自动装配器,可以用 express.logger() 代替 require('connect').logger()
*/
var exports = module.exports = require('connect').middleware;
/**
版本信息
*/
exports.version = '1.0.0rc4';
/**
* 导入服务器模块依赖
*/
var Server = exports.Server = require('./server');
/**
* 替代 new Server(...) 方式的捷径方法。
*/
exports.createServer = function(){
//把参数返回数组形式并加入到 new Server 构造器中。
return new Server(Array.prototype.slice.call(arguments));
};
//导入 View / response / request 的扩展模块。
require('./view');
require('./response');
require('./request');
// 后续: 基本做了3个事情
// 1 . 标准化扩展件导入方式 用 express.xxx 来代替 connect.xxx
// 2 . 简化new Server()创建方式。
// 3 . 导入了 view / request / response 模块
/*
express基本使用方法也是从这个文件开始的
var express = require('express'); // 导入express 模块
var server = express.createServer(); // 创建 服务器对象
server.listen(3000); // 监听3000端口并启动服务器
*/
request.js 源代码讲解
/*
/**
* 导入依赖模块
*/
var http = require('http')
, utils = require('./utils')
, mime = require('connect/utils').mime;
/**
* 默认闪光灯格式
*/
var flashFormatters = exports.flashFormatters = {
s: function(val){
return String(val);
}
};
/**
* 返回请求头或默认选项。
*
* 例如 :
*
* req.header('Content-Type');
* // => "text/plain"
*
* req.header('content-type');
* // => "text/plain"
*
* req.header('Accept');
* // => undefined
*
* req.header('Accept', 'text/html');
* // => "text/html"
×
*/
http.IncomingMessage.prototype.header = function(name, defaultValue){
return this.headers[name.toLowerCase()] || defaultValue;
};
/**
判断请求头是否有相关类型
*
* 例子 :
*
* // Accept: text/html
* req.accepts('html');
* // => true
*
* // Accept: text/*; application/json
* req.accepts('html');
* req.accepts('text/html');
* req.accepts('text/plain');
* req.accepts('application/json');
* // => true
*
* req.accepts('image/png');
* req.accepts('png');
* // => false
*
*/
http.IncomingMessage.prototype.accepts = function(type){
var accept = this.header('Accept');
if (!accept || accept === '*/*') {
return true;
} else if (type) {
// Allow "html" vs "text/html" etc
if (type.indexOf('/') < 0) {
type = mime.types['.' + type];
}
// Check if we have a direct match
if (accept.indexOf(type) >= 0) {
return true;
// Check if we have type/*
} else {
type = type.split('/')[0] + '/*';
return accept.indexOf(type) >= 0;
}
} else {
return false;
}
};
/**
* 根据请求参数返回请求内容
*/
http.IncomingMessage.prototype.param = function(name){
// 路由参数就像 /user/:id
if (this.params[name] !== undefined) {
return this.params[name];
}
// 请求字符串参数
if (this.query[name] !== undefined) {
return this.query[name];
}
// 当加载connect.bodyDecoder后,可以查询post请求参数对应的内容。
if (this.body && this.body[name] !== undefined) {
return this.body[name];
}
};
/**
* 闪存功能 ,前提应该加载 session 模块。
*
* 例如:
*
* req.flash('info', 'email sent');
* req.flash('error', 'email delivery failed');
* req.flash('info', 'email re-sent');
* // => 2
*
* req.flash('info');
* // => ['email sent', 'email re-sent']
*
* req.flash('info');
* // => []
*
* req.flash();
* // => { error: ['email delivery failed'], info: [] }
*
* 也可以使用如下方式
* req.flash('info', 'email has been sent to %s.', userName);
*
*/
http.IncomingMessage.prototype.flash = function(type, msg){
var msgs = this.session.flash = this.session.flash || {};
if (type && msg) {
var i = 2
, args = arguments
, formatters = this.app.flashFormatters || {};
formatters.__proto__ = flashFormatters;
msg = utils.miniMarkdown(utils.htmlEscape(msg));
msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
var formatter = formatters[format];
if (formatter) return formatter(args[i++]);
});
return (msgs[type] = msgs[type] || []).push(msg);
} else if (type) {
var arr = msgs[type];
delete msgs[type];
return arr || [];
} else {
this.session.flash = {};
return msgs;
}
};
// 判断是否是 XHR 请求方式。
function isxhr() {
return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
}
/**
检查请求是一个 _XMLHttpRequest_
*/
http.IncomingMessage.prototype.__defineGetter__('isXMLHttpRequest', isxhr);
http.IncomingMessage.prototype.__defineGetter__('xhr', isxhr);
request相关后续: 其实这个源代码就是对原始的nodejs的http.IncomingMessage 的扩展。 IncomingMessage就是request的原始类型,可以这么理解。
(待续)