創(chuàng)建HTTP服務(wù)器
在Node.js中,可以很方便地創(chuàng)建一個(gè)HTTP服務(wù)器,只需調(diào)用http模塊中的create Server方法即可
var server=http.createServer([requestListener])
在createServer方法中,可以使用一個(gè)可選參數(shù),參數(shù)值為一個(gè)回調(diào)函數(shù),用于指定當(dāng)接收到客戶端請(qǐng)求時(shí)所需執(zhí)行的處理,該回調(diào)函數(shù)的指定方法如下所示。
function (request,response) {
//回調(diào)函數(shù)代碼略
}
- request:代表一個(gè)客戶端請(qǐng)求
- response:代表一個(gè)服務(wù)器端響應(yīng)對(duì)象
createServer方法返回被創(chuàng)建的服務(wù)器對(duì)象,如果不在createServer方法中使用參數(shù),也可以通過監(jiān)聽該方法創(chuàng)建的服務(wù)器對(duì)象的request事件(當(dāng)接收到客戶端請(qǐng)求時(shí)觸發(fā)),并且指定該事件觸發(fā)時(shí)調(diào)用的回調(diào)函數(shù)的方法來(lái)指定當(dāng)接收到客戶端請(qǐng)求時(shí)所需執(zhí)行的處理,代碼如下所示(代碼中的server代表一個(gè)HTTP服務(wù)器)。
server.on('request',function(request,response){
//回調(diào)函數(shù)代碼略
});
在創(chuàng)建了HTTP服務(wù)器后,需要指定該服務(wù)器所要監(jiān)聽的地址(可以為一個(gè)IP地址,也可以為一個(gè)主機(jī)名)及端口,這時(shí),可以使用該HTTP服務(wù)器的listen方法
server.listen(port,[host],[backlog],[callback])
- port:端口號(hào)
- host:主機(jī)
- backlog:最大連接數(shù)
- callback:回調(diào)
也可使用listening事件實(shí)現(xiàn)
server.on('listening',function(){
//回調(diào)函數(shù)代碼略
});
創(chuàng)建一個(gè)服務(wù)器完整示例:
var http = require('http');
var server=http.createServer(function (req, res) {
//暫不指定接收到客戶端請(qǐng)求時(shí)的處理
}).listen(1337, "127.0.0.1",function(){
console.log('服務(wù)器端開始監(jiān)聽。');
});
close()關(guān)閉服務(wù)器
server.close();
可以監(jiān)聽服務(wù)器被關(guān)閉以后
server.on('close',function(){
//回調(diào)函數(shù)代碼略
});
監(jiān)聽服務(wù)器錯(cuò)誤信息
server.on('error', function (e) {
if (e.code == 'EADDRINUSE') {//當(dāng)?shù)刂芳岸丝诒徽加脮r(shí)錯(cuò)誤代碼為'EADDRINUSE'
//可以在此處指定當(dāng)?shù)刂芳岸丝诒徽加脮r(shí)所需執(zhí)行的處理
}
});
長(zhǎng)鏈接
在默認(rèn)情況下,客戶端和服務(wù)器端每進(jìn)行一次HTTP操作,都將建立一次連接,客戶端與服務(wù)器端之間的交互通信完成后該連接就中斷。在HTTP1.1中,添加了長(zhǎng)連接支持。如果客戶端發(fā)出的請(qǐng)求頭信息或者服務(wù)器端發(fā)出的響應(yīng)頭信息中加入了“Connection:keep-alive”信息,則HTTP連接將繼續(xù)保持,客戶端可以繼續(xù)通過相同的連接向服務(wù)器端發(fā)出請(qǐng)求。
在Node.js中,當(dāng)客戶端與服務(wù)器端建立連接時(shí),觸發(fā)HTTP服務(wù)器對(duì)象的connection事件,可以監(jiān)聽該事件并在該事件觸發(fā)時(shí)調(diào)用的回調(diào)函數(shù)中指定當(dāng)連接建立時(shí)所需要執(zhí)行的處理
server.on('connection',function(socket){
//回調(diào)函數(shù)代碼略
});
在該回調(diào)函數(shù)中可以使用一個(gè)參數(shù),參數(shù)值為服務(wù)器端用于監(jiān)聽客戶端請(qǐng)求的socket端口對(duì)象。
設(shè)置服務(wù)器的超時(shí)時(shí)間
可以使用HTTP服務(wù)器的setTimeout方法來(lái)設(shè)置服務(wù)器的超時(shí)時(shí)間。當(dāng)該超時(shí)時(shí)間超過之后,客戶端不可繼續(xù)利用本次與HTTP服務(wù)器建立的連接,下次向該HTTP服務(wù)器發(fā)出請(qǐng)求時(shí)必須重新建立連接。
server.setTimeout(msecs, callback)
- mecs:參數(shù)值為一個(gè)整數(shù),用于設(shè)置服務(wù)器的超時(shí)時(shí)間,單位為毫秒,可以通過將該參數(shù)值設(shè)置為0的方法取消服務(wù)器的超時(shí)處理。
- callback:用于設(shè)置當(dāng)服務(wù)器超時(shí)時(shí)調(diào)用的回調(diào)函數(shù),在該回調(diào)函數(shù)中可以使用一個(gè)參數(shù),參數(shù)值為服務(wù)器端用于監(jiān)聽客戶端請(qǐng)求的socket對(duì)象。
server.on('timeout',function(socket){
//回調(diào)函數(shù)代碼略
});
獲取客戶端請(qǐng)求信息
HTTP服務(wù)器接收到客戶端請(qǐng)求時(shí)調(diào)用的回調(diào)函數(shù)中的第一個(gè)參數(shù)值為一個(gè)http.IncomingMessage對(duì)象,該對(duì)象用于讀取客戶端請(qǐng)求流中的數(shù)據(jù),因此,當(dāng)從客戶端請(qǐng)求流中讀取到新的數(shù)據(jù)時(shí)觸發(fā)data事件,當(dāng)讀取完客戶端請(qǐng)求流中的數(shù)據(jù)時(shí)觸發(fā)end事件。當(dāng)該對(duì)象被用于讀取客戶端請(qǐng)求流中的數(shù)據(jù)時(shí),該對(duì)象擁有如下所示的一些屬性。
- method:該屬性值為一個(gè)字符串,字符串值為客戶端向服務(wù)器端發(fā)送請(qǐng)求時(shí)使用的方法,例如“GET”、“POST”、“PUT”或“DELETE”。
- url:該屬性值為客戶端發(fā)送請(qǐng)求時(shí)使用的URL參數(shù)字符串,例如“/”、“/user/1”、“/post/new/?param=value”。該屬性為一個(gè)非常重要的屬性,通常用來(lái)判斷客戶端請(qǐng)求的頁(yè)面及需要執(zhí)行的處理。
- headers:該屬性值為客戶端發(fā)送的請(qǐng)求頭對(duì)象,其中存放了客戶端發(fā)送的所有請(qǐng)求頭信息,包括各種cookie信息以及瀏覽器的各種信息。
- httpVersion:該屬性值為一個(gè)字符串,字符串值為客戶端發(fā)送的HTTP版本,可能的值為“1.1”或“1.0”。
- trailers:該屬性值為客戶端發(fā)送的trailer對(duì)象。該對(duì)象中存放了客戶端附加的一些HTTP頭信息,該對(duì)象被包含在客戶端發(fā)送的請(qǐng)求數(shù)據(jù)之后,因此只有當(dāng)http.IncomingMessage對(duì)象的end事件觸發(fā)之后才能讀取到trailer對(duì)象中的信息。
- socket:該屬性值為服務(wù)器端用于監(jiān)聽客戶端請(qǐng)求的socket對(duì)象。
獲取請(qǐng)求數(shù)據(jù)
var http = require('http');
var fs = require('fs');
var server=http.createServer(function (req, res) {
if(req.url!=="/favicon.ico"){
req.on('data',function(data){
console.log('服務(wù)器端接收到數(shù)據(jù):'+decodeURIComponent(data));
});
req.on('end',function(){
console.log('客戶端請(qǐng)求數(shù)據(jù)已全部接收完畢。');
});
}
res.end();
}).listen(1337, "127.0.0.1");
轉(zhuǎn)換URL字符串與查詢字符串
在Node.js中,提供了一個(gè)url模塊與一個(gè)QueryString模塊,分別用來(lái)轉(zhuǎn)換完整URL字符串與URL中的查詢字符串。
在一個(gè)完整的URL字符串中,從“?”字符之后(不包括“?”字符)到“#”字符之前(如果存在“#”字符)或者到該URL字符串結(jié)束(如果不存在“#”字符)的這一部分稱為查詢字符串,例如在“http://google.com/user.php?userName=Lulingniu&age=40&sex=male#hash”這個(gè)URL字符串中,“userName=Lulingniu&age=40&sex=male”這個(gè)部分稱為一個(gè)查詢字符串。
Query String模塊中的parse方法
可以使用Query String模塊中的parse方法將該字符串轉(zhuǎn)換為一個(gè)對(duì)象
querystring.parse(str,[sep],[eq],[options])
- str:用于指定被轉(zhuǎn)換的查詢字符串;
- sep:用于指定該查詢字符串中的分割字符,默認(rèn)參數(shù)值為“&”
- eq:用于指定該查詢字符串中的分配字符,默認(rèn)參數(shù)值為“=”
- options:options參數(shù)值為一個(gè)對(duì)象,可以在該對(duì)象中使用一個(gè)整數(shù)值類型的maxKeys屬性來(lái)指定轉(zhuǎn)換后的對(duì)象中的屬性個(gè)數(shù),如果將maxKeys屬性值設(shè)定為0,其效果等于不使用maxKeys屬性值。
Query String模塊中的stringify方法
可以使用Query String模塊中的stringify方法將對(duì)象轉(zhuǎn)換為一個(gè)查詢字符串
querystring.stringify(obj,[sep],[eq])
- obj:用于指定被轉(zhuǎn)換的對(duì)象;
- sep:用于指定查詢字符串中所使用的分割字符,默認(rèn)參數(shù)值為“&”;
- eq:用于指定查詢字符串中使用的分配字符,默認(rèn)參數(shù)值為“=”。
url.parse()
在url模塊中,可以使用parse方法將URL字符串轉(zhuǎn)換為一個(gè)對(duì)象,根據(jù)URL字符串中的不同內(nèi)容,該對(duì)象中可能具有的屬性及其含義如下所示。
- href:被轉(zhuǎn)換的原URL字符串。
- protocol:客戶端發(fā)出請(qǐng)求時(shí)使用的協(xié)議。
- slashes:在協(xié)議與路徑中間是否使用“//”分隔符。
- host:URL字符串中的完整地址及端口號(hào),該地址可能為一個(gè)IP地址,也可能為一個(gè)主機(jī)名。
- auth:URL字符串中的認(rèn)證信息部分。
- hostname:URL字符串中的完整地址,該地址可能為一個(gè)IP地址,也可能為一個(gè)主機(jī)名。
- port:URL字符串中的端口號(hào)。
- pathname:URL字符串中的路徑,不包含查詢字符串。
- search:URL字符串中的查詢字符串,包含起始字符“?”。
- path:URL字符串中的路徑,包含查詢字符串。
- query:URL字符串中的查詢字符串,不包含起始字符“?”,或根據(jù)該查詢字符串而轉(zhuǎn)換的對(duì)象(根據(jù)parse方法所用參數(shù)而決定query屬性值)。
- hash:URL字符串中的散列字符串,包含起始字符“#”。
url.parse(urlStr,[parseQueryString])
- urlStr:用于指定需要轉(zhuǎn)換的URL字符串;
- parseQueryString:為一個(gè)布爾類型的參數(shù),當(dāng)參數(shù)值為true時(shí),內(nèi)部使用Query String模塊將查詢字符串轉(zhuǎn)換為一個(gè)對(duì)象,參數(shù)值為false時(shí)不執(zhí)行該轉(zhuǎn)換操作,默認(rèn)參數(shù)值為false。
url.format()
可以使用url模塊中的format方法將URL字符串經(jīng)過轉(zhuǎn)換后的對(duì)象還原為一個(gè)URL字符串。
url.format(urlObj)
url.resolve()
可以使用resolve方法將兩個(gè)方法結(jié)合成為一個(gè)路徑
url.resolve(from,to
- from:起點(diǎn)路徑字符串
- to:參考路徑字符串
在resolve方法中,使用兩個(gè)字符串類型的參數(shù),其中第一個(gè)參數(shù)為起點(diǎn)路徑字符串,第二個(gè)參數(shù)為參考路徑字符串。這兩個(gè)路徑既可為相對(duì)路徑,也可為絕對(duì)路徑。該方法返回轉(zhuǎn)換后的路徑。
在結(jié)合路徑時(shí),以第一參數(shù)值為起點(diǎn)路徑,執(zhí)行如下所示的轉(zhuǎn)換規(guī)則。
- 如果起點(diǎn)路徑為網(wǎng)絡(luò)路徑,參考路徑為非網(wǎng)絡(luò)路徑的絕對(duì)路徑,則返回路徑為網(wǎng)絡(luò)根目錄+參考路徑。
- 在其他情況下,如果參考路徑為絕對(duì)路徑,則返回路徑為該參考路徑。
- 如果起點(diǎn)路徑為一個(gè)不以“/”字符結(jié)尾的根目錄且參考路徑為相對(duì)路徑,則返回路徑為:起點(diǎn)路徑+“/”+參考路徑中去除開頭的“./”字符或“../”字符(如果存在的話)后的文字。如果起點(diǎn)路徑為一個(gè)以“/”字符結(jié)尾的根目錄且參考路徑為相對(duì)路徑,則返回起點(diǎn)路徑+參考路徑中去除開頭的“./”字符或“../”字符(如果存在的話)后的文字。
- 如果起點(diǎn)路徑為一個(gè)不以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符不為“./”或“../”,則返回路徑為:起點(diǎn)路徑的上層目錄+“/”+參考路徑。如果起點(diǎn)路徑為一個(gè)以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符不為“./”或“../”,則返回路徑為:起點(diǎn)路徑的上層目錄+“/”+參考路徑。
- 如果起點(diǎn)路徑為一個(gè)不以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符為“./”,則返回路徑為:起點(diǎn)路徑的上層目錄+“/”+參考路徑中去除開頭的“./”字符后的文字。如果起點(diǎn)路徑為一個(gè)以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符為“./”,則返回起點(diǎn)路徑+參考路徑中去除開頭的“./”字符后的文字。
- 如果起點(diǎn)路徑為一個(gè)不以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符為“../”,則返回路徑為:起點(diǎn)路徑的上層目錄的上層目錄+“/”+參考路徑中去除開頭的“../”字符后的文字。如果起點(diǎn)路徑為一個(gè)以“/”字符結(jié)尾的子目錄且參考路徑為相對(duì)路徑,同時(shí)開頭字符為“../”,則返
回起點(diǎn)路徑的上層目錄+參考路徑中去除開頭的“../”字符后的文字。