穩(wěn)定性: 3 - 穩(wěn)定
如果要在Node.js中使用HTTP服務(wù)器或客戶端功能,則必須調(diào)用require('http')
。
Node里的HTTP接口支持協(xié)議里原本比較難用的特性。特別是很大的或塊編碼的消息。這些接口不會(huì)完全緩存整個(gè)請(qǐng)求或響應(yīng),這樣用戶可以在請(qǐng)求或響應(yīng)中使用數(shù)據(jù)流。
HTTP消息頭對(duì)象和下面的例子類似:
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }
Keys都是小寫,值不能修改。
為了能支持盡可能多的HTTP應(yīng)用程序,Node提供的HTTP API接口都是底層的。僅能處理流和消息。它把消息解析成報(bào)文頭和報(bào)文體,但是不解析實(shí)際的報(bào)文頭和報(bào)文體內(nèi)容。
定義報(bào)文頭的時(shí)候,多個(gè)值間可用,
分隔。除了set-cookie
和cookie
頭,因?yàn)樗鼈儽硎局档臄?shù)組。諸如content-length
的只有一個(gè)值的報(bào)文頭,直接解析,并且只有單值可以表示成已經(jīng)解析好的對(duì)象。
接收到的原始頭信息以數(shù)組([key, value, key2, value2, ...]
)的形式保存在rawHeaders
里。例如,之前提到的消息對(duì)象會(huì)有如下的rawHeaders
:
[ 'ConTent-Length', '123456',
'content-LENGTH', '123',
'content-type', 'text/plain',
'CONNECTION', 'keep-alive',
'Host', 'mysite.com',
'accepT', '*/*' ]
解析器支持的HTTP方法列表。
全部標(biāo)準(zhǔn)HTTP響應(yīng)狀態(tài)碼的和描述的集合。例如,http.STATUS_CODES[404] === 'Not Found'
。
返回http.Server的新實(shí)例。
requestListener
函數(shù)自動(dòng)加到'request'
事件里。
這個(gè)函數(shù)已經(jīng)被拋棄,用http.request()替換。創(chuàng)建一個(gè)新的HTTP客戶端,連接到服務(wù)器的port
和host
。
這是事件分發(fā)器EventEmitter,有以下事件:
function (request, response) { }
每當(dāng)有請(qǐng)求的時(shí)候觸發(fā)。注意:每個(gè)連接可以有多個(gè)請(qǐng)求(在keep-alive連接中)。request
是http.IncomingMessage實(shí)例,response
是http.ServerResponse 的實(shí)例。
function (socket) { }
當(dāng)建立新的TCP流的時(shí)候。socket
是一個(gè)net.Socket
對(duì)象。通常用戶不會(huì)訪問(wèn)這個(gè)事件。協(xié)議解析器綁定套接字時(shí)采用的方式使套接字不會(huì)出發(fā)readable事件。也能通過(guò)request.connection
訪問(wèn)socket
。
function () { }
服務(wù)器關(guān)閉的時(shí)候觸發(fā)。
function (request, response) { }
當(dāng)http收到100-continue的http請(qǐng)求時(shí)會(huì)觸發(fā)。如果沒(méi)有監(jiān)聽(tīng)這個(gè)事件,服務(wù)器將會(huì)自動(dòng)發(fā)送100 Continue的響應(yīng)。
如果客戶端需要繼續(xù)發(fā)送請(qǐng)求主題,或者生成合適的HTTP響應(yīng)(如,400請(qǐng)求無(wú)效),可以通過(guò)調(diào)用response.writeContinue()來(lái)處理。
注意:觸發(fā)并處理這個(gè)事件的時(shí)候,不會(huì)再觸發(fā)request
事件。
function (request, socket, head) { }
當(dāng)客戶端請(qǐng)求http連接時(shí)觸發(fā)。如果沒(méi)有監(jiān)聽(tīng)這個(gè)事件,客戶端請(qǐng)求連接的時(shí)候會(huì)被關(guān)閉。
request
是http請(qǐng)求的參數(shù),與request事件參數(shù)相同。socket
是服務(wù)器和客戶端間的socket。head
是buffer的實(shí)例。網(wǎng)絡(luò)隧道的第一個(gè)包,可能為空。這個(gè)事件觸發(fā)后,請(qǐng)求的socket不會(huì)有data
事件監(jiān)聽(tīng)器,也就是說(shuō)你需要綁定一個(gè)監(jiān)聽(tīng)器到data
上,來(lái)處理在發(fā)送到服務(wù)器上的socket數(shù)據(jù)。
function (request, socket, head) { }
當(dāng)客戶端請(qǐng)求http upgrage時(shí)候會(huì)觸發(fā)。如果沒(méi)有監(jiān)聽(tīng)這個(gè)事件,客戶端請(qǐng)求一個(gè)連接的時(shí)候會(huì)被關(guān)閉。
request
是http請(qǐng)求的參數(shù),與request事件參數(shù)相同。socket
是服務(wù)器和客戶端間的socket。head
是buffer的實(shí)例。網(wǎng)絡(luò)隧道的第一個(gè)包,可能為空。這個(gè)事件觸發(fā)后,請(qǐng)求的socket不會(huì)有data
事件監(jiān)聽(tīng)器,也就是說(shuō)你需要綁定一個(gè)監(jiān)聽(tīng)器到data
上,來(lái)處理在發(fā)送到服務(wù)器上的socket數(shù)據(jù)。
function (exception, socket) { }
如果一個(gè)客戶端連接觸發(fā)了一個(gè)'error'事件,它就會(huì)轉(zhuǎn)發(fā)到這里.
socket
是導(dǎo)致錯(cuò)誤的net.Socket
對(duì)象。
在指定的的端口和主機(jī)名上開(kāi)始接收連接。如果忽略主機(jī)名,服務(wù)器將會(huì)接收指向任意的IPv4地址(INADDR_ANY
)。
監(jiān)聽(tīng)一個(gè)unix socket,需要提供一個(gè)文件名而不是主機(jī)名和端口。
積壓量backlog為等待連接隊(duì)列的最大長(zhǎng)度。實(shí)際的長(zhǎng)度由你的操作系統(tǒng)的sysctl設(shè)置決定(比如linux上的tcp_max_syn_backlog
和somaxconn
)。默認(rèn)參數(shù)值為 511 (不是512)
這是異步函數(shù)。最后一個(gè)參數(shù)callback
會(huì)作為事件監(jiān)聽(tīng)器添加到listening
事件。參見(jiàn)net.Server.listen(port)。
啟動(dòng)一個(gè)UNIX socket服務(wù)器所給路徑path
這是異步函數(shù)。最后一個(gè)參數(shù)callback
會(huì)作為事件監(jiān)聽(tīng)器添加到listening
事件。參見(jiàn)net.Server.listen(port)。
handle
{Object}callback
{Function}
handle
對(duì)象可以是server或socket(任意以下劃線_handle
開(kāi)頭的成員),或者{fd: <n>}
對(duì)象。
這會(huì)導(dǎo)致server用參數(shù)handle
接收連接,前提條件是文件描述符或句柄已經(jīng)連接到端口或域socket。
Windows不能監(jiān)聽(tīng)文件句柄。
這是異步函數(shù)。最后一個(gè)參數(shù)callback
會(huì)作為事件監(jiān)聽(tīng)器添加到listening
事件。參見(jiàn)net.Server.listen(port)。
用于禁止server接收連接。參見(jiàn)net.Server.close().
最大請(qǐng)求頭的數(shù)量限制,默認(rèn)為1000。如果設(shè)置為0,則不做任何限制。
msecs
{Number}callback
{Function}為socket設(shè)置超時(shí)時(shí)間,單位為毫秒,如果發(fā)生超時(shí),在server對(duì)象上觸發(fā)'timeout'
事件,參數(shù)為socket。
如果在Server對(duì)象上有一個(gè)'timeout'
事件監(jiān)聽(tīng)器,超時(shí)的時(shí)候,將會(huì)調(diào)用它,參數(shù)為socket。
默認(rèn)情況下,Server的超時(shí)為2分鐘,如果超時(shí)將會(huì)銷毀socket。如果你給Server的超時(shí)事件設(shè)置了回調(diào)函數(shù),那你就得負(fù)責(zé)處理socket超時(shí)。
超時(shí)的時(shí)長(zhǎng),單位為毫秒。
注意,socket的超時(shí)邏輯在連接時(shí)設(shè)定,所以有新的連接時(shí)才能改變這個(gè)值。
設(shè)為0時(shí),建立連接的自動(dòng)超時(shí)將失效。
這是一個(gè)由HTTP服務(wù)器(而不是用戶)內(nèi)部創(chuàng)建的對(duì)象。作為第二個(gè)參數(shù)傳遞給'request'
事件。
該響應(yīng)實(shí)現(xiàn)了Writable Stream接口。這是一個(gè)包含下列事件的EventEmitter :
function () { }
在調(diào)用response.end(),或準(zhǔn)備flush前,底層連接結(jié)束。
function () { }
發(fā)送完響應(yīng)觸發(fā)。響應(yīng)頭和響應(yīng)體最后一段數(shù)據(jù)被剝離給操作系統(tǒng)后,通過(guò)網(wǎng)絡(luò)來(lái)傳輸時(shí)被觸發(fā)。這并不代表客戶端已經(jīng)收到數(shù)據(jù)。
這個(gè)事件之后,響應(yīng)對(duì)象不會(huì)再觸發(fā)任何事件。
發(fā)送HTTP/1.1 100 Continue消息給客戶端,表示請(qǐng)求體可以發(fā)送??梢栽诜?wù)器上查看'checkContinue'事件。
發(fā)送一個(gè)響應(yīng)頭給請(qǐng)求。狀態(tài)碼是3位數(shù)字,如404
。最后一個(gè)參數(shù)headers
是響應(yīng)頭。建議第二個(gè)參數(shù)設(shè)置為可以看的懂的消息。
例如:
var body = 'hello world';
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain' });
這個(gè)方法僅能在消息中調(diào)用一次,而且必須在response.end()前調(diào)用。
如果你在這之前調(diào)用response.write()或response.end(),將會(huì)計(jì)算出不穩(wěn)定的頭。
Content-Length是字節(jié)數(shù),而不是字符數(shù)。上面的例子'hello world'
僅包含一個(gè)字節(jié)字符。如果body包含高級(jí)編碼的字符,則Buffer.byteLength()
就必須確定指定編碼的字符數(shù)。Node不會(huì)檢查Content-Length和body的長(zhǎng)度是否相同。
msecs
{Number}callback
{Function}設(shè)置socket超時(shí)時(shí)間,單位為毫秒。如果提供了回調(diào)函數(shù),將會(huì)在response對(duì)象的'timeout'
事件上添加監(jiān)聽(tīng)器。
如果沒(méi)有給請(qǐng)求、響應(yīng)、服務(wù)器添加'timeout'
監(jiān)視器,超時(shí)的時(shí)候?qū)?huì)銷毀socket。如果你給請(qǐng)求、響應(yīng)、服務(wù)器加了處理函數(shù),就需要負(fù)責(zé)處理socket超時(shí)。
使用默認(rèn)的headers 時(shí)(沒(méi)有顯式的調(diào)用response.writeHead()),這個(gè)屬性表示將要發(fā)送給客戶端狀態(tài)碼。
例如:
response.statusCode = 404;
響應(yīng)頭發(fā)送給客戶端的后,這個(gè)屬性表示狀態(tài)碼已經(jīng)發(fā)送。
使用默認(rèn)headers時(shí)(沒(méi)有顯式的調(diào)用response.writeHead()),這個(gè)屬性表示將要發(fā)送給客戶端狀態(tài)信息。如果這個(gè)沒(méi)有定義,將會(huì)使用狀態(tài)碼的標(biāo)準(zhǔn)消息。
例如:
response.statusMessage = 'Not found';
當(dāng)響應(yīng)頭發(fā)送給客戶端的時(shí)候,這個(gè)屬性表示狀態(tài)消息已經(jīng)發(fā)送。
設(shè)置默認(rèn)頭某個(gè)字段內(nèi)容。如果這個(gè)頭即將被發(fā)送,內(nèi)容會(huì)被替換。如果你想設(shè)置更多的頭, 就使用一個(gè)相同名字的字符串?dāng)?shù)組。
例如:
response.setHeader("Content-Type", "text/html");
或
response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
Boolean(只讀)。如果headers發(fā)送完畢,則為true,反之為false。
默認(rèn)值為true。若為true,當(dāng)headers里沒(méi)有Date值時(shí),自動(dòng)生成Date并發(fā)送。
只有在測(cè)試環(huán)境才能禁用,因?yàn)镠TTP要求響應(yīng)包含Date頭.
讀取一個(gè)在隊(duì)列中但是還沒(méi)有被發(fā)送至客戶端的header。名字是大小寫敏感的。僅能再頭被flushed前調(diào)用。
例如:
var contentType = response.getHeader('content-type');
從即將發(fā)送的隊(duì)列里移除頭。
例如:
response.removeHeader("Content-Encoding");
如果調(diào)用了這個(gè)方法,且還沒(méi)有調(diào)用response.writeHead(),將會(huì)切換到默認(rèn)的header,并更新這個(gè)header。
這個(gè)方法將發(fā)送響應(yīng)體數(shù)據(jù)塊。可能會(huì)多次調(diào)用這個(gè)方法,以提供body成功的部分內(nèi)容。
chunk
可以是字符串或 buffer。如果chunk
是字符串,第二個(gè)參數(shù)表明如何將它編碼成字節(jié)流。encoding
的默認(rèn)值是'utf8'
。最后一個(gè)參數(shù)在刷新這個(gè)數(shù)據(jù)塊時(shí)調(diào)用。
注意:這個(gè)是原始的HTTP body,和高級(jí)的multi-part body編碼無(wú)關(guān)。
第一次調(diào)用response.write()
的時(shí)候,將會(huì)發(fā)送緩存的頭信息和第一個(gè)body給客戶端。第二次,將會(huì)調(diào)用response.write()
。Node認(rèn)為你將會(huì)獨(dú)立發(fā)送流數(shù)據(jù)。這意味著,響應(yīng)緩存在第一個(gè)數(shù)據(jù)塊中。
如果成功的刷新全部數(shù)據(jù)到內(nèi)核緩沖區(qū),返回true
。如果部分或全部數(shù)據(jù)在用戶內(nèi)存中還處于排隊(duì)狀況,返回false
。當(dāng)緩存再次釋放的時(shí)候,將會(huì)觸發(fā) 'drain'
。
這個(gè)方法給響應(yīng)添加HTTP的尾部header(消息末尾的header)。
只有數(shù)據(jù)塊編碼用于響應(yīng)體時(shí),才會(huì)觸發(fā)Trailers;如果不是(例如,請(qǐng)求是HTTP/1.0),它們將會(huì)被自動(dòng)丟棄。
如果你想觸發(fā)trailers, HTTP會(huì)要求發(fā)送Trailer
頭,它包含一些信息,比如:
response.writeHead(200, { 'Content-Type': 'text/plain',
'Trailer': 'Content-MD5' });
response.write(fileData);
response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});
response.end();
這個(gè)方法告訴服務(wù)器,所有的響應(yīng)頭和響應(yīng)體已經(jīng)發(fā)送;服務(wù)器可以認(rèn)為消息結(jié)束。response.end()
方法必須在每個(gè)響應(yīng)中調(diào)用。
如果指定了參數(shù)data
,將會(huì)在響應(yīng)流結(jié)束的時(shí)候調(diào)用。
Node維護(hù)每個(gè)服務(wù)器的連接來(lái)生成HTTP請(qǐng)求。這個(gè)函數(shù)讓你可以發(fā)布請(qǐng)求。
參數(shù)options
是對(duì)象或字符串。如果options
是字符串,會(huì)通過(guò)url.parse()自動(dòng)解析。
options
值:
host
: 請(qǐng)求的服務(wù)器域名或 IP 地址,默認(rèn):'localhost'
hostname
: 用于支持url.parse()
。hostname
優(yōu)于host
port
: 遠(yuǎn)程服務(wù)器端口。 默認(rèn)為:80.localAddress
: 用于綁定網(wǎng)絡(luò)連接的本地接口socketPath
: Unix域socket(使用host:port或socketPath)method
: 指定 HTTP 請(qǐng)求方法。 默認(rèn): 'GET'
.path
: 請(qǐng)求路徑。 默認(rèn)為:'/'
。如果有查詢字符串,則需要包含。例如,'/index.html?page=12'。請(qǐng)求路徑包含非法字符時(shí)拋出異常。目前,只有空格不行,不過(guò)在未來(lái)可能改變。headers
: 包含請(qǐng)求頭的對(duì)象auth
: 用于計(jì)算認(rèn)證頭的基本認(rèn)證,即user:password
agent
: 控制Agent的行為。當(dāng)使用了一個(gè)Agent的時(shí)候,請(qǐng)求將默認(rèn)為Connection: keep-alive
??赡艿闹禐椋?ul>undefined
(default): 在這個(gè)主機(jī)和端口上使用global AgentAgent
object: 在Agent
中顯式使用passed .false
: 選擇性停用連接池,默認(rèn)請(qǐng)求為:Connection: close
.keepAlive
: {Boolean} 持資源池周圍的socket,用于未來(lái)其它請(qǐng)求。默認(rèn)值為false
。keepAliveMsecs
: {Integer} 使用HTTP KeepAlive的時(shí)候,通過(guò)正在保持活動(dòng)的sockets發(fā)送TCP KeepAlive包的頻繁程度。默認(rèn)值為1000。僅當(dāng)keepAlive為true時(shí)才相關(guān)。 可選參數(shù)callback
將會(huì)作為一次性的監(jiān)視器,添加給 'response' 事件。
http.request()返回一個(gè)http.ClientRequest類的實(shí)例。ClientRequest實(shí)例是一個(gè)可寫流對(duì)象。如果需要用POST請(qǐng)求上傳一個(gè)文件的話,就將其寫入到ClientRequest對(duì)象。
例如:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(postData);
req.end();
注意,例子里調(diào)用了req.end()
。http.request()
必須調(diào)用req.end()
來(lái)表明請(qǐng)求已經(jīng)完成,即使沒(méi)有數(shù)據(jù)寫入到請(qǐng)求body里。
如果在請(qǐng)求的時(shí)候遇到錯(cuò)誤(DNS解析、TCP級(jí)別的錯(cuò)誤或?qū)嶋HHTTP解析錯(cuò)誤),在返回的請(qǐng)求對(duì)象時(shí)會(huì)觸發(fā)一個(gè)'error'事件。
有一些特殊的頭需要注意:
發(fā)送Connection: keep-alive
告訴服務(wù)器保持連接,直到下一個(gè)請(qǐng)求到來(lái)。
發(fā)送Content-length
頭將會(huì)禁用chunked編碼。
發(fā)送一個(gè)Expect
頭,會(huì)立即發(fā)送請(qǐng)求頭,一般來(lái)說(shuō),發(fā)送Expect: 100-continue
,你必須設(shè)置超時(shí),并監(jiān)聽(tīng)continue
事件。更多細(xì)節(jié)參見(jiàn)RFC2616 Section 8.2.3。
auth
參數(shù)重寫,來(lái)計(jì)算基本的授權(quán)。因?yàn)槎鄶?shù)請(qǐng)求是沒(méi)有報(bào)文體的GET請(qǐng)求,Node提供了這個(gè)簡(jiǎn)便的方法。和http.request()
唯一不同點(diǎn)在于,這個(gè)方法自動(dòng)設(shè)置GET,并自動(dòng)調(diào)用req.end()
。
例如:
http.get("http://www.google.com/index.html", function(res) {
console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
HTTP Agent用于socket池,用于HTTP客戶端請(qǐng)求。
HTTP Agent也把客戶端請(qǐng)求默認(rèn)為使用Connection:keep-alive 。如果沒(méi)有HTTP請(qǐng)求正在等著成為空閑socket的話,那么socket將關(guān)閉。這意味著,Node的資源池在負(fù)載的情況下對(duì)keep-alive有利,但是仍然不需要開(kāi)發(fā)人員使用KeepAlive來(lái)手動(dòng)關(guān)閉HTTP客戶端。
如果你選擇使用HTTP KeepAlive, 可以創(chuàng)建一個(gè)Agent對(duì)象,將 flag 設(shè)置為true
. (參見(jiàn)下面的constructor options ) ,這樣Agent會(huì)把沒(méi)用到的socket放到池里,以便將來(lái)使用。他們會(huì)被顯式的標(biāo)志,讓Node不運(yùn)行。但是,當(dāng)不再使用它的時(shí)候,需要顯式的調(diào)用destroy()
,這樣socket將會(huì)被關(guān)閉。
當(dāng)socket事件觸發(fā)close
事件或特殊的agentRemove
事件時(shí),socket將會(huì)從agent池里移除。如果你要保持HTTP請(qǐng)求保持長(zhǎng)時(shí)間打開(kāi),并且不希望他們?cè)诔乩?,可以參考以下代碼:
http.get(options, function(res) {
// Do stuff
}).on("socket", function (socket) {
socket.emit("agentRemove");
});
另外,你可以使用agent:false
讓資源池停用:
http.get({
hostname: 'localhost',
port: 80,
path: '/',
agent: false // create a new agent just for this one request
}, function (res) {
// Do stuff with response
})
options
{Object} agent上的設(shè)置選項(xiàng)集合,有以下字段內(nèi)容:keepAlive
{Boolean} 持資源池周圍的socket,用于未來(lái)其它請(qǐng)求。默認(rèn)值為false
。keepAliveMsecs
{Integer} 使用HTTP KeepAlive的時(shí)候,通過(guò)正在保持活動(dòng)的sockets發(fā)送TCP KeepAlive包的頻繁程度。默認(rèn)值為1000。僅當(dāng) keepAlive為true時(shí)才相關(guān)。maxSockets
{Number}在空閑狀態(tài)下,還依然開(kāi)啟的socket的最大值。僅當(dāng)keepAlive
設(shè)置為true的時(shí)候有效。默認(rèn)值為256。被http.request
使用的默認(rèn)的http.globalAgent
,會(huì)設(shè)置全部的值為默認(rèn)。
必須在創(chuàng)建你自己的Agent
對(duì)象后,才能配置這些值。
var http = require('http');
var keepAliveAgent = new http.Agent({ keepAlive: true });
options.agent = keepAliveAgent;
http.request(options, onResponseCallback);
默認(rèn)值為Infinity。決定了每臺(tái)主機(jī)上的agent可以擁有的并發(fā)socket的打開(kāi)數(shù)量,主機(jī)可以是host:port
或host:port:localAddress
。
默認(rèn)值256.對(duì)于支持HTTP KeepAlive的Agent而言,這個(gè)方法設(shè)置了空閑狀態(tài)下仍然打開(kāi)的套接字?jǐn)?shù)的最大值。
這個(gè)對(duì)象包含了當(dāng)前Agent使用中的socket數(shù)組。不要修改它。
使用HTTP KeepAlive的時(shí)候,這個(gè)對(duì)象包含等待當(dāng)前Agent使用的socket數(shù)組。不要修改它。
這個(gè)對(duì)象包含了還沒(méi)分配給socket的請(qǐng)求數(shù)組。不要修改它。
銷毀任意一個(gè)被agent使用的socket。
通常情況下不要這么做。如果你正在使用一個(gè)允許KeepAlive的agent,當(dāng)你知道不在使用它的時(shí)候,最好關(guān)閉agent。否則,socket會(huì)一直保存打開(kāi)狀態(tài),直到服務(wù)器關(guān)閉。
獲取一組請(qǐng)求選項(xiàng)的唯一名,來(lái)確定某個(gè)連接是否可重用。在http agent里,它會(huì)返回host:port:localAddress
。在http agent里, name包括CA,cert, ciphers, 和其他HTTPS/TLS特殊選項(xiàng)來(lái)決定socket是否可以重用。
Agent的全局實(shí)例,是http客戶端的默認(rèn)請(qǐng)求。
該對(duì)象在內(nèi)部創(chuàng)建并從http.request()
返回。他是正在處理的請(qǐng)求,其頭部已經(jīng)在隊(duì)列中。使用setHeader(name, value)
,getHeader(name)
, removeHeader(name)
API可以改變header。當(dāng)關(guān)閉連接的時(shí)候,header將會(huì)和第一個(gè)數(shù)據(jù)塊一起發(fā)送。
為了獲取響應(yīng),可以給請(qǐng)求對(duì)象的'response'
添加監(jiān)聽(tīng)器。當(dāng)接收到響應(yīng)頭的時(shí)候?qū)?huì)從請(qǐng)求對(duì)象里觸發(fā)'response'
。'response'
事件執(zhí)行時(shí)有一個(gè)參數(shù),該參數(shù)為http.IncomingMessage的實(shí)例。
在'response'
事件期間,可以給響應(yīng)對(duì)象添加監(jiān)視器,監(jiān)聽(tīng)'data'
事件。
如果沒(méi)有添加'response'
處理函數(shù),響應(yīng)將被完全忽略。如果你添加了'response'
事件處理函數(shù),那你必須消費(fèi)掉從響應(yīng)對(duì)象獲取的數(shù)據(jù),可以在 'readable'
事件里調(diào)用response.read()
,或者添加一個(gè)'data'
處理函數(shù),或者調(diào)用.resume()
方法。如果未讀取數(shù)據(jù),它將會(huì)消耗內(nèi)存,最終產(chǎn)生 process out of memory
錯(cuò)誤。
Node不會(huì)檢查Content-Length和body的長(zhǎng)度是否相同。
該請(qǐng)求實(shí)現(xiàn)了Writable Stream接口。這是一個(gè)包含下列事件的EventEmitter。
function (response) { }
當(dāng)接收到請(qǐng)求的時(shí)候會(huì)觸發(fā),僅會(huì)觸發(fā)一次。response
的參數(shù)是http.IncomingMessage的實(shí)例。
Options:
host
: 要請(qǐng)求的服務(wù)器域名或IP地址port
: 遠(yuǎn)程服務(wù)器的端口socketPath
: Unix域Socket (使用host:port或socketPath之一)function (socket) { }
Socket附加到這個(gè)請(qǐng)求的時(shí)候觸發(fā)。
function (response, socket, head) { }
每次服務(wù)器使用CONNECT方法響應(yīng)一個(gè)請(qǐng)求時(shí)觸發(fā)。如果這個(gè)這個(gè)事件未被監(jiān)聽(tīng),接收CONNECT方法的客戶端將關(guān)閉他們的連接。
下面的例子展示了一對(duì)匹配的客戶端/服務(wù)器如何監(jiān)聽(tīng)connect
事件。var http = require('http');var net = require('net');var url = require('url');
// Create an HTTP tunneling proxy
var proxy = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
proxy.on('connect', function(req, cltSocket, head) {
// connect to an origin server
var srvUrl = url.parse('http://' + req.url);
var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, function() {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', function() {
// make a request to a tunneling proxy
var options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
var req = http.request(options);
req.end();
req.on('connect', function(res, socket, head) {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', function(chunk) {
console.log(chunk.toString());
});
socket.on('end', function() {
proxy.close();
});
});
});
function (response, socket, head) { }
每當(dāng)服務(wù)器響應(yīng)upgrade請(qǐng)求時(shí)觸發(fā)。如果沒(méi)有監(jiān)聽(tīng)這個(gè)事件,客戶端會(huì)收到upgrade頭后關(guān)閉連接。
下面的例子展示了一對(duì)匹配的客戶端/服務(wù)器如何監(jiān)聽(tīng)upgrade
事件。
var http = require('http');
// Create an HTTP server
var srv = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', function(req, socket, head) {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n');
socket.pipe(socket); // echo back
});
// now that server is running
srv.listen(1337, '127.0.0.1', function() {
// make a request
var options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
req.on('upgrade', function(res, socket, upgradeHead) {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
function () { }
當(dāng)服務(wù)器發(fā)送'100 Continue' HTTP響應(yīng)的時(shí)候觸發(fā),通常因?yàn)檎?qǐng)求包含'Expect: 100-continue'。該指令表示客戶端應(yīng)發(fā)送請(qǐng)求體。
刷新請(qǐng)求的頭。
考慮效率因素,Node.js通常會(huì)緩存請(qǐng)求的頭直到你調(diào)用request.end()
,或?qū)懭胝?qǐng)求的第一個(gè)數(shù)據(jù)塊。然后,包裝請(qǐng)求的頭和數(shù)據(jù)到一個(gè)獨(dú)立的TCP包里。
發(fā)送一個(gè)請(qǐng)求體的數(shù)據(jù)塊。通過(guò)多次調(diào)用這個(gè)函數(shù),用戶能流式的發(fā)送請(qǐng)求給服務(wù)器,這種情況下,建議使用['Transfer-Encoding', 'chunked']
頭。
chunk
參數(shù)必須是Buffer或字符串。
回調(diào)參數(shù)可選,當(dāng)這個(gè)數(shù)據(jù)塊被刷新的時(shí)候會(huì)被調(diào)用。
發(fā)送請(qǐng)求完畢。如果body的數(shù)據(jù)沒(méi)被發(fā)送,將會(huì)將他們刷新到流里。如果請(qǐng)求是分塊的,該方法會(huì)發(fā)送終結(jié)符0\r\n\r\n 。
如果指定了data
,等同于先調(diào)用request.write(data, encoding)
,再調(diào)用request.end(callback)
。
如果有callback
,將會(huì)在請(qǐng)求流結(jié)束的時(shí)候調(diào)用。
終止一個(gè)請(qǐng)求. (v0.3.8開(kāi)始新加入)。
如果socket被分配給這個(gè)請(qǐng)求,并完成連接,將會(huì)調(diào)用socket.setTimeout() 。
如果socket被分配給這個(gè)請(qǐng)求,并完成連接,將會(huì)調(diào)用socket.setNoDelay()。
如果socket被分配給這個(gè)請(qǐng)求,并完成連接,將會(huì)調(diào)用socket.setKeepAlive()。
http.Server或http.ClientRequest創(chuàng)建了IncomingMessage
對(duì)象,作為第一個(gè)參數(shù)傳遞給'response'
。它可以用來(lái)訪問(wèn)應(yīng)答的狀態(tài),頭文件和數(shù)據(jù)。
它實(shí)現(xiàn)了Readable Stream接口,以及以下額外的事件,方法和屬性。
function () { }
表示底層連接已經(jīng)關(guān)閉。和'end'
類似,這個(gè)事件每個(gè)應(yīng)答只會(huì)發(fā)送一次。
客戶端向服務(wù)器發(fā)送請(qǐng)求時(shí),客戶端發(fā)送的 HTTP 版本;或者服務(wù)器想客戶端返回應(yīng)答時(shí),服務(wù)器的HTTP版本。通常是'1.1'
或'1.0'
。
另外,response.httpVersionMajor
是第一個(gè)整數(shù),response.httpVersionMinor
是第二個(gè)整數(shù)。
請(qǐng)求/響應(yīng)頭對(duì)象。
只讀的頭名稱和值的映射。頭的名字是小寫,比如:
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*/*' }
console.log(request.headers);
接收到的請(qǐng)求/響應(yīng)頭字段列表。
注意,鍵和值在同一個(gè)列表中。它并非一個(gè)元組列表。所以,偶數(shù)偏移量為鍵,奇數(shù)偏移量為對(duì)應(yīng)的值。
頭名字不是小寫敏感,也沒(méi)用合并重復(fù)的頭。
// Prints something like:
//
// [ 'user-agent',
// 'this is invalid because there can be only one',
// 'User-Agent',
// 'curl/7.22.0',
// 'Host',
// '127.0.0.1:8000',
// 'ACCEPT',
// '*/*' ]
console.log(request.rawHeaders);
請(qǐng)求/響應(yīng)的尾部對(duì)象。只在'end'事件中存在。
接收到的原始的請(qǐng)求/響應(yīng)尾部鍵和值。僅在'end'事件中存在。
msecs
{Number}callback
{Function}調(diào)用message.connection.setTimeout(msecs, callback)
.
僅對(duì)從http.Server獲得的請(qǐng)求有效。
請(qǐng)求方法如果一個(gè)只讀的字符串。例如:'GET'
,'DELETE'
.
僅對(duì)從http.Server獲得的請(qǐng)求有效。
請(qǐng)求的URL字符串。它僅包含實(shí)際的HTTP請(qǐng)求中所提供的URL,比如請(qǐng)求如下:
GET /status?name=ryan HTTP/1.1\r\n
Accept: text/plain\r\n
\r\n
request.url
就是:
'/status?name=ryan'
如果你想將URL分解,可以用require('url').parse(request.url)
,例如:
node> require('url').parse('/status?name=ryan')
{ href: '/status?name=ryan',
search: '?name=ryan',
query: 'name=ryan',
pathname: '/status' }
如果想從查詢字符串中解析出參數(shù),可以用require('querystring').parse
函數(shù),或者將true
作為第二個(gè)參數(shù)傳遞給require('url').parse
。 例如:
node> require('url').parse('/status?name=ryan', true)
{ href: '/status?name=ryan',
search: '?name=ryan',
query: { name: 'ryan' },
pathname: '/status' }
僅對(duì)從http.ClientRequest
獲取的響應(yīng)有效。
3位數(shù)的HTTP響應(yīng)狀態(tài)碼404
。
僅對(duì)從http.ClientRequest
獲取的響應(yīng)有效。
HTTP的響應(yīng)消息。比如,OK
或Internal Server Error
.
和連接相關(guān)聯(lián)的net.Socket
對(duì)象。
通過(guò)HTTPS支持,使用request.connection.verifyPeer()
和request.connection.getPeerCertificate()
獲取客戶端的身份信息。
更多建議: