你必須通過(guò)require('http')
來(lái)使用HTTP服務(wù)器和客戶(hù)端。
io.js
中的HTTP接口被設(shè)置來(lái)支持許多HTTP協(xié)議里原本用起來(lái)很困難的特性。特別是大且成塊的有編碼的消息。這個(gè)接口從不緩沖整個(gè)請(qǐng)求或響應(yīng)。用戶(hù)可以對(duì)它們使用流。
HTTP消息頭可能是一個(gè)類(lèi)似于以下例子的對(duì)象:
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }
鍵是小寫(xiě)的。值沒(méi)有被修改。
為了全方位的支持所有的HTTP應(yīng)用。io.js
的HTTP API是非常底層的。它只處理流以及解釋消息。它將消息解釋為消息頭和消息體,但是不解釋實(shí)際的消息頭和消息體。
被定義的消息頭允許以多個(gè),
字符分割,除了set-cookie
和cookie
頭,因?yàn)樗鼈儽硎局档脭?shù)組。如content-length
這樣只有單個(gè)值的頭被直接將解析,并且成為解析后對(duì)象的一個(gè)單值。
收到的原始消息頭會(huì)被保留在rawHeaders
屬性中,它是一個(gè)形式如[key, value, key2, value2, ...]
的數(shù)組。例如,之前的消息頭可以有如下的rawHeaders
:
[ 'ConTent-Length', '123456',
'content-LENGTH', '123',
'content-type', 'text/plain',
'CONNECTION', 'keep-alive',
'Host', 'mysite.com',
'accepT', '*/*' ]
一個(gè)被解析器所支持的HTTP方法的列表。
一個(gè)所有標(biāo)準(zhǔn)HTTP響應(yīng)狀態(tài)碼的集合,以及它們的簡(jiǎn)短描述。例如,http.STATUS_CODES[404] === 'Not Found'
。
http.Server
實(shí)例requestListener
是一個(gè)會(huì)被自動(dòng)添加為request
事件監(jiān)聽(tīng)器的函數(shù)。
這個(gè)函數(shù)已經(jīng)被啟用。請(qǐng)使用http.request()
替代。構(gòu)造一個(gè)新的HTTP客戶(hù)端。port
和host
指定了需要連接的目標(biāo)服務(wù)器。
這是一個(gè)具有以下事件的EventEmitter
:
當(dāng)有請(qǐng)求來(lái)到時(shí)觸發(fā)。注意每一個(gè)連接可能有多個(gè)請(qǐng)求(在長(zhǎng)連接的情況下)。請(qǐng)求是一個(gè)http.IncomingMessage
實(shí)例,響應(yīng)是一個(gè)http.ServerResponse
實(shí)例。
當(dāng)一個(gè)新的TCP流建立時(shí)觸發(fā)。socket
是一個(gè)net.Socket
類(lèi)型的實(shí)例。用戶(hù)通常不會(huì)接觸這個(gè)事件。特別的,因?yàn)閰f(xié)議解釋器綁定它的方式,socket
將不會(huì)觸發(fā)readable
事件。這個(gè)socket
可以由request.connection
得到。
當(dāng)服務(wù)器關(guān)閉時(shí)觸發(fā)。
當(dāng)每次收到一個(gè)HTTPExpect: 100-continue
請(qǐng)求時(shí)觸發(fā)。如果不監(jiān)聽(tīng)這個(gè)事件,那么服務(wù)器會(huì)酌情自動(dòng)響應(yīng)一個(gè)100 Continue
。
處理該事件時(shí),如果客戶(hù)端可以繼續(xù)發(fā)送請(qǐng)求主體則調(diào)用response.writeContinue()
, 如果不能則生成合適的HTTP響應(yīng)(如400 Bad Request
)。
注意,當(dāng)這個(gè)事件被觸發(fā)并且被處理,request
事件則不會(huì)再觸發(fā)。
每當(dāng)客戶(hù)端發(fā)起一個(gè)httpCONNECT
請(qǐng)求時(shí)觸發(fā)。如果這個(gè)事件沒(méi)有被監(jiān)聽(tīng),那么客戶(hù)端發(fā)起httpCONNECT
的連接會(huì)被關(guān)閉。
request
是一個(gè)http請(qǐng)求參數(shù),它也被包含在request
事件中。socket
是一個(gè)服務(wù)器和客戶(hù)端間的網(wǎng)絡(luò)套接字。head
是一個(gè)Buffer
實(shí)例,隧道流中的第一個(gè)報(bào)文,該參數(shù)可能為空在這個(gè)事件被觸發(fā)后,請(qǐng)求的socket
將不會(huì)有data
事件的監(jiān)聽(tīng)器,意味著你將要綁定一個(gè)data
事件的監(jiān)聽(tīng)器來(lái)處理這個(gè)socket
中發(fā)往服務(wù)器的數(shù)據(jù)。
每當(dāng)客戶(hù)端發(fā)起一個(gè)httpupgrade
請(qǐng)求時(shí)觸發(fā)。如果這個(gè)事件沒(méi)有被監(jiān)聽(tīng),那么客戶(hù)端發(fā)起upgrade
的連接會(huì)被關(guān)閉。
request
是一個(gè)http請(qǐng)求參數(shù),它也被包含在request
事件中。socket
是一個(gè)服務(wù)器和客戶(hù)端間的網(wǎng)絡(luò)套接字。head
是一個(gè)Buffer
實(shí)例,升級(jí)后流中的第一個(gè)報(bào)文,該參數(shù)可能為空在這個(gè)事件被觸發(fā)后,請(qǐng)求的socket
將不會(huì)有data
事件的監(jiān)聽(tīng)器,意味著你將要綁定一個(gè)data
事件的監(jiān)聽(tīng)器來(lái)處理這個(gè)socket
中發(fā)往服務(wù)器的數(shù)據(jù)。
如果一個(gè)客戶(hù)端連接發(fā)生了錯(cuò)誤,這個(gè)事件將會(huì)被觸發(fā)。
socket
是一個(gè)錯(cuò)誤來(lái)源的net.Socket
對(duì)象。
從指定的端口和主機(jī)名開(kāi)始接收連接。如果hostname
被忽略,那么如果IPv6可用,服務(wù)器將接受任意IPv6地址(::),否則為任何IPv4地址(0.0.0.)。port
為0
將會(huì)設(shè)置一個(gè)隨機(jī)端口。
如果要監(jiān)聽(tīng)一個(gè)unix socket
,請(qǐng)?zhí)峁┮粋€(gè)文件名而不是端口和主機(jī)名。
backlog
是連接等待隊(duì)列的最大長(zhǎng)度。它的實(shí)際長(zhǎng)度將有你操作系統(tǒng)的sysctl
設(shè)置(如linux中的tcp_max_syn_backlog
和somaxconn
)決定。默認(rèn)值為511
(不是512
)。
這個(gè)函數(shù)式異步的。最后一個(gè)callback
參數(shù)將會(huì)添加至listening
事件的監(jiān)聽(tīng)器。參閱net.Server.listen(port)
。
通過(guò)給定的path
,開(kāi)啟一個(gè)監(jiān)聽(tīng)連接的 UNIX socket
服務(wù)器。
這個(gè)函數(shù)式異步的。最后一個(gè)callback
參數(shù)將會(huì)添加至listening
事件的監(jiān)聽(tīng)器。參閱net.Server.listen(path)
。
handle
對(duì)象是既可以是一個(gè)server可以是一個(gè)socket
(或者任意以下劃線開(kāi)頭的成員_handle
),或一個(gè){fd: <n>}
對(duì)象。
這將使得服務(wù)器使用指定句柄接受連接,但它假設(shè)文件描述符或句柄已經(jīng)被綁定至指定的端口或域名socket
。
在Windows下不支持監(jiān)聽(tīng)一個(gè)文件描述符。
這個(gè)函數(shù)式異步的。最后一個(gè)callback
參數(shù)將會(huì)添加至listening
事件的監(jiān)聽(tīng)器。參閱net.Server.listen()
。
讓服務(wù)器停止接收新的連接。參閱net.Server.close()
。
限制最大請(qǐng)求頭數(shù)量,默認(rèn)為1000
。如果設(shè)置為0
,則代表無(wú)限制。
設(shè)置socket
的超時(shí)值,并且如果超時(shí),會(huì)在服務(wù)器對(duì)象上觸發(fā)一個(gè)timeout
事件,并且將傳遞socket
作為參數(shù)。
如果在服務(wù)器對(duì)象時(shí)又一個(gè)timeout
事件監(jiān)聽(tīng)器,那么它將會(huì)被調(diào)用,而超時(shí)的socket
將會(huì)被作為參數(shù)。
默認(rèn)的,服務(wù)器的超時(shí)值是兩分鐘,并且如果超時(shí),socket
會(huì)被自動(dòng)銷(xiāo)毀。但是,如果你給timeout
事件傳遞了回調(diào)函數(shù),那么你必須為要親自處理socket
超時(shí)。
返回一個(gè)server
對(duì)象。
120000
(兩分鐘)一個(gè)socket
被判定為超時(shí)之前的毫秒數(shù)。
注意,socket
的超時(shí)邏輯在連接時(shí)被設(shè)定,所以改變它的值僅影響之后到達(dá)服務(wù)器的連接,而不是所有的連接。
設(shè)置為0
將會(huì)為連接禁用所有的自動(dòng)超時(shí)行為。
這個(gè)對(duì)象由HTTP服務(wù)器內(nèi)部創(chuàng)建,而不是由用戶(hù)。它會(huì)被傳遞給request
事件監(jiān)聽(tīng)器的第二個(gè)參數(shù)。
這個(gè)對(duì)象實(shí)現(xiàn)了Writable
流接口。它是一個(gè)具有以下事件的EventEmitter
:
表明底層的連接在response.end()
被調(diào)用或能夠沖刷前被關(guān)閉。
當(dāng)響應(yīng)被設(shè)置時(shí)觸發(fā)。更明確地說(shuō),這個(gè)事件在當(dāng)響應(yīng)頭的最后一段和響應(yīng)體為了網(wǎng)絡(luò)傳輸而交給操作系統(tǒng)時(shí)觸發(fā)。它并不表明客戶(hù)端已經(jīng)收到了任何信息。
這個(gè)事件之后,response
對(duì)象不會(huì)再觸發(fā)任何事件。
給客戶(hù)端傳遞一個(gè)HTTP/1.1 100 Continue
信息,表明請(qǐng)求體必須被傳遞。參閱服務(wù)器的checkContinue
事件。
為請(qǐng)求設(shè)置一個(gè)響應(yīng)頭。statusCode
是一個(gè)三位的HTTP狀態(tài)碼,如404
。最后一個(gè)參數(shù)headers
,是響應(yīng)頭。第二個(gè)參數(shù)statusMessage
是可選的,表示狀態(tài)碼的一個(gè)可讀信息。
例子:
var body = 'hello world';
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain' });
這個(gè)方法對(duì)于一個(gè)信息只能調(diào)用一次,并且它必須在response.end()
之前被調(diào)用。
如果你在調(diào)用這個(gè)方法前調(diào)用了response.write()
或response.end()
,將會(huì)調(diào)用這個(gè)函數(shù),并且一個(gè)implicit/mutable
頭會(huì)被計(jì)算使用。
注意,Content-Length
是以字節(jié)計(jì),而不是以字符計(jì)。上面例子能正常運(yùn)行時(shí)因?yàn)樽址?code>'hello world'僅包含單字節(jié)字符。如果響應(yīng)體包含了多字節(jié)編碼的字符,那么必須通過(guò)指定的編碼來(lái)調(diào)用Buffer.byteLength()
來(lái)確定字節(jié)數(shù)。并且io.js
不會(huì)檢查Content-Length
與響應(yīng)體的字節(jié)數(shù)是否相等。
設(shè)置socket
的超時(shí)值(毫秒),如果傳遞了回調(diào)函數(shù),那么它將被添加至response
對(duì)象的timeout
事件的監(jiān)聽(tīng)器。
如果沒(méi)有為request
,request
或服務(wù)器添加timeout
監(jiān)聽(tīng)器。那么socket
會(huì)在超時(shí)時(shí)銷(xiāo)毀。如果你為request
,request
或服務(wù)器添加了timeout
監(jiān)聽(tīng)器,那么你必須為要親自處理socket
超時(shí)。
返回一個(gè)response
對(duì)象。
當(dāng)使用隱式響應(yīng)頭(不明確調(diào)用response.writeHead()
)時(shí),這個(gè)屬性控制了發(fā)送給客戶(hù)端的狀態(tài)碼,在當(dāng)響應(yīng)頭被沖刷時(shí)。
例子:
response.statusCode = 404;
在響應(yīng)頭發(fā)送給客戶(hù)端之后,這個(gè)屬性表明了被發(fā)送的狀態(tài)碼。
當(dāng)使用隱式響應(yīng)頭(不明確調(diào)用response.writeHead()
)時(shí),這個(gè)屬性控制了發(fā)送給客戶(hù)端的狀態(tài)信息,在當(dāng)響應(yīng)頭被沖刷時(shí)。當(dāng)它沒(méi)有被指定(undefined
)時(shí),將會(huì)使用標(biāo)準(zhǔn)HTTP狀態(tài)碼信息。
例子:
response.statusMessage = 'Not found';
在響應(yīng)頭發(fā)送給客戶(hù)端之后,這個(gè)屬性表明了被發(fā)送的狀態(tài)信息。
為一個(gè)隱式的響應(yīng)頭設(shè)置一個(gè)單獨(dú)的頭內(nèi)容。如果這個(gè)頭已存在,那么將會(huì)被覆蓋。當(dāng)你需要發(fā)送一個(gè)同名多值的頭內(nèi)容時(shí)請(qǐng)使用一個(gè)字符串?dāng)?shù)組。
例子:
response.setHeader("Content-Type", "text/html");
//or
response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
布爾值(只讀)。如果響應(yīng)頭被發(fā)送則為true
,反之為false
。
當(dāng)為true
時(shí),當(dāng)響應(yīng)頭中沒(méi)有Date
值時(shí)會(huì)被自動(dòng)設(shè)置。默認(rèn)為true
。
這個(gè)值只會(huì)為了測(cè)試目的才會(huì)被禁用。HTTP協(xié)議要求響應(yīng)頭中有Date
值。
讀取已經(jīng)被排隊(duì)但還未發(fā)送給客戶(hù)端的響應(yīng)頭。注意name
是大小寫(xiě)敏感的。這個(gè)函數(shù)只能在響應(yīng)頭被隱式?jīng)_刷前被調(diào)用。
例子:
var contentType = response.getHeader('content-type');
取消一個(gè)在隊(duì)列中等待隱式發(fā)送的頭。
例子:
response.removeHeader("Content-Encoding");
如果這個(gè)方法被調(diào)用并且response.writeHead()
沒(méi)有備調(diào)用,那么它將轉(zhuǎn)換到隱式響應(yīng)頭模式,并且刷新隱式響應(yīng)頭。
這個(gè)方法傳遞一個(gè)數(shù)據(jù)塊的響應(yīng)體。這個(gè)方法可能被調(diào)用多次來(lái)保證連續(xù)的提供響應(yīng)體。
數(shù)據(jù)塊可以是一個(gè)字符串或一個(gè)buffer
。如果數(shù)據(jù)塊是一個(gè)字符串,那么第二個(gè)參數(shù)是它的編碼。默認(rèn)是UTF-8.最后一個(gè)回調(diào)函數(shù)參數(shù)會(huì)在數(shù)據(jù)塊被沖刷后觸發(fā)。注意:這是一個(gè)底層的HTTP報(bào)文,高級(jí)的多部分報(bào)文編碼無(wú)法使用。
第一次調(diào)用response.write()
時(shí),它會(huì)傳遞緩存的頭信息以及第一個(gè)報(bào)文給客戶(hù)端。第二次調(diào)用時(shí),io.js
假設(shè)你將發(fā)送數(shù)據(jù)流,然后分別發(fā)送。這意味著響應(yīng)式緩沖到第一個(gè)報(bào)文的數(shù)據(jù)塊中。
如果整個(gè)數(shù)據(jù)都成功得沖刷至內(nèi)核緩沖,則放回true
。如果用戶(hù)內(nèi)存中有部分或全部的數(shù)據(jù)在隊(duì)列中,那么返回false
。drain
事件將會(huì)在緩沖再次釋放時(shí)觸發(fā)。
這個(gè)方法添加HTTP尾隨頭(一個(gè)在消息最后的頭)給響應(yīng)。
只有當(dāng)數(shù)據(jù)編碼被用于響應(yīng)時(shí)尾隨才會(huì)觸發(fā)。如果不是(如請(qǐng)求是HTTP/1.0
),它們將被安靜地丟棄。
注意,如果你要觸發(fā)尾隨消息,HTTP要求傳遞一個(gè)包含報(bào)文頭場(chǎng)列表的尾隨頭:
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ù)器會(huì)認(rèn)為這個(gè)消息完成了。這個(gè)方法必須在每次響應(yīng)完成后被調(diào)用。
如果指定了data
,就相當(dāng)于調(diào)用了response.write(data, encoding)
之后再調(diào)用response.end(callback)
。
如果指定了回調(diào)函數(shù),那么它將在響應(yīng)流結(jié)束后觸發(fā)。
io.js
為每個(gè)服務(wù)器維護(hù)了幾個(gè)連接,用來(lái)產(chǎn)生HTTP請(qǐng)求。這函數(shù)允許你透明地發(fā)送請(qǐng)求。
options
參數(shù)可以是一個(gè)對(duì)象或一個(gè)字符串,如果options
是一個(gè)字符串,它將自動(dòng)得被url.parse()
翻譯。
Options:
localhost
。host
的別名。為了支持url.parse()
的話,hostname
比host
更好些。host
和hostname
時(shí)的IP地址協(xié)議族。合法值是4
和6
。當(dāng)沒(méi)有指定時(shí),將都被使用。80
。socket
(使用host:port
或socketPath
)。GET
。/
。如果有查詢(xún)字符串,則需要包含。例如'/index.html?page=12'。請(qǐng)求路徑包含非法字符時(shí)拋出異常。目前,只否決空格,不過(guò)在未來(lái)可能改變。'user:password'
。agent: 控制agent
行為。當(dāng)使用一個(gè)代理時(shí),請(qǐng)求將默認(rèn)為Connection: keep-alive
??赡苤涤校?/p>
agent
中顯示使用passed。agent
的連接池。默認(rèn)請(qǐng)求為Connection: close
。可選的回調(diào)函數(shù)將會(huì)被添加為response
事件的“一次性”監(jiān)聽(tīng)器(one time listener)。
http.request()
返回一個(gè)http.ClientRequest
類(lèi)的實(shí)例。這個(gè)ClientRequest
實(shí)例是一個(gè)可寫(xiě)流。如果你需要使用POST
請(qǐng)求上傳一個(gè)文件,那么就將之寫(xiě)入這個(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);
});
res.on('end', function() {
console.log('No more data in response.')
})
});
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()
時(shí)必須調(diào)用req.end()
來(lái)表明你已經(jīng)完成了請(qǐng)求(即使沒(méi)有數(shù)據(jù)要被寫(xiě)入請(qǐng)求體)。
如果有一個(gè)錯(cuò)誤在請(qǐng)求時(shí)發(fā)生(如DNS解析,TCP級(jí)別錯(cuò)誤或?qū)嶋H的HTTP解析錯(cuò)誤),一個(gè)error
事件將會(huì)在返回對(duì)象上觸發(fā)。
下面有一些特殊的需要主要的請(qǐng)求頭:
發(fā)送'Connection: keep-alive'
會(huì)告知io.js
保持連直到下一個(gè)請(qǐng)求發(fā)送。
發(fā)送'Content-length'
頭會(huì)禁用默認(rèn)的數(shù)據(jù)塊編碼。
發(fā)送'Expect'
頭將會(huì)立刻發(fā)送一個(gè)請(qǐng)求頭。通常,當(dāng)發(fā)送'Expect: 100-continue'
時(shí),你需要同時(shí)設(shè)置一個(gè)超時(shí)和監(jiān)聽(tīng)后續(xù)的時(shí)間。參閱RFC2616的8.2.3章節(jié)來(lái)獲取更多信息。
發(fā)送一個(gè)授權(quán)頭將會(huì)覆蓋使用auth
選項(xiàng)來(lái)進(jìn)行基本授權(quán)。
由于大多數(shù)請(qǐng)求是沒(méi)有請(qǐng)求體的GET
請(qǐng)求。io.js
提供了這個(gè)簡(jiǎn)便的方法。這個(gè)方法和http.request()
方法的唯一區(qū)別是它設(shè)置請(qǐng)求方法為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是用來(lái)把HTTP客戶(hù)端請(qǐng)求中的socket
做成池。
HTTP Agent 也把客戶(hù)端的請(qǐng)求默認(rèn)為使用Connection:keep-alive
。如果沒(méi)有HTTP請(qǐng)求正在等待成為空閑的套接字的話,那么套接字將關(guān)閉。這意味著io.js
的資源池在負(fù)載的情況下對(duì)keep-alive
有利,但是仍然不需要開(kāi)發(fā)人員使用KeepAlive來(lái)手動(dòng)關(guān)閉HTTP客戶(hù)端。
如果你選擇使用HTTP KeepAlive
,那么你可以創(chuàng)建一個(gè)標(biāo)志設(shè)為true
的Agent對(duì)象(見(jiàn)下面的構(gòu)造函數(shù)選項(xiàng))。然后,Agent將會(huì)在資源池中保持未被使用的套接字,用于未來(lái)使用。它們將會(huì)被顯式標(biāo)記,以便于不保持io.js
進(jìn)程的運(yùn)行。但是當(dāng)KeepAlive agent沒(méi)有被使用時(shí),顯式地destroy()
KeepAlive agent仍然是個(gè)好主意,這樣socket
會(huì)被關(guān)閉。
當(dāng)socket
觸發(fā)了close
事件或者特殊的agentRemove
事件的時(shí)候,套接字們從agent的資源池中移除。這意味著如果你打算保持一個(gè)HTTP請(qǐng)求長(zhǎng)時(shí)間開(kāi)啟,并且不希望它保持在資源池中,那么你可以按照下列幾行的代碼做事:
http.get(options, function(res) {
// Do stuff
}).on("socket", function (socket) {
socket.emit("agentRemove");
});
另外,你可以使用agent:false
來(lái)停用池:
http.get({
hostname: 'localhost',
port: 80,
path: '/',
agent: false // create a new agent just for this one request
}, function (res) {
// Do stuff with response
})
new Agent([options])#
options Object 為agent設(shè)置可配置的選項(xiàng)。可以有以下屬性:
socket
被其他請(qǐng)求所使用,默認(rèn)為false
socket
發(fā)送TCP KeepAlive 報(bào)文的間隔。默認(rèn)為1000
。只在KeepAlive
被設(shè)置為true
時(shí)有效socket
的最大數(shù)量。默認(rèn)為Infinity
socket
數(shù)。僅在keepAlive
為true
時(shí)有效。默認(rèn)為256
http.request
使用的默認(rèn)的http.globalAgent
包含它們屬性的各自的默認(rèn)值。
為了配置它們中的任何一個(gè),你必須創(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
。決定了每個(gè)源上可以擁有的并發(fā)的socket
的數(shù)量。源為'host:port'
或'host:port:localAddress'
結(jié)合體。
默認(rèn)為256
。對(duì)于支持HTTP KeepAlive的Agent,這設(shè)置了在空閑狀態(tài)下保持打開(kāi)的最大socket
數(shù)量。
這個(gè)對(duì)象包含了正在被Agent使用desocket
數(shù)組。請(qǐng)不要修改它。
這個(gè)對(duì)象包含了當(dāng)HTTP KeepAlive被使用時(shí)正在等待的socket
數(shù)組。請(qǐng)不要修改它。
這個(gè)對(duì)象包含了還沒(méi)有被分配給socket
的請(qǐng)求隊(duì)列。請(qǐng)不要修改它。
銷(xiāo)毀正在被agent使用的所有socket
。
通常沒(méi)有必要這么做。但是,如果你正在使用一個(gè)啟用了KeepAlive
的agent,那么最好明確地關(guān)閉agent當(dāng)你知道它不會(huì)再被使用時(shí)。否則,在服務(wù)器關(guān)閉它們前socket
可能被閑置。
通過(guò)一個(gè)請(qǐng)求選項(xiàng)集合來(lái)獲取一個(gè)獨(dú)一無(wú)二的名字,來(lái)決定一個(gè)連接是否可被再使用。在http代理中,這返回host:port:localAddress
。在https代理中,name
包括了CA,cert,ciphers和HTTPS/TLS-specific
配置來(lái)決定一個(gè)socket
是否能被再使用。
所有的http客戶(hù)端請(qǐng)求使用的默認(rèn)全局Agent
實(shí)例。
這個(gè)對(duì)象時(shí)被內(nèi)部創(chuàng)建的,并且通過(guò)http.request()
被返回。它代表了一個(gè)正在處理的請(qǐng)求,其頭部已經(jīng)進(jìn)入了隊(duì)列。這個(gè)頭部仍然可以通過(guò)setHeader(name, value)
,getHeader(name)
和removeHeader(name)
修改。實(shí)際的頭部會(huì)隨著第一個(gè)數(shù)據(jù)塊發(fā)送,或在關(guān)閉連接時(shí)發(fā)送。
要獲得響應(yīng)對(duì)象,請(qǐng)為response
事件添加一個(gè)監(jiān)聽(tīng)器。request
對(duì)象的response
事件將會(huì)在收到響應(yīng)頭時(shí)觸發(fā)。這個(gè)response
事件的第一個(gè)參數(shù)是一個(gè)http.IncomingMessage
的實(shí)例。
在response
事件期間,可以給響應(yīng)對(duì)象添加監(jiān)聽(tīng)器;尤其是監(jiān)聽(tīng)data
事件。
如果沒(méi)有添加response
事件監(jiān)聽(tīng)器,那么響應(yīng)會(huì)被完全忽略。但是,如果你添加了response
事件,那么你必須通過(guò)調(diào)用response.read()
,添加data
事件監(jiān)聽(tīng)器或調(diào)用.resume()
方法等等,來(lái)從響應(yīng)對(duì)象中消耗數(shù)據(jù)。在數(shù)據(jù)被消費(fèi)之前,end
事件不會(huì)觸發(fā)。如果數(shù)據(jù)沒(méi)有被讀取,它會(huì)消耗內(nèi)存,最后導(dǎo)致'process out of memory'
錯(cuò)誤。
注意:io.js
不會(huì)檢查Content-Length
和被傳輸?shù)捻憫?yīng)體長(zhǎng)度是否相同。
這個(gè)請(qǐng)求實(shí)現(xiàn)了Writable
流接口。這是一個(gè)包含了以下事件的EventEmitter
:
當(dāng)這個(gè)請(qǐng)求收到一個(gè)響應(yīng)時(shí)觸發(fā)。這個(gè)事件只會(huì)被觸發(fā)一次。response
參數(shù)是一個(gè)http.IncomingMessage
實(shí)例。
Options:
socket
(使用host:port
或socketPath
中的一個(gè))當(dāng)一個(gè)socket
被分配給一個(gè)請(qǐng)求時(shí)觸發(fā)。
每次服務(wù)器使用CONNECT
方法響應(yīng)一個(gè)請(qǐng)求時(shí)觸發(fā)。如果這個(gè)事件沒(méi)有被監(jiān)聽(tīng),那么接受CONNECT
方法的客戶(hù)端將會(huì)關(guān)閉它們的連接。
以下是一對(duì)客戶(hù)端/服務(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: io.js-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();
});
});
});
Emitted each time a server responds to a request with an upgrade. If this event isn't being listened for, clients receiving an upgrade header will have their connections closed.每次服務(wù)器返回upgrade
響應(yīng)給請(qǐng)求時(shí)觸發(fā)。如果這個(gè)事件沒(méi)有被監(jiān)聽(tīng),客戶(hù)端接收一個(gè)upgrade
頭時(shí)會(huì)關(guān)閉它們的連接。
以下是一對(duì)客戶(hù)端/服務(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);
});
});
當(dāng)服務(wù)器發(fā)出一個(gè)'100 Continue'
HTTP響應(yīng)時(shí),通常這是因?yàn)檎?qǐng)求包含'Expect: 100-continue'
。這是一個(gè)客戶(hù)端須要發(fā)送請(qǐng)求體的指示。
當(dāng)請(qǐng)求被客戶(hù)端中止時(shí)觸發(fā)。這個(gè)事件只會(huì)在第一次調(diào)用abort()
時(shí)觸發(fā)。
沖刷請(qǐng)求頭。
由于效率原因,io.js
通常在直到你調(diào)用request.end()
或?qū)懭氲谝粋€(gè)數(shù)據(jù)塊前都會(huì)緩沖請(qǐng)求頭,然后努力將請(qǐng)求頭和數(shù)據(jù)打包為一個(gè)TCP報(bào)文。
這通常是你想要的(它節(jié)約了一個(gè)TCP往返)。但當(dāng)?shù)谝环輸?shù)據(jù)會(huì)等待很久才被發(fā)送時(shí)不是。request.flushHeaders()
使你能繞過(guò)這個(gè)優(yōu)化并且啟動(dòng)請(qǐng)求。
發(fā)送一個(gè)響應(yīng)塊。當(dāng)用戶(hù)想要將請(qǐng)求體流式得發(fā)送給服務(wù)器時(shí),可以通過(guò)調(diào)用這個(gè)方法多次來(lái)辦到--在這種情況下,建議在創(chuàng)建請(qǐng)求時(shí)使用['Transfer-Encoding', 'chunked']
頭。
chunk
參數(shù)必須是一個(gè)Buffer
或一個(gè)字符串。
encoding
參數(shù)是可選的,并且僅當(dāng)chunk
是字符串時(shí)有效。默認(rèn)為'utf8'
。
callback
參數(shù)是可選的,并且當(dāng)數(shù)據(jù)塊被沖刷時(shí)被調(diào)用。
結(jié)束發(fā)送請(qǐng)求。如果有任何部分的請(qǐng)求體未被發(fā)送,這個(gè)函數(shù)將會(huì)將它們沖刷至流中。如果請(qǐng)求是成塊的,它會(huì)發(fā)送終結(jié)符'0\r\n\r\n'
。
如果data
被指定,那么這與調(diào)用request.write(data, encoding)
后再調(diào)用request.end(callback)
相同。
如果callback
被指定,那么它將在請(qǐng)求流結(jié)束時(shí)被調(diào)用。
中止請(qǐng)求。
一旦一個(gè)socket
被分配給這個(gè)請(qǐng)求并且完成連接,socket.setTimeout()
會(huì)被調(diào)用。
返回request
對(duì)象。
一旦一個(gè)socket
被分配給這個(gè)請(qǐng)求并且完成連接,socket.setNoDelay()
會(huì)被調(diào)用。
一旦一個(gè)socket
被分配給這個(gè)請(qǐng)求并且完成連接,socket.setKeepAlive()
會(huì)被調(diào)用。
一個(gè)IncomingMessage
對(duì)象被http.Server
或http.ClientRequest
創(chuàng)建,并且分別被傳遞給request
和response
事件的第一個(gè)參數(shù)。它被用來(lái)取得響應(yīng)狀態(tài),響應(yīng)頭和響應(yīng)體。
它實(shí)現(xiàn)了Readable
流接口,并且有以下額外的事件,方法和屬性。
表明底層連接被關(guān)閉。與end
相同,這個(gè)時(shí)間每次響應(yīng)只會(huì)觸發(fā)一次。
當(dāng)向服務(wù)器發(fā)送請(qǐng)求時(shí),客戶(hù)端發(fā)送的HTTP版本。向客戶(hù)端發(fā)送響應(yīng)時(shí),服務(wù)器響應(yīng)的HTTP版本。通常是'1.1'
或'1.0'
。
另外,response.httpVersionMajor
是第一個(gè)整數(shù),response.httpVersionMinor
是第二個(gè)整數(shù)。
請(qǐng)求/響應(yīng)頭對(duì)象。
只讀的頭名稱(chēng)和值映射。頭名稱(chēng)是小寫(xiě)的,例子:
// 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)的值。
頭名稱(chēng)不是必須小寫(xiě)的,并且重復(fù)也沒(méi)有被合并。
// 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)頭尾部鍵值對(duì)。只在end
事件中存在。
調(diào)用message.connection.setTimeout(msecs, callback)
。
返回message
。
僅對(duì)從http.Server
獲得的請(qǐng)求有效。
請(qǐng)求方法是字符串。只讀。例如:'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。你可以調(diào)用require('url').parse(request.url)
。例子:
iojs> require('url').parse('/status?name=ryan')
{ href: '/status?name=ryan',
search: '?name=ryan',
query: 'name=ryan',
pathname: '/status' }
如果你想從查詢(xún)字符串中提取參數(shù),你可以使用require('querystring').parse
函數(shù),或者給require('url').parse
方法的第二個(gè)參數(shù)傳遞true
,例子:
iojs> require('url').parse('/status?name=ryan', true)
{ href: '/status?name=ryan',
search: '?name=ryan',
query: { name: 'ryan' },
pathname: '/status' }
只對(duì)從http.ClientRequest
到來(lái)的響應(yīng)有效。
3位整數(shù)HTTP狀態(tài)碼。如404
。
只對(duì)從http.ClientRequest
到來(lái)的響應(yīng)有效。
HTTP響應(yīng)狀態(tài)信息。如OK
或Internal Server Error
。
與此連接關(guān)聯(lián)的net.Socket
對(duì)象。
通過(guò)HTTPS的支持,使用request.socket.getPeerCertificate()
來(lái)獲取客戶(hù)端的身份細(xì)節(jié)。
更多建議: