HTTP构建一个网站:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req, res) {
if('GET' === req.method && '/img' === req.url.substr(0,4) && '.jpg' === req.url.substr(-4)) {
fs.stat(__dirname + req.url, function(err, stat) { //检查文件是否存在
if(err || !stat.isFile()) {
res.writeHead(404);
res.end('Not Found');
return;
}
serve(__dirname + req.url, 'image/png'); //'application/jpg':会下载图片
});
} else if('GET' === req.method && '/' === req.url) {
serve(__dirname + '/index.html','text/html');
} else {
res.writeHead(400);
res.end('Not Found');
}
function serve(path, type) {
res.writeHead(200, {'Content-Type': type});
fs.createReadStream(path).pipe(res); //将文件系统流接到HTTP响应流中;
}
});
server.listen(3000);
通过connect实现一个网站:
- 创建package.json:
{ "name": "my-website", "version": "0.0.1", "dependencies": { "connect": "1.8.7" }, "description": "an connect website" }
- 安装依赖:npm install;
- 代码例子:
//用connect修改http构建的网站;
var connect = require('connect'); var server = connect.createServer(); //可以简化 server = connect(); server.use(function(req, res, next) { console.log(' %s: %s ', req.method, req.url); next(); //下一个中间件; }); server.use(function(req, res, next) { if('GET' === req.method && '/img' === req.url.substr(0,4)) { console.log('img'); } else { next(); } }); server.use(function(req, res, next) { if('GET' === req.method && '/' === req.url) { console.log('index'); } else { console.log('other'); next(); } }); server.use(function(req, res, next) { res.writeHead(404); res.end('Not Found'); }); server.listen(3000);
中间件://中间件由函数组成,它除了处理req,res对象外还接受 一个next函数做流控制;
//sample.js
/*
请求超时
*/
module.exports = function(opts) {
var time = opts.time || 100;
return function(req, res, next) {
console.log(1);
var timer = setTimeout(function() {
console.log('\033[90m%s %s\033[91mis taking too long!\033[39m', req.method, req.url);
}, time);
var end = res.end;
res.end = function(chunk, encoding) {
res.end = end;
res.end(chunk, encoding);
clearTimeout();
}
next();
}
}
//main.js
var connect = require('connect');
var time = require('./3.2');
var server = connect.createServer();
/*
记录请求情况
*/
server.use(connect.logger('dev'));
/*
实现时间中间件
*/
server.use(time({time: 500}));
/*
快速响应
*/
server.use(function(req, res, next) {
if('/a' === req.url) {
res.writeHead(200);
res.end('Fast!');
} else {
next();
}
});
/*
慢速响应
*/
server.use(function(req, res, next) {
if('/b' === req.url) {
setTimeout(function() {
res.writeHead(200);
res.end('slow');
}, 1000);
} else {
next();
}
});
server.listen(3000);
- static中间件:
- 挂载:将任意一个URL匹配到文件系统中任意一个目录
server.use('/my-images', connect.static(__dirname + '/website/img'));
- maxAge:设置一个资源客户端缓存的时间
server.use('/js', connect.static(__dirname, {maxAge:10000}));
- hidden:设置为true的话,connect也会托管文件系统中的隐藏文件
server.use(connect.static(__dirname, {hidden:true}));
- 挂载:将任意一个URL匹配到文件系统中任意一个目录
- query中间件:获取查询字符串 //query中间件在express中默认是启用的;
server.use(connect.query()) server.use(function (req, res) { console.log(req.query.name); //req.query对象格式返回,如访问xxx?name = jinks;返回{name:'jinks'} })
- logger中间件:诊断工具;将发送进来的请求信息和发送出去的响应信息打印在终端
- server.use(connect.logger('dev'));
-
- server.use(connect.logger('default'));
-
- server.use(connect.logger('short'));
-
- server.use(connect.logger('tiny'));
-
- server.use(connect.logger(':method :remote-addr' :res[Content-Length])); //自定义格式输出; 查看完整的token
- bodyParser中间层:
- 与http模块中使用qs模块解析post请求消息体一样,bodyParser中间层也具有这样功能;
server.use(connect.bodyParser()); server.use(function(req, res, next) { //req.body; }
- 其另一个功能就是处理用户上传的文件;
var connect = require('connect'); var fs = require('fs'); var server = connect(connect.logger('dev'),connect.static('static'),connect.bodyParser()); //简化加载中间件
//设置默认url:'/'为文件系统中static文件夹,如果有Index.html,就加载此项; server.use(function(req, res, next) { if('POST' === req.method ) { fs.readFile(req.files.files.path, 'utf8', function(err, data) { if(err) { res.writeHead(500); res.end('Error!'); return; } res.writeHead(200, {'Content-Type': 'text/html'}); res.end([ '<h3>File: ' + req.files.files.name + '</h3>', '<h4>Type: ' + req.files.files.type + '</h4>', '<h1>Contents:</h4><pre>' + data + '</pre>' ].join('')); }); } else { next(); } }) server.listen(3000);
- 与http模块中使用qs模块解析post请求消息体一样,bodyParser中间层也具有这样功能;
- cookieParser中间件; //读写cookie数据
server.use(connect.cookieParser()); server.use(function(req, res ,next) { //req.cookies //对象形式返回 });
-
session中间件;
- 出于安全考虑,在初始化session中间件的时候需要提供secret选项
connect.session({secret: 'my app secret'})
- 使用req.sesstion记录数据: req.session.logged_in; req.session.name
- 出于安全考虑,在初始化session中间件的时候需要提供secret选项
创建会话:
--------------users.json----------------------------------
//当只要对外暴露数据时,不需要module.exports而直接把数据文件以JSON形式暴露出来
{
"jinks": {
"password" : "ferret",
"name": "jinks"
}
}
--------------app.js------------------------------------
var connect = require('connect');
var users = require('./users');
var server = connect(
connect.logger('dev'),
connect.bodyParser(),
connect.cookieParser(),
connect.session({secret: 'my app secret'}),
function(req, res, next) {
console.log(req.session.logged_in);
if('/' === req.url && req.session.logged_in) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('welcome back, <b>' + req.session.name + '</b>. '
+ '<a href="/logout">Logout</a>');
} else {
next();
}
},
function(req, res, next) {
if('/' === req.url && 'GET' === req.method) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end([
'<form action="/login" method="post"'
+'<fieldset>'
+'<legend>Please log in</legend>'
+'<p>User: <input type="text" name="user"/></p>'
+'<p>Password: <input type="password" name="password"/></p>'
+'<button>Submit</button>'
+'</fieldset>'
+'</form>'].join(''));
} else {
next();
}
},
function(req, res, next) {
if('/login' === req.url && 'POST' === req.method) {
res.writeHead(200);
if(!users[req.body.user] || req.body.password != users[req.body.user].password) {
res.end('Bad username/password');
} else {
req.session.logged_in = true;
req.session.name = users[req.body.user].name;
res.end('Authenticated!');
}
} else {
next();
}
},
function(req, res, next) {
if('/logout' === req.url) {
req.session.logged_in = false;
res.writeHead(200);
res.end('Logged out!');
} else {
next();
}
});
server.listen(3000);