####对Web请求的处理: #####1. 请求方法的判断 #####2. URL的路径解析 #####3. URL中查询字符串解析 #####4. Cookie的解析 #####5. Basic认证 #####6. 表单数据的解析 #####7. 任意格式文件的上传处理javascript
var http = require('http'); http.createServer(function(req,res){ res.writeHead(200,{'Content-Type':'text/plain'}); res.end('Hello World\n'); }).listen(1337,'127.0.0.1'); console.log('Server running at http://127.0.0.1:1137'); //上面的函数参数能够用如下函数代替,高阶函数 var app = connect(); //var app = express();
#####1. 请求方法判断 HHTP_Parser在解析请求报文的时候,将报文头抽取出来,设置为req.method #####2. 路径解析 HTTP_Parser将其解析为req.urlhtml
//2.1 根据路径去查找磁盘中的文件 function(req,res){ var pathname = url.parse(req.url).pathname; fs.readFile(path.join(ROOT,pathname),function(err,file){ if (err){ res.writeHead(404); res.end('找不到相关文件。--'); return; } res.writeHead(200); res.end(file); }); }
//2.2 根据路径来选择控制器 function(req,res){ var pathname = url.parse(req.url).pathname; var paths = pathname.split('/'); var controller = paths[1] || 'index'; var action = path[2] || 'index'; var args = paths.slice(3); if (handles[controller] && hanlders[controller][action]{ hanlders[controller][action].apply(null,[req,res].concat(args)); }else { res.writeHead(500); res.end('找不到响应控制器'); }) }
#####7. Basic认证java
请求头:Authorization:Basic dXN1cjpwYXNznode
//将用户和密码组合:username + ":" + password,而后进行Base64编码。 var encode = function (username,password){ return new Buffer(username + ':' + password).toString('base64'); }
首次访问,返回401响应express
function (req,res) { var auth = req.headers['authorization'] || ''; var parts = auth.split(' '); var method = parts[0] || ''; var encoded = parts[1] || ''; var decoded = new Buffer(encoded,'base64').toString('utf-8').split(":"); var user = decoded[0]; var pass = decoded[1]; if (!checkUser(user,pass){ res.setHeader('WWW-Authenticate','Basic realm="Secure Area"'); res.writeHead(401); res.end(); }else{ handle(req,res); }) }
Base64不安全,多放在HTTPS中使用,为了改进Basic认证,RFC 2069规范提出了访问认证,它加入了服务端随机数来保护认证过程。json
#####8. 数据上传 http模块只对http报头解析,而后触发request事件浏览器
//判断请求是否带有body var hasBody = function(req){ return 'transfer-encoding' in req.headers || 'content-lenght' in req.headers; }
内容经过data事件触发,使用流方式处理安全
function (req,res){ if (hasBody(req)){ var buffers = []; req.on('data',function(chunk){ buffers.push(chunk); }); req.on('end',function(){ req.rawBody = Buffer.concat(buffers).toString(); handle(req,res); }else{ handle(req,res); }); } }
将接收到Buffer列表转化为一个Buffer对象后,在转换为没有乱码的字符串app
######8.1 表单数据函数
默认表单提交: Content-Type:application/x-www-form-urlencoded
var handle = function(req,res){ if (req.headers['content-type'] === 'application/x-www-form-urlencoded') { req.body = querystring.parse(req.rawBody); } todo(req,res); }
Content-Type取值: · JSON类型值:application/json · XML类型值:application/xml · PDF文件:application/pdf · 纯文本:text/plain · html:text/html
######8.5 页面渲染 Content-Type:gzip Content-Length:21170 Content-Type:text/javascript;charset=utf-8 客户端处理过程是:经过gzip解码报文体中的内容,用长度校验报文内容是否正确,而后以字符集UTF-8将解码后的脚本插入到文档节点中。 浏览器根据Content-Type值决定采用什么方式渲染,简称为MIME(Multipurpose Internet Mail Extensions)。
//判断文件类型 var mime = require('mime'); mime.lookup('/path/to/file.txt'); mime.lookup('file.txt'); mime.lookup('.TXT'); mime.lookup('html');
即时查看:Content-Disposition:inline 附件下载:Content-Disposition:attachment;filename="filename.ext"
//响应下载 res.sendfile = function(filepath) { fs.stat(filepath,function(err,stat){ var stream = fs.createReadStream(filepath); res.setHeader('Content-Type',mime.lookup(filepath)); res.setHeader('Content-Length',stat.size); res.setHeader('Content-Disposition','attachment;filename="' + path.basename(filepath) + '"'); res.writeHead(200); stream.pipe(res); }); };
//响应JSON res.json = function(json) { res.setHeader('Content-Type','application/json'); res.writeHead(200); res.end(JSON.stringify(json)); };
//响应跳转 res.redirect= function(url) { res.setHeader('Location',url); res.writeHead(302); res.end('Redirect to' + url); };