####對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); };