IO.js HTTP

2018-11-28 22:34 更新

穩(wěn)定度: 2 - 穩(wěn)定

你必須通過require('http')來使用HTTP服務(wù)器和客戶端。

io.js中的HTTP接口被設(shè)置來支持許多HTTP協(xié)議里原本用起來很困難的特性。特別是大且成塊的有編碼的消息。這個接口從不緩沖整個請求或響應(yīng)。用戶可以對它們使用流。

HTTP消息頭可能是一個類似于以下例子的對象:

{ 'content-length': '123',
  'content-type': 'text/plain',
  'connection': 'keep-alive',
  'host': 'mysite.com',
  'accept': '*/*' }

鍵是小寫的。值沒有被修改。

為了全方位的支持所有的HTTP應(yīng)用。io.js的HTTP API是非常底層的。它只處理流以及解釋消息。它將消息解釋為消息頭和消息體,但是不解釋實際的消息頭和消息體。

被定義的消息頭允許以多個,字符分割,除了set-cookiecookie頭,因為它們表示值得數(shù)組。如content-length這樣只有單個值的頭被直接將解析,并且成為解析后對象的一個單值。

收到的原始消息頭會被保留在rawHeaders屬性中,它是一個形式如[key, value, key2, value2, ...]的數(shù)組。例如,之前的消息頭可以有如下的rawHeaders

[ 'ConTent-Length', '123456',
  'content-LENGTH', '123',
  'content-type', 'text/plain',
  'CONNECTION', 'keep-alive',
  'Host', 'mysite.com',
  'accepT', '*/*' ]

http.METHODS

  • Array

一個被解析器所支持的HTTP方法的列表。

http.STATUS_CODES

  • Object

一個所有標(biāo)準(zhǔn)HTTP響應(yīng)狀態(tài)碼的集合,以及它們的簡短描述。例如,http.STATUS_CODES[404] === 'Not Found'。

http.createServer([requestListener])

  • 返回一個新的http.Server實例

requestListener是一個會被自動添加為request事件監(jiān)聽器的函數(shù)。

http.createClient([port][, host])

這個函數(shù)已經(jīng)被啟用。請使用http.request()替代。構(gòu)造一個新的HTTP客戶端。porthost指定了需要連接的目標(biāo)服務(wù)器。

Class: http.Server

這是一個具有以下事件的EventEmitter

Event: 'request'

  • function (request, response) { }

當(dāng)有請求來到時觸發(fā)。注意每一個連接可能有多個請求(在長連接的情況下)。請求是一個http.IncomingMessage實例,響應(yīng)是一個http.ServerResponse實例。

Event: 'connection'

  • function (socket) { }

當(dāng)一個新的TCP流建立時觸發(fā)。socket是一個net.Socket類型的實例。用戶通常不會接觸這個事件。特別的,因為協(xié)議解釋器綁定它的方式,socket將不會觸發(fā)readable事件。這個socket可以由request.connection得到。

Event: 'close'

  • function () { }

當(dāng)服務(wù)器關(guān)閉時觸發(fā)。

Event: 'checkContinue'

  • function (request, response) { }

當(dāng)每次收到一個HTTPExpect: 100-continue請求時觸發(fā)。如果不監(jiān)聽這個事件,那么服務(wù)器會酌情自動響應(yīng)一個100 Continue。

處理該事件時,如果客戶端可以繼續(xù)發(fā)送請求主體則調(diào)用response.writeContinue(), 如果不能則生成合適的HTTP響應(yīng)(如400 Bad Request)。

注意,當(dāng)這個事件被觸發(fā)并且被處理,request事件則不會再觸發(fā)。

Event: 'connect'

  • function (request, socket, head) { }

每當(dāng)客戶端發(fā)起一個httpCONNECT請求時觸發(fā)。如果這個事件沒有被監(jiān)聽,那么客戶端發(fā)起httpCONNECT的連接會被關(guān)閉。

  • request是一個http請求參數(shù),它也被包含在request事件中。
  • socket是一個服務(wù)器和客戶端間的網(wǎng)絡(luò)套接字。
  • head是一個Buffer實例,隧道流中的第一個報文,該參數(shù)可能為空

在這個事件被觸發(fā)后,請求的socket將不會有data事件的監(jiān)聽器,意味著你將要綁定一個data事件的監(jiān)聽器來處理這個socket中發(fā)往服務(wù)器的數(shù)據(jù)。

Event: 'upgrade'

  • function (request, socket, head) { }

每當(dāng)客戶端發(fā)起一個httpupgrade請求時觸發(fā)。如果這個事件沒有被監(jiān)聽,那么客戶端發(fā)起upgrade的連接會被關(guān)閉。

  • request是一個http請求參數(shù),它也被包含在request事件中。
  • socket是一個服務(wù)器和客戶端間的網(wǎng)絡(luò)套接字。
  • head是一個Buffer實例,升級后流中的第一個報文,該參數(shù)可能為空

在這個事件被觸發(fā)后,請求的socket將不會有data事件的監(jiān)聽器,意味著你將要綁定一個data事件的監(jiān)聽器來處理這個socket中發(fā)往服務(wù)器的數(shù)據(jù)。

Event: 'clientError'

  • function (exception, socket) { }

如果一個客戶端連接發(fā)生了錯誤,這個事件將會被觸發(fā)。

socket是一個錯誤來源的net.Socket對象。

server.listen(port[, hostname][, backlog][, callback])

從指定的端口和主機名開始接收連接。如果hostname被忽略,那么如果IPv6可用,服務(wù)器將接受任意IPv6地址(::),否則為任何IPv4地址(0.0.0.)。port0將會設(shè)置一個隨機端口。

如果要監(jiān)聽一個unix socket,請?zhí)峁┮粋€文件名而不是端口和主機名。

backlog是連接等待隊列的最大長度。它的實際長度將有你操作系統(tǒng)的sysctl設(shè)置(如linux中的tcp_max_syn_backlogsomaxconn)決定。默認(rèn)值為511(不是512)。

這個函數(shù)式異步的。最后一個callback參數(shù)將會添加至listening事件的監(jiān)聽器。參閱net.Server.listen(port)。

server.listen(path[, callback])

通過給定的path,開啟一個監(jiān)聽連接的 UNIX socket服務(wù)器。

這個函數(shù)式異步的。最后一個callback參數(shù)將會添加至listening事件的監(jiān)聽器。參閱net.Server.listen(path)

server.listen(handle[, callback])

  • handle Object
  • callback Function

handle對象是既可以是一個server可以是一個socket(或者任意以下劃線開頭的成員_handle),或一個{fd: <n>}對象。

這將使得服務(wù)器使用指定句柄接受連接,但它假設(shè)文件描述符或句柄已經(jīng)被綁定至指定的端口或域名socket。

在Windows下不支持監(jiān)聽一個文件描述符。

這個函數(shù)式異步的。最后一個callback參數(shù)將會添加至listening事件的監(jiān)聽器。參閱net.Server.listen()。

server.close([callback])

讓服務(wù)器停止接收新的連接。參閱net.Server.close()

server.maxHeadersCount

限制最大請求頭數(shù)量,默認(rèn)為1000。如果設(shè)置為0,則代表無限制。

server.setTimeout(msecs, callback)

  • msecs Number
  • callback Function

設(shè)置socket的超時值,并且如果超時,會在服務(wù)器對象上觸發(fā)一個timeout事件,并且將傳遞socket作為參數(shù)。

如果在服務(wù)器對象時又一個timeout事件監(jiān)聽器,那么它將會被調(diào)用,而超時的socket將會被作為參數(shù)。

默認(rèn)的,服務(wù)器的超時值是兩分鐘,并且如果超時,socket會被自動銷毀。但是,如果你給timeout事件傳遞了回調(diào)函數(shù),那么你必須為要親自處理socket超時。

返回一個server對象。

server.timeout

  • Number 默認(rèn)為120000(兩分鐘)

一個socket被判定為超時之前的毫秒數(shù)。

注意,socket的超時邏輯在連接時被設(shè)定,所以改變它的值僅影響之后到達(dá)服務(wù)器的連接,而不是所有的連接。

設(shè)置為0將會為連接禁用所有的自動超時行為。

Class: http.ServerResponse

這個對象由HTTP服務(wù)器內(nèi)部創(chuàng)建,而不是由用戶。它會被傳遞給request事件監(jiān)聽器的第二個參數(shù)。

這個對象實現(xiàn)了Writable流接口。它是一個具有以下事件的EventEmitter

Event: 'close'

  • function () { }

表明底層的連接在response.end()被調(diào)用或能夠沖刷前被關(guān)閉。

Event: 'finish'

  • function () { }

當(dāng)響應(yīng)被設(shè)置時觸發(fā)。更明確地說,這個事件在當(dāng)響應(yīng)頭的最后一段和響應(yīng)體為了網(wǎng)絡(luò)傳輸而交給操作系統(tǒng)時觸發(fā)。它并不表明客戶端已經(jīng)收到了任何信息。

這個事件之后,response對象不會再觸發(fā)任何事件。

response.writeContinue()

給客戶端傳遞一個HTTP/1.1 100 Continue信息,表明請求體必須被傳遞。參閱服務(wù)器的checkContinue事件。

response.writeHead(statusCode[, statusMessage][, headers])

為請求設(shè)置一個響應(yīng)頭。statusCode是一個三位的HTTP狀態(tài)碼,如404。最后一個參數(shù)headers,是響應(yīng)頭。第二個參數(shù)statusMessage是可選的,表示狀態(tài)碼的一個可讀信息。

例子:

var body = 'hello world';
response.writeHead(200, {
  'Content-Length': body.length,
  'Content-Type': 'text/plain' });

這個方法對于一個信息只能調(diào)用一次,并且它必須在response.end()之前被調(diào)用。

如果你在調(diào)用這個方法前調(diào)用了response.write()response.end(),將會調(diào)用這個函數(shù),并且一個implicit/mutable頭會被計算使用。

注意,Content-Length是以字節(jié)計,而不是以字符計。上面例子能正常運行時因為字符串'hello world'僅包含單字節(jié)字符。如果響應(yīng)體包含了多字節(jié)編碼的字符,那么必須通過指定的編碼來調(diào)用Buffer.byteLength()來確定字節(jié)數(shù)。并且io.js不會檢查Content-Length與響應(yīng)體的字節(jié)數(shù)是否相等。

response.setTimeout(msecs, callback)

  • msecs Number
  • callback Function

設(shè)置socket的超時值(毫秒),如果傳遞了回調(diào)函數(shù),那么它將被添加至response對象的timeout事件的監(jiān)聽器。

如果沒有為request,request或服務(wù)器添加timeout監(jiān)聽器。那么socket會在超時時銷毀。如果你為request,request或服務(wù)器添加了timeout監(jiān)聽器,那么你必須為要親自處理socket超時。

返回一個response對象。

response.statusCode

當(dāng)使用隱式響應(yīng)頭(不明確調(diào)用response.writeHead())時,這個屬性控制了發(fā)送給客戶端的狀態(tài)碼,在當(dāng)響應(yīng)頭被沖刷時。

例子:

response.statusCode = 404;

在響應(yīng)頭發(fā)送給客戶端之后,這個屬性表明了被發(fā)送的狀態(tài)碼。

response.statusMessage

當(dāng)使用隱式響應(yīng)頭(不明確調(diào)用response.writeHead())時,這個屬性控制了發(fā)送給客戶端的狀態(tài)信息,在當(dāng)響應(yīng)頭被沖刷時。當(dāng)它沒有被指定(undefined)時,將會使用標(biāo)準(zhǔn)HTTP狀態(tài)碼信息。

例子:

response.statusMessage = 'Not found';

在響應(yīng)頭發(fā)送給客戶端之后,這個屬性表明了被發(fā)送的狀態(tài)信息。

response.setHeader(name, value)

為一個隱式的響應(yīng)頭設(shè)置一個單獨的頭內(nèi)容。如果這個頭已存在,那么將會被覆蓋。當(dāng)你需要發(fā)送一個同名多值的頭內(nèi)容時請使用一個字符串?dāng)?shù)組。

例子:

response.setHeader("Content-Type", "text/html");
//or

response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);

response.headersSent

布爾值(只讀)。如果響應(yīng)頭被發(fā)送則為true,反之為false。

response.sendDate

當(dāng)為true時,當(dāng)響應(yīng)頭中沒有Date值時會被自動設(shè)置。默認(rèn)為true

這個值只會為了測試目的才會被禁用。HTTP協(xié)議要求響應(yīng)頭中有Date值。

response.getHeader(name)

讀取已經(jīng)被排隊但還未發(fā)送給客戶端的響應(yīng)頭。注意name是大小寫敏感的。這個函數(shù)只能在響應(yīng)頭被隱式?jīng)_刷前被調(diào)用。

例子:

var contentType = response.getHeader('content-type');

response.removeHeader(name)

取消一個在隊列中等待隱式發(fā)送的頭。

例子:

response.removeHeader("Content-Encoding");

response.write(chunk[, encoding][, callback])

如果這個方法被調(diào)用并且response.writeHead()沒有備調(diào)用,那么它將轉(zhuǎn)換到隱式響應(yīng)頭模式,并且刷新隱式響應(yīng)頭。

這個方法傳遞一個數(shù)據(jù)塊的響應(yīng)體。這個方法可能被調(diào)用多次來保證連續(xù)的提供響應(yīng)體。

數(shù)據(jù)塊可以是一個字符串或一個buffer。如果數(shù)據(jù)塊是一個字符串,那么第二個參數(shù)是它的編碼。默認(rèn)是UTF-8.最后一個回調(diào)函數(shù)參數(shù)會在數(shù)據(jù)塊被沖刷后觸發(fā)。注意:這是一個底層的HTTP報文,高級的多部分報文編碼無法使用。

第一次調(diào)用response.write()時,它會傳遞緩存的頭信息以及第一個報文給客戶端。第二次調(diào)用時,io.js假設(shè)你將發(fā)送數(shù)據(jù)流,然后分別發(fā)送。這意味著響應(yīng)式緩沖到第一個報文的數(shù)據(jù)塊中。

如果整個數(shù)據(jù)都成功得沖刷至內(nèi)核緩沖,則放回true。如果用戶內(nèi)存中有部分或全部的數(shù)據(jù)在隊列中,那么返回false。drain事件將會在緩沖再次釋放時觸發(fā)。

response.addTrailers(headers)

這個方法添加HTTP尾隨頭(一個在消息最后的頭)給響應(yīng)。

只有當(dāng)數(shù)據(jù)編碼被用于響應(yīng)時尾隨才會觸發(fā)。如果不是(如請求是HTTP/1.0),它們將被安靜地丟棄。

注意,如果你要觸發(fā)尾隨消息,HTTP要求傳遞一個包含報文頭場列表的尾隨頭:

response.writeHead(200, { 'Content-Type': 'text/plain',
                          'Trailer': 'Content-MD5' });
response.write(fileData);
response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});
response.end();

response.end([data][, encoding][, callback])

這個方法告知服務(wù)器所有的響應(yīng)頭和響應(yīng)體都已經(jīng)發(fā)送;服務(wù)器會認(rèn)為這個消息完成了。這個方法必須在每次響應(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ā)。

http.request(options[, callback])

io.js為每個服務(wù)器維護(hù)了幾個連接,用來產(chǎn)生HTTP請求。這函數(shù)允許你透明地發(fā)送請求。

options參數(shù)可以是一個對象或一個字符串,如果options是一個字符串,它將自動得被url.parse()翻譯。

Options:

  • host: 一個將要向其發(fā)送請求的服務(wù)器域名或IP地址。默認(rèn)為localhost
  • hostname: host的別名。為了支持url.parse()的話,hostnamehost更好些。
  • family: 解析hosthostname時的IP地址協(xié)議族。合法值是46。當(dāng)沒有指定時,將都被使用。
  • port: 遠(yuǎn)程服務(wù)器端口。默認(rèn)為80。
  • localAddress: 用于綁定網(wǎng)絡(luò)連接的本地端口。
  • socketPath: Unix域socket(使用host:portsocketPath)。
  • method: 指定HTTP請求方法的字符串。默認(rèn)為GET。
  • path: 請求路徑。默認(rèn)為/。如果有查詢字符串,則需要包含。例如'/index.html?page=12'。請求路徑包含非法字符時拋出異常。目前,只否決空格,不過在未來可能改變。
  • headers: 一個包含請求頭的對象。
  • auth: 用于計算認(rèn)證頭的基本認(rèn)證,即'user:password'。
  • agent: 控制agent行為。當(dāng)使用一個代理時,請求將默認(rèn)為Connection: keep-alive??赡苤涤校?/p>

  • undefined (默認(rèn)): 在這個主機和端口上使用全局`agent。
  • Agent object: 在agent中顯示使用passed。
  • false: 跳出agent的連接池。默認(rèn)請求為Connection: close。

可選的回調(diào)函數(shù)將會被添加為response事件的“一次性”監(jiān)聽器(one time listener)。

http.request()返回一個http.ClientRequest類的實例。這個ClientRequest實例是一個可寫流。如果你需要使用POST請求上傳一個文件,那么就將之寫入這個ClientRequest對象。

例子:

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()時必須調(diào)用req.end()來表明你已經(jīng)完成了請求(即使沒有數(shù)據(jù)要被寫入請求體)。

如果有一個錯誤在請求時發(fā)生(如DNS解析,TCP級別錯誤或?qū)嶋H的HTTP解析錯誤),一個error事件將會在返回對象上觸發(fā)。

下面有一些特殊的需要主要的請求頭:

  • 發(fā)送'Connection: keep-alive'會告知io.js保持連直到下一個請求發(fā)送。

  • 發(fā)送'Content-length'頭會禁用默認(rèn)的數(shù)據(jù)塊編碼。

  • 發(fā)送'Expect'頭將會立刻發(fā)送一個請求頭。通常,當(dāng)發(fā)送'Expect: 100-continue'時,你需要同時設(shè)置一個超時和監(jiān)聽后續(xù)的時間。參閱RFC2616的8.2.3章節(jié)來獲取更多信息。

  • 發(fā)送一個授權(quán)頭將會覆蓋使用auth選項來進(jìn)行基本授權(quán)。

http.get(options[, callback])

由于大多數(shù)請求是沒有請求體的GET請求。io.js提供了這個簡便的方法。這個方法和http.request()方法的唯一區(qū)別是它設(shè)置請求方法為GET且自動調(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);
});

Class: http.Agent

HTTP Agent是用來把HTTP客戶端請求中的socket做成池。

HTTP Agent 也把客戶端的請求默認(rèn)為使用Connection:keep-alive。如果沒有HTTP請求正在等待成為空閑的套接字的話,那么套接字將關(guān)閉。這意味著io.js的資源池在負(fù)載的情況下對keep-alive有利,但是仍然不需要開發(fā)人員使用KeepAlive來手動關(guān)閉HTTP客戶端。

如果你選擇使用HTTP KeepAlive,那么你可以創(chuàng)建一個標(biāo)志設(shè)為true的Agent對象(見下面的構(gòu)造函數(shù)選項)。然后,Agent將會在資源池中保持未被使用的套接字,用于未來使用。它們將會被顯式標(biāo)記,以便于不保持io.js進(jìn)程的運行。但是當(dāng)KeepAlive agent沒有被使用時,顯式地destroy() KeepAlive agent仍然是個好主意,這樣socket會被關(guān)閉。

當(dāng)socket觸發(fā)了close事件或者特殊的agentRemove事件的時候,套接字們從agent的資源池中移除。這意味著如果你打算保持一個HTTP請求長時間開啟,并且不希望它保持在資源池中,那么你可以按照下列幾行的代碼做事:

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
})

new Agent([options])#

options Object 為agent設(shè)置可配置的選項??梢杂幸韵聦傩?/strong>:

  • keepAlive Boolean 在未來保持池中的socket被其他請求所使用,默認(rèn)為false
  • keepAliveMsecs Integer 當(dāng)使用HTTP KeepAlive時,通過被保持連接的socket發(fā)送TCP KeepAlive 報文的間隔。默認(rèn)為1000。只在KeepAlive被設(shè)置為true時有效
  • maxSockets Number 每個主機允許擁有的socket的最大數(shù)量。默認(rèn)為Infinity
  • maxFreeSockets Number 在空閑狀態(tài)下允許打開的最大socket數(shù)。僅在keepAlivetrue時有效。默認(rèn)為256

http.request使用的默認(rèn)的http.globalAgent包含它們屬性的各自的默認(rèn)值。

為了配置它們中的任何一個,你必須創(chuàng)建你自己的Agent對象。

var http = require('http');
var keepAliveAgent = new http.Agent({ keepAlive: true });
options.agent = keepAliveAgent;
http.request(options, onResponseCallback);

agent.maxSockets

默認(rèn)為Infinity。決定了每個源上可以擁有的并發(fā)的socket的數(shù)量。源為'host:port''host:port:localAddress'結(jié)合體。

agent.maxFreeSockets

默認(rèn)為256。對于支持HTTP KeepAlive的Agent,這設(shè)置了在空閑狀態(tài)下保持打開的最大socket數(shù)量。

agent.sockets

這個對象包含了正在被Agent使用desocket數(shù)組。請不要修改它。

agent.freeSockets

這個對象包含了當(dāng)HTTP KeepAlive被使用時正在等待的socket數(shù)組。請不要修改它。

agent.requests

這個對象包含了還沒有被分配給socket的請求隊列。請不要修改它。

agent.destroy()

銷毀正在被agent使用的所有socket

通常沒有必要這么做。但是,如果你正在使用一個啟用了KeepAlive的agent,那么最好明確地關(guān)閉agent當(dāng)你知道它不會再被使用時。否則,在服務(wù)器關(guān)閉它們前socket可能被閑置。

agent.getName(options)

通過一個請求選項集合來獲取一個獨一無二的名字,來決定一個連接是否可被再使用。在http代理中,這返回host:port:localAddress。在https代理中,name包括了CA,cert,ciphers和HTTPS/TLS-specific配置來決定一個socket是否能被再使用。

http.globalAgent

所有的http客戶端請求使用的默認(rèn)全局Agent實例。

Class: http.ClientRequest

這個對象時被內(nèi)部創(chuàng)建的,并且通過http.request()被返回。它代表了一個正在處理的請求,其頭部已經(jīng)進(jìn)入了隊列。這個頭部仍然可以通過setHeader(name, value),getHeader(name)removeHeader(name)修改。實際的頭部會隨著第一個數(shù)據(jù)塊發(fā)送,或在關(guān)閉連接時發(fā)送。

要獲得響應(yīng)對象,請為response事件添加一個監(jiān)聽器。request對象的response事件將會在收到響應(yīng)頭時觸發(fā)。這個response事件的第一個參數(shù)是一個http.IncomingMessage的實例。

response事件期間,可以給響應(yīng)對象添加監(jiān)聽器;尤其是監(jiān)聽data事件。

如果沒有添加response事件監(jiān)聽器,那么響應(yīng)會被完全忽略。但是,如果你添加了response事件,那么你必須通過調(diào)用response.read(),添加data事件監(jiān)聽器或調(diào)用.resume()方法等等,來從響應(yīng)對象中消耗數(shù)據(jù)。在數(shù)據(jù)被消費之前,end事件不會觸發(fā)。如果數(shù)據(jù)沒有被讀取,它會消耗內(nèi)存,最后導(dǎo)致'process out of memory'錯誤。

注意:io.js不會檢查Content-Length和被傳輸?shù)捻憫?yīng)體長度是否相同。

這個請求實現(xiàn)了Writable流接口。這是一個包含了以下事件的EventEmitter

Event: 'response'

  • function (response) { }

當(dāng)這個請求收到一個響應(yīng)時觸發(fā)。這個事件只會被觸發(fā)一次。response參數(shù)是一個http.IncomingMessage實例。

  • Options:

  • host: 一個向其發(fā)送請求的服務(wù)器的域名或IP地址
  • port: 遠(yuǎn)程服務(wù)器的端口
  • socketPath: Unix域socket(使用host:portsocketPath中的一個)

Event: 'socket'

  • function (socket) { }

當(dāng)一個socket被分配給一個請求時觸發(fā)。

Event: 'connect'

  • function (response, socket, head) { }

每次服務(wù)器使用CONNECT方法響應(yīng)一個請求時觸發(fā)。如果這個事件沒有被監(jiān)聽,那么接受CONNECT方法的客戶端將會關(guān)閉它們的連接。

以下是一對客戶端/服務(wù)器代碼,展示如何監(jiān)聽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();
    });
  });
});

Event: 'upgrade'

  • function (response, socket, head) { }

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)給請求時觸發(fā)。如果這個事件沒有被監(jiān)聽,客戶端接收一個upgrade頭時會關(guān)閉它們的連接。

以下是一對客戶端/服務(wù)器代碼,展示如何監(jiān)聽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);
  });
});

Event: 'continue'

  • function () { }

當(dāng)服務(wù)器發(fā)出一個'100 Continue'HTTP響應(yīng)時,通常這是因為請求包含'Expect: 100-continue'。這是一個客戶端須要發(fā)送請求體的指示。

Event: 'abort'

  • function () { }

當(dāng)請求被客戶端中止時觸發(fā)。這個事件只會在第一次調(diào)用abort()時觸發(fā)。

request.flushHeaders()

沖刷請求頭。

由于效率原因,io.js通常在直到你調(diào)用request.end()或?qū)懭氲谝粋€數(shù)據(jù)塊前都會緩沖請求頭,然后努力將請求頭和數(shù)據(jù)打包為一個TCP報文。

這通常是你想要的(它節(jié)約了一個TCP往返)。但當(dāng)?shù)谝环輸?shù)據(jù)會等待很久才被發(fā)送時不是。request.flushHeaders()使你能繞過這個優(yōu)化并且啟動請求。

request.write(chunk[, encoding][, callback])

發(fā)送一個響應(yīng)塊。當(dāng)用戶想要將請求體流式得發(fā)送給服務(wù)器時,可以通過調(diào)用這個方法多次來辦到--在這種情況下,建議在創(chuàng)建請求時使用['Transfer-Encoding', 'chunked']頭。

chunk參數(shù)必須是一個Buffer或一個字符串。

encoding參數(shù)是可選的,并且僅當(dāng)chunk是字符串時有效。默認(rèn)為'utf8'。

callback參數(shù)是可選的,并且當(dāng)數(shù)據(jù)塊被沖刷時被調(diào)用。

request.end([data][, encoding][, callback])

結(jié)束發(fā)送請求。如果有任何部分的請求體未被發(fā)送,這個函數(shù)將會將它們沖刷至流中。如果請求是成塊的,它會發(fā)送終結(jié)符'0\r\n\r\n'

如果data被指定,那么這與調(diào)用request.write(data, encoding)后再調(diào)用request.end(callback)相同。

如果callback被指定,那么它將在請求流結(jié)束時被調(diào)用。

request.abort()

中止請求。

request.setTimeout(timeout[, callback])

一旦一個socket被分配給這個請求并且完成連接,socket.setTimeout()會被調(diào)用。

返回request對象。

request.setNoDelay([noDelay])

一旦一個socket被分配給這個請求并且完成連接,socket.setNoDelay()會被調(diào)用。

request.setSocketKeepAlive([enable][, initialDelay])

一旦一個socket被分配給這個請求并且完成連接,socket.setKeepAlive()會被調(diào)用。

http.IncomingMessage

一個IncomingMessage對象被http.Serverhttp.ClientRequest創(chuàng)建,并且分別被傳遞給requestresponse事件的第一個參數(shù)。它被用來取得響應(yīng)狀態(tài),響應(yīng)頭和響應(yīng)體。

它實現(xiàn)了Readable流接口,并且有以下額外的事件,方法和屬性。

Event: 'close'

  • function () { }

表明底層連接被關(guān)閉。與end相同,這個時間每次響應(yīng)只會觸發(fā)一次。

message.httpVersion

當(dāng)向服務(wù)器發(fā)送請求時,客戶端發(fā)送的HTTP版本。向客戶端發(fā)送響應(yīng)時,服務(wù)器響應(yīng)的HTTP版本。通常是'1.1''1.0'

另外,response.httpVersionMajor是第一個整數(shù),response.httpVersionMinor是第二個整數(shù)。

message.headers

請求/響應(yīng)頭對象。

只讀的頭名稱和值映射。頭名稱是小寫的,例子:

// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
//   host: '127.0.0.1:8000',
//   accept: '*/*' }
console.log(request.headers);

message.rawHeaders

接受到的原始請求/響應(yīng)頭列表。

注意鍵和值在同一個列表中,它并非一個元組列表。于是,偶數(shù)偏移量為鍵,奇數(shù)偏移量為對應(yīng)的值。

頭名稱不是必須小寫的,并且重復(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);

message.trailers

請求/響應(yīng)尾部對象。只在end事件中存在。

message.rawTrailers

接受到的原始請求/響應(yīng)頭尾部鍵值對。只在end事件中存在。

message.setTimeout(msecs, callback)

  • msecs Number
  • callback Function

調(diào)用message.connection.setTimeout(msecs, callback)。

返回message。

message.method

僅對從http.Server獲得的請求有效。

請求方法是字符串。只讀。例如:'GET','DELETE'。

message.url

僅對從http.Server獲得的請求有效。

請求的URL字符串。這僅僅只包含實際HTTP請求中的URL。如果請求是:

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' }

如果你想從查詢字符串中提取參數(shù),你可以使用require('querystring').parse函數(shù),或者給require('url').parse方法的第二個參數(shù)傳遞true,例子:

iojs> require('url').parse('/status?name=ryan', true)
{ href: '/status?name=ryan',
  search: '?name=ryan',
  query: { name: 'ryan' },
  pathname: '/status' }

message.statusCode

只對從http.ClientRequest到來的響應(yīng)有效。

3位整數(shù)HTTP狀態(tài)碼。如404。

message.statusMessage

只對從http.ClientRequest到來的響應(yīng)有效。

HTTP響應(yīng)狀態(tài)信息。如OKInternal Server Error。

message.socket

與此連接關(guān)聯(lián)的net.Socket對象。

通過HTTPS的支持,使用request.socket.getPeerCertificate()來獲取客戶端的身份細(xì)節(jié)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號