經過require("http")來使用HTTP的客戶端和服務端。html
Node.js中的HTTP接口用於提供對傳統協議中難以使用的特性的支持。 尤爲是那些龐大或者是塊編碼的信息。該接口不會緩衝整個請求或者響應——用戶能夠本身使用流來處理數據。node
HTTP頭信息會被以以下的對象格式來表示:linux
{ 'content-length': '123', 'content-type': 'text/plain', 'connection': 'keep-alive', 'host': 'mysite.com', 'accept': '*/*' }
鍵都是小寫的。值沒有被修改。web
爲了儘量的支持HTTP應用的所有範圍,Node.js的API是很低級的。 它只會處理流和信息的解析。它只是將一個信息解析成HTTP頭或者HTTP體可是不會去解析實際的HTTP頭或HTTP體。api
想了解如何處理重複的http頭的細節請參考message.headers。
數組
原生的http頭被保留在rawHeaders
屬性中,並以[key, value, key2, value2, ...]的數組形式呈現。好比, 以前的信息頭對象就含有一個以下形式的rawHeaders列表:
緩存
[ 'ConTent-Length', '123456', 'content-LENGTH', '123', 'content-type', 'text/plain', 'CONNECTION', 'keep-alive', 'Host', 'mysite.com', 'accepT', '*/*' ]
HTTP代理用於做爲一個HTTP客戶端請求的socket池。服務器
HTTP代理默認對客戶端請求使用keep-alive鏈接。若是一個空閒的socket沒有待定處理的http請求,那麼這個socket會被關閉。這意味着當服務器處於低負荷狀態時開發者不須要去關閉每個使用KeepAlive的鏈接,這是一個好消息。websocket
若是你選擇使用KeepAlive,你能夠將設置一個標識設置爲true來建立一個代理對象(詳細信息參考constructor options)。而後,代理對象會在池中保存空閒的socket用於之後來使用。他們會被打上明確的標記因此Node.js的進程不會一直處於運行狀態。不管如何,當不須要再使用KeepAlive代理時用destroy()來取消它不失爲一個好主意,那樣全部的sockets也會被關閉。
網絡
當socket發生一個'close'事件或者一個特殊的'agentRemove'事件時socket會被從代理池中移除。這意味着若是你試圖去維持一個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 })
options對象用於配置agent
. 能夠設置如下幾個屬性:
keepAlive
布爾型,在池中保持sockets能夠在以後給其餘請求使用。默認值是false
keepAliveMsecs
整型,當使用HTTP KeepAlive,TCP KeepAlive包要發送多久socket就會保持鏈接多久,默認是1000. 只有當keepalive爲true的時候纔會起做用。maxSockets
number型,每一個主機可以接受的最大的sockets數量,默認是infinity。maxFreeSockets
number型,處於空閒狀態的socket的最大值。只有當keepAlive設置爲true纔會起做用。默認值是256。當這些屬性被設置爲各自的默認值並被http.request()使用時,默認的
http.globalAgent
纔會被使用。
若是想配置其中的任何一個值,你必須建立一個本身的http.Agent
對象。
var http = require('http'); var keepAliveAgent = new http.Agent({ keepAlive: true }); options.agent = keepAliveAgent; http.request(options, onResponseCallback);
銷燬任何一個正在被agent使用的sockets。
一般狀況下並不須要這麼作。無論怎麼說,若是你正在使用開啓了keepAlive的agent,最好明確的關閉一個即將不被使用的agent。除此之外,sockets會維持一段時間直到服務器關閉他們。
當使用HTTP KeepAlive時,agent.freeSockets對象會包含一個當前空閒的sockets數組。不要修改它。
經過對request選項的進行設置來獲取一個獨一無二的名字,用於確認一個鏈接是否能夠重複使用 。在http代理中,他會返回host:port:localAddress
. 在https代理中,這個獨一無二的名稱中將會包含CA,cert,ciphers以及其餘HTTPS/TLS-specific選項用於決定一個socket是否能夠重複使用。
默認值是256.對於支持HTTP KeepAlive的代理,這個屬性設置了處於空閒狀態的sockets的最大數量。
默認值是Infinity,用於決定一個一個代理能夠設置最多多少個併發的sockets。
一個包含了尚未分配sockets的請求隊列的對象,不要修改他。
一個包含了代理中正在使用的sockets的數組的對象。不要修改他。
這個對象是在內部建立而後被 http.request()返回的。它表明了一個正在處理的請求,該請求的頭部已經進入請求隊列中。經過使用
setHeader(name,value)
, getHeader(name)
, removeHeader(name)
仍然能夠改變該頭部。實際的頭部會隨着第一個數據塊一塊兒發送或者當鏈接結束時發送。
爲了獲得響應對象,應該給request對象添加一個監聽器用於監聽response。當響應頭被接收到時,request對象會發送一個'response'。'response'事件會被執行,在執行時會使用一個http.IncomingMessage的實例做爲參數。
在'response'事件期間,能夠爲reponse對象添加監聽器;特別是監聽'data'事件。
若是沒有添加'response'處理函數,那麼這個相應對象會被直接丟棄
. 無論怎麼說,若是你給 'response'事件添加了處理函數,那麼你必須接收從response對象傳遞過來的數據
,要麼對
'readable'事件使用response.read()處理
,或是添加一個 'data'
事件的處理函數, 也可使用 .resume()
方法。只有在數據被接收完畢以後, 'end'
事件纔會被觸發。一樣的,只要數據沒有被讀取,那麼將持續消耗內存直到產生一個'進程耗盡內存'的錯誤。
注意:Node.js不會去確認Content-Length以及被髮送的body的長度是否相等。
該請求實現了Writable Stream接口。這是一個 包含了下列事件的EventEmitter:
function () { }
當請求被客戶端打斷時觸發。該事件只會在第一次調用 abort()時觸發。
function (response, socket, head) { }
當服務器經過CONNECT方法響應一個請求時觸發。若是該事件沒有被監聽,接受
CONNECT
方法的客戶端將關閉鏈接。
下面這對客戶端和服務端的交互將向你展現如何監聽'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.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(); }); }); });
function () { }
當服務器回送'100 Continue'時觸發該事件,一般狀況是由於請求中包含了'Expected:100-continue'。這是一個讓客戶端發送請求體的指令。
function (response) { }
當請求接收到響應時觸發該事件。該事件只會觸發一次。這個response參數
是http.IncomingMessage的一個實例。
可選項:
host
: 請求要發送到的服務器的域名或者IP地址。port
: 遠程服務器的端口號。socketPath
: Unix域名套接字(使用host:post或者socketPath)。function (socket) { }
當一個socket被分配給一個request時觸發該事件。
function (response, socket, head) { }
每當服務器向request返回一個upgrade時觸發該事件。若是沒有監聽該事件,客戶端會收到一個upgrade頭並關閉鏈接。
一組客戶端和服務器端交互的例子將向你展現如何監聽'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); }); });
將request標記爲停止。使用該方法會將數據保留在被停止的response中並將socket移除。
完成request的發送。若是請求體中仍有部分未被髮送,那麼會這一部分flush到stream中。若是request被分塊發送,那麼該方法會發送一個終結符號 '0\r\n\r\n'。
那麼該方法至關於調用以後緊接着調用
若是指定了data,
那麼該方法至關於先調用response.write(data, encoding)
以後再調用request.end(callback)。
若是指定了callback,那麼這個回調函數會在request流結束時被調用。
flush請求頭。
處於效率的考慮,Node.js通常會將請求頭緩存直到你調用request.end()或者請求數據的第一個數據塊被寫出。以後它會盡可能將請求頭和數據打包在一個TCP數據包中。
一般來講,你是很但願在TCP往返的過程當中請求頭都會被保留,除非第一個數據過了好久才發送。request.flushHeaders()讓你能夠忽視最優化並啓動請求(可能不太準確,建議參照原文)。
一旦一個socket被分配給這個request而且鏈接成功,socket.setNoDelay()就會被調用。
一旦一個socket被分配給這個request並鏈接成功,socket.setKeepAlive()就會被調用。
一旦一個socket被分配給這個request並鏈接成功,socket.setTimeout()
就會被調用。
發送請求體的一個數據塊。經過屢次調用該方法,使用者能夠以流的形式將請求體發送給服務器--這種狀況下建議在建立請求時使用['Transfer-Encoding', 'chunked']
做爲頭部。
chunk參數必須是一個buffer類型或者string類型。
encoding參數是可選的,只有在chunk是字符串類型是才能使用。默認值是'utf8'。
callback參數是可選的,當數據塊被flushed時,該回調函數會被調用。
request.write()方法返回一個request對象。
這是一個包含了下列事件的EventEmitter:
function (request, response) { }
每當收到一個Expect:100-continues時觸發該事件。若是沒有監聽該事件,那麼服務器會在合適的時機自動的響應一個100 Continue。
處理該事件時,若是客戶端能夠繼續發送請求體,那麼須要調用response.writeContinue(),
若是客戶端不能繼續發送請求體,則生成一個合適的HTTP響應(好比,400 Bad Request)。
請注意,當該事件被觸發和處理時,'request'事件將不會被觸發。
function (exception, socket) { }
若是客戶端鏈接時觸發了一個事件,將會被轉發到這裏。
socket
是最初發生錯誤的的一個net.Socket
對象。
function () { }
當服務器關閉時觸發該事件。
function (request, socket, head) { }
當客戶端請求爲CONNECT方法時觸發該事件。
若是沒有監聽該事件,那麼當客戶端發起CONNECT
請求時,鏈接會被關閉。
request
是一個http的請求參數,和request事件中是相同的。socket
是介於服務器和客戶端之間的網絡socket。head
是一個Buffer實例,是隧道流的第一個包,多是個空包。該事件觸發後。請求的socket將不會監聽'data'事件,這意味着你須要手動去綁定一個處理從socket傳遞給服務器的數據的監聽器。
function (socket) { }
當一個新的TCP流創建後觸發。socket是
net.Socket類型的一個對象。
通常來講用戶並不須要去接觸這個事件。特別注意的是,協議分析器綁定到socket的方式會致使socket沒法觸發'readable'事件。
該socket
在 request.connection中也能夠訪問到。
function (request, response) { }
每當產生一個請求時觸發。請注意每一個鏈接可能存在多個請求(好比keep-alive鏈接)。request
是http.IncomingMessage的實例,
response
是http.ServerResponse的實例。
function (request, socket, head) { }
當客戶端發送一個upgrade的http請求時觸發。若是沒有監聽該事件,那麼當客戶端發起upgrade請求時會斷開鏈接。
request
是表示http請求的參數,和request事件中相同。socket
是介於服務器和客戶端的網絡socket。head
是一個Buffer的實例,是upgrade流的第一個數據包,有多是個空包。在該事件觸發後,請求的socket將不在監聽data事件,這意味着你須要手動綁定一個處理該socket發給服務器的數據的監聽器。
中止服務器接收新的鏈接。詳情請參考net.Server.close()。
handle
Object類型callback
Function類型
The handle
對象能夠被設置成一個服務器或一個socket(任何一個含有下劃線的成員_handle),又或者是一個{fd: <n>}
對象。
該方法使服務器用特殊的句柄來接收鏈接,可是它假設文件描述符或者處理器已經被綁定給一個端口或domain socket。
Windows環境下不支持監聽一個文件描述符。
該方法是異步的。最後一個參數 callback
將被做爲 'listening'事件的監聽器。
能夠參考 net.Server.listen()。
開啓一個UNIX socket服務器用於監聽對給定 path 的鏈接。
該函數是異步的。最後一個 callback
參數會被做爲 'listening'
事件的監聽器。能夠參考 net.Server.listen(path)。
在特定的端口和主機名接收鏈接。若是省略了主機名,服務器會在任何一個可使用的IPv6地址或一個IPv4地址接受鏈接。若是將端口設置爲0那麼將會隨機分配一個端口。
若是用於監聽一個unix socket,那麼須要提供一個文件名來代替端口和主機名。
backlog是指待處理鏈接隊列的最大長度。實際長度經過操做系統的sysctl設置(好比linux下設置tcp_max_syn_backlog和
)來決定。這個參數的默認值是511(而不是512)。somaxconn
該方法是異步的。最後一個callback參數會做爲
'listening'
事件的監聽器。能夠參考 net.Server.listen(port)。
最大的請求頭數量限制,默認設置爲1000。若是設置成0則表明不作限制。
msecs
Number類型callback
Function類型設置socket的超時時間。若是出現超時,則在Server對象上觸發一個'timeout'
事件,則將socket做爲一個參數傳遞。
若是在Server對象上監聽了 'timeout'
事件,那麼當一個超時的socket被做爲參數時會調用該監聽器。
默認的,Server的超時時間被設置成2分鐘,若是超時那麼socket會自動銷燬。無論怎麼說,若是你給Server的事件分配了一個回調函數,那麼你將負責去處理過時的socket。
返回一個server對象。
一個socket被判斷爲超時以前的閒置毫秒數。
請注意socket的超時邏輯上說是設置在鏈接上的,因此改變這個值只會影響新鏈接而不會影響已存在的鏈接。
設置爲0用於禁止鏈接的任意自動超時行爲。
該對象由HTTP server內部建立--而不是被用戶建立。他被做爲第二個參數傳遞給 'request'
事件。
response實現了 Writable Stream 接口。 這是一個包含下列事件的 EventEmitter
:
function () { }
要指出底層鏈接會在調用 response.end()
以前或被flush以前被終結。
function () { }
當response被髮送時觸發該事件。更加須要注意的是,該事件被觸發當response頭和體的最後一個部分More specifically, this event is emitted when the last segment of the response headers and body have been handed off to the operating system for transmission over the network. It does not imply that the client has received anything yet.
After this event, no more events will be emitted on the response object.