HTTP協(xié)議
要理解Web服務(wù)器程序的工作原理笋鄙,首先,我們要對HTTP協(xié)議有基本的了解怪瓶。如果你對HTTP協(xié)議不太熟悉萧落,先看一看HTTP協(xié)議簡介。
HTTP服務(wù)器
要開發(fā)HTTP服務(wù)器程序洗贰,從頭處理TCP連接找岖,解析HTTP是不現(xiàn)實(shí)的。這些工作實(shí)際上已經(jīng)由Node.js自帶的http模塊完成了敛滋。應(yīng)用程序并不直接和HTTP協(xié)議打交道许布,而是操作http模塊提供的(請求)和
(響應(yīng))對象。
request對象封裝了HTTP請求绎晃,我們調(diào)用request對象的屬性和方法就可以拿到所有HTTP蜜唾;
response對象封裝了HTTP響應(yīng),我們操作response對象的方法庶艾,就可以把HTTP返回給瀏覽器袁余。
用Node.js實(shí)現(xiàn)一個(gè)HTTP服務(wù)器程序非常簡單。我們來實(shí)現(xiàn)一個(gè)咱揍,它對于所有請求泌霍,都返回Hello world!:
'use strict'
//導(dǎo)入http模塊
var http = require('http');
//創(chuàng)建http server,並傳入回調(diào)函數(shù);
var server = http.createServer(function(request,response){
console.log(request.methods + '6:7' + request.url);//回調(diào)函數(shù)接收request和response對象 獲得HTTP請求的methods和url:
response.writeHead(200,{'Content-Type':'text/html'}); //將HTTP響應(yīng)200寫入response述召。同時(shí)設(shè)置Content-Type:text/html:
response.end('<h1>Hello world!</h1>') //將HTTP響應(yīng)的Html內(nèi)容寫入response
});
server.listen(8000);// 讓服務(wù)器監(jiān)聽8080端口:
console.log('Server is running at http://127.0.0.1:8000/')
每次運(yùn)行瀏覽器,都會(huì)進(jìn)入兩次蟹地,因?yàn)闉g覽器默認(rèn)一次會(huì)請求favicon.ico积暖,如果這不符合我們的業(yè)務(wù)邏輯,就可以通過解析url怪与,當(dāng)請求icon時(shí)不做邏輯處理夺刑。
文件服務(wù)器
讓我們繼續(xù)擴(kuò)展一下上面的Web程序。我們可以設(shè)定一個(gè)目錄分别,然后讓W(xué)eb程序變成一個(gè)文件服務(wù)器遍愿。要實(shí)現(xiàn)這一點(diǎn),我們只需要解析request.url中的路徑耘斩,然后在本地找到對應(yīng)的文件沼填,把文件內(nèi)容發(fā)送出去就可以了。
解析URL需要用到Node.js提供的括授,它使用起來非常簡單坞笙,通過
將一個(gè)字符串解析為一個(gè)Url對象:
'use strict';
var url = require('url');
console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
'use strict';
var fs = require('fs')
var path = require('path');
// 解析當(dāng)前目錄:
var workDir = path.resolve('.');
console.log(workDir) // '/Users/mild/day/lianxi/jianshu-node'
var filePath = path.join(workDir, 'save_new_excel.xls'); // '/Users/mild/day/lianxi/jianshu-node/save_new_excel.xls'
// var filePath = path.join(workDir, 'pub','save_new_excel.xls'); // => '/Users/mild/day/lianxi/jianshu-node/pub/save_new_excel.xls'
console.log(filePath)
var data = fs.createReadStream(filePath)
var ws = fs.createWriteStream('testexc.xls')
data.pipe(ws)
path獲取的是當(dāng)前的路徑岩饼,filePath獲取的是拼接好的文件路徑
最后,我們實(shí)現(xiàn)一個(gè)文件服務(wù)器index19.js:
(index19.js)
'use strict';
var
fs = require('fs'),
url = require('url'),
path = require('path'),
http = require('http');
// 從命令行參數(shù)獲取root目錄薛夜,默認(rèn)是當(dāng)前目錄:
var root = path.resolve(process.argv[2] || '.');
//類似 '/Users/mild/day/lianxi/jianshu-node':
console.log('Static root dir: ' + root);
// 創(chuàng)建服務(wù)器:
var server = http.createServer(function (request, response) {
// 獲得URL的path籍茧,類似 '/node.text':
var pathname = url.parse(request.url).pathname;
// 獲得對應(yīng)的本地文件路徑,類似 '/Users/mild/day/lianxi/jianshu-node/node.text':
var filepath = path.join(root, pathname); //當(dāng)前路徑拼接文件名 =>文件當(dāng)前路徑
// 獲取文件狀態(tài):
fs.stat(filepath, function (err, stats) {
if (!err && stats.isFile()) {
// 沒有出錯(cuò)并且文件存在:
console.log('200 ' + request.url);
// 發(fā)送200響應(yīng):
response.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8;' });//<=響應(yīng)頭加utf-8
// 將文件流導(dǎo)向response:
fs.createReadStream(filepath).pipe(response);
} else {
// 出錯(cuò)了或者文件不存在:
console.log('404 ' + request.url);
// 發(fā)送404響應(yīng):
response.writeHead(404);
response.end('404 Not Found');
}
});
});
server.listen(8080);
console.log('Server is running at http://127.0.0.1:8080/node.text');
(node.text)
我是node喲 adsfadsfa
commoand + 點(diǎn)擊 http://127.0.0.1:8080/node.text