经过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.