稳定性: 3 - 稳定
如果要在node.js中使用http服务器或客户端功能,则必须调用require('http')
。
node里的http接口支持协议里原本比较难用的特性。特别是很大的或块编码的消息。这些接口不会完全缓存整个请求或响应,这样用户可以在请求或响应中使用数据流。
http消息头对象和下面的例子类似:
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }
keys都是小写,值不能修改。
为了能支持尽可能多的http应用程序,node提供的http api接口都是底层的。仅能处理流和消息。它把消息解析成报文头和报文体,但是不解析实际的报文头和报文体内容。
定义报文头的时候,多个值间可用,
分隔。除了set-cookie
和cookie
头,因为它们表示值的数组。诸如content-length
的只有一个值的报文头,直接解析,并且只有单值可以表示成已经解析好的对象。
接收到的原始头信息以数组([key, value, key2, value2, ...]
)的形式保存在rawheaders
里。例如,之前提到的消息对象会有如下的rawheaders
:
[ 'content-length', '123456',
'content-length', '123',
'content-type', 'text/plain',
'connection', 'keep-alive',
'host', 'mysite.com',
'accept', '*/*' ]
解析器支持的http方法列表。
全部标准http响应状态码的和描述的集合。例如,http.status_codes[404] === 'not found'
。
返回http.server的新实例。
requestlistener
函数自动加到'request'
事件里。
这个函数已经被抛弃,用http.request()替换。创建一个新的http客户端,连接到服务器的port
和host
。
这是事件分发器eventemitter,有以下事件:
function (request, response) { }
每当有请求的时候触发。注意:每个连接可以有多个请求(在keep-alive连接中)。request
是http.incomingmessage实例,response
是http.serverresponse 的实例。
function (socket) { }
当建立新的tcp流的时候。socket
是一个net.socket
对象。通常用户不会访问这个事件。协议解析器绑定套接字时采用的方式使套接字不会出发readable事件。也能通过request.connection
访问socket
。
function () { }
服务器关闭的时候触发。
function (request, response) { }
当http收到100-continue的http请求时会触发。如果没有监听这个事件,服务器将会自动发送100 continue的响应。
如果客户端需要继续发送请求主题,或者生成合适的http响应(如,400请求无效),可以通过调用response.writecontinue()来处理。
注意:触发并处理这个事件的时候,不会再触发request
事件。
function (request, socket, head) { }
当客户端请求http连接时触发。如果没有监听这个事件,客户端请求连接的时候会被关闭。
request
是http请求的参数,与request事件参数相同。socket
是服务器和客户端间的socket。head
是buffer的实例。网络隧道的第一个包,可能为空。这个事件触发后,请求的socket不会有data
事件监听器,也就是说你需要绑定一个监听器到data
上,来处理在发送到服务器上的socket数据。
function (request, socket, head) { }
当客户端请求http upgrage时候会触发。如果没有监听这个事件,客户端请求一个连接的时候会被关闭。
request
是http请求的参数,与request事件参数相同。socket
是服务器和客户端间的socket。head
是buffer的实例。网络隧道的第一个包,可能为空。这个事件触发后,请求的socket不会有data
事件监听器,也就是说你需要绑定一个监听器到data
上,来处理在发送到服务器上的socket数据。
function (exception, socket) { }
如果一个客户端连接触发了一个'error'事件,它就会转发到这里.
socket
是导致错误的net.socket
对象。
在指定的的端口和主机名上开始接收连接。如果忽略主机名,服务器将会接收指向任意的ipv4地址(inaddr_any
)。
监听一个unix socket,需要提供一个文件名而不是主机名和端口。
积压量backlog为等待连接队列的最大长度。实际的长度由你的操作系统的sysctl设置决定(比如linux上的tcp_max_syn_backlog
和somaxconn
)。默认参数值为 511 (不是512)
这是异步函数。最后一个参数callback
会作为事件监听器添加到listening
事件。参见net.server.listen(port)。
启动一个unix socket服务器所给路径path
这是异步函数。最后一个参数callback
会作为事件监听器添加到listening
事件。参见net.server.listen(port)。
handle
{object}callback
{function}
handle
对象可以是server或socket(任意以下划线_handle
开头的成员),或者{fd: <n>}
对象。
这会导致server用参数handle
接收连接,前提条件是文件描述符或句柄已经连接到端口或域socket。
windows不能监听文件句柄。
这是异步函数。最后一个参数callback
会作为事件监听器添加到listening
事件。参见net.server.listen(port)。
用于禁止server接收连接。参见net.server.close().
最大请求头的数量限制,默认为1000。如果设置为0,则不做任何限制。
msecs
{number}callback
{function}为socket设置超时时间,单位为毫秒,如果发生超时,在server对象上触发'timeout'
事件,参数为socket。
如果在server对象上有一个'timeout'
事件监听器,超时的时候,将会调用它,参数为socket。
默认情况下,server的超时为2分钟,如果超时将会销毁socket。如果你给server的超时事件设置了回调函数,那你就得负责处理socket超时。
超时的时长,单位为毫秒。
注意,socket的超时逻辑在连接时设定,所以有新的连接时才能改变这个值。
设为0时,建立连接的自动超时将失效。
这是一个由http服务器(而不是用户)内部创建的对象。作为第二个参数传递给'request'
事件。
该响应实现了writable stream接口。这是一个包含下列事件的eventemitter :
function () { }
在调用response.end(),或准备flush前,底层连接结束。
function () { }
发送完响应触发。响应头和响应体最后一段数据被剥离给操作系统后,通过网络来传输时被触发。这并不代表客户端已经收到数据。
这个事件之后,响应对象不会再触发任何事件。
发送http/1.1 100 continue消息给客户端,表示请求体可以发送。可以在服务器上查看'checkcontinue'事件。
发送一个响应头给请求。状态码是3位数字,如404
。最后一个参数headers
是响应头。建议第二个参数设置为可以看的懂的消息。
例如:
var body = 'hello world';
response.writehead(200, {
'content-length': body.length,
'content-type': 'text/plain' });
这个方法仅能在消息中调用一次,而且必须在response.end()前调用。
如果你在这之前调用response.write()或response.end(),将会计算出不稳定的头。
content-length是字节数,而不是字符数。上面的例子'hello world'
仅包含一个字节字符。如果body包含高级编码的字符,则buffer.bytelength()
就必须确定指定编码的字符数。node不会检查content-length和body的长度是否相同。
msecs
{number}callback
{function}设置socket超时时间,单位为毫秒。如果提供了回调函数,将会在response对象的'timeout'
事件上添加监听器。
如果没有给请求、响应、服务器添加'timeout'
监视器,超时的时候将会销毁socket。如果你给请求、响应、服务器加了处理函数,就需要负责处理socket超时。
使用默认的headers 时(没有显式的调用response.writehead()),这个属性表示将要发送给客户端状态码。
例如:
response.statuscode = 404;
响应头发送给客户端的后,这个属性表示状态码已经发送。
使用默认headers时(没有显式的调用response.writehead()),这个属性表示将要发送给客户端状态信息。如果这个没有定义,将会使用状态码的标准消息。
例如:
response.statusmessage = 'not found';
当响应头发送给客户端的时候,这个属性表示状态消息已经发送。
设置默认头某个字段内容。如果这个头即将被发送,内容会被替换。如果你想设置更多的头, 就使用一个相同名字的字符串数组。
例如:
response.setheader("content-type", "text/html");
或
response.setheader("set-cookie", ["type=ninja", "language=javascript"]);
boolean(只读)。如果headers发送完毕,则为true,反之为false。
默认值为true。若为true,当headers里没有date值时,自动生成date并发送。
只有在测试环境才能禁用,因为http要求响应包含date头.
读取一个在队列中但是还没有被发送至客户端的header。名字是大小写敏感的。仅能再头被flushed前调用。
例如:
var contenttype = response.getheader('content-type');
从即将发送的队列里移除头。
例如:
response.removeheader("content-encoding");
如果调用了这个方法,且还没有调用response.writehead(),将会切换到默认的header,并更新这个header。
这个方法将发送响应体数据块。可能会多次调用这个方法,以提供body成功的部分内容。
chunk
可以是字符串或 buffer。如果chunk
是字符串,第二个参数表明如何将它编码成字节流。encoding
的默认值是'utf8'
。最后一个参数在刷新这个数据块时调用。
注意:这个是原始的http body,和高级的multi-part body编码无关。
第一次调用response.write()
的时候,将会发送缓存的头信息和第一个body给客户端。第二次,将会调用response.write()
。node认为你将会独立发送流数据。这意味着,响应缓存在第一个数据块中。
如果成功的刷新全部数据到内核缓冲区,返回true
。如果部分或全部数据在用户内存中还处于排队状况,返回false
。当缓存再次释放的时候,将会触发 'drain'
。
这个方法给响应添加http的尾部header(消息末尾的header)。
只有数据块编码用于响应体时,才会触发trailers;如果不是(例如,请求是http/1.0),它们将会被自动丢弃。
如果你想触发trailers, http会要求发送trailer
头,它包含一些信息,比如:
response.writehead(200, { 'content-type': 'text/plain',
'trailer': 'content-md5' });
response.write(filedata);
response.addtrailers({'content-md5': "7895bf4b8828b55ceaf47747b4bca667"});
response.end();
这个方法告诉服务器,所有的响应头和响应体已经发送;服务器可以认为消息结束。response.end()
方法必须在每个响应中调用。
如果指定了参数data
,将会在响应流结束的时候调用。
node维护每个服务器的连接来生成http请求。这个函数让你可以发布请求。
参数options
是对象或字符串。如果options
是字符串,会通过url.parse()自动解析。
options
值:
host
: 请求的服务器域名或 ip 地址,默认:'localhost'
hostname
: 用于支持url.parse()
。hostname
优于host
port
: 远程服务器端口。 默认为:80.localaddress
: 用于绑定网络连接的本地接口socketpath
: unix域socket(使用host:port或socketpath)method
: 指定 http 请求方法。 默认: 'get'
.path
: 请求路径。 默认为:'/'
。如果有查询字符串,则需要包含。例如,'/index.html?page=12'。请求路径包含非法字符时抛出异常。目前,只有空格不行,不过在未来可能改变。headers
: 包含请求头的对象auth
: 用于计算认证头的基本认证,即user:password
agent
: 控制agent的行为。当使用了一个agent的时候,请求将默认为connection: keep-alive
。可能的值为:undefined
(default): 在这个主机和端口上使用global agentagent
object: 在agent
中显式使用passed .false
: 选择性停用连接池,默认请求为:connection: close
.keepalive
: {boolean} 持资源池周围的socket,用于未来其它请求。默认值为false
。keepalivemsecs
: {integer} 使用http keepalive的时候,通过正在保持活动的sockets发送tcp keepalive包的频繁程度。默认值为1000。仅当keepalive为true时才相关。 可选参数callback
将会作为一次性的监视器,添加给 'response' 事件。
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);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(postdata);
req.end();
注意,例子里调用了req.end()
。http.request()
必须调用req.end()
来表明请求已经完成,即使没有数据写入到请求body里。
如果在请求的时候遇到错误(dns解析、tcp级别的错误或实际http解析错误),在返回的请求对象时会触发一个'error'事件。
有一些特殊的头需要注意:
发送connection: keep-alive
告诉服务器保持连接,直到下一个请求到来。
发送content-length
头将会禁用chunked编码。
发送一个expect
头,会立即发送请求头,一般来说,发送expect: 100-continue
,你必须设置超时,并监听continue
事件。更多细节参见rfc2616 section 8.2.3。
auth
参数重写,来计算基本的授权。因为多数请求是没有报文体的get请求,node提供了这个简便的方法。和http.request()
唯一不同点在于,这个方法自动设置get,并自动调用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客户端请求。
http agent也把客户端请求默认为使用connection:keep-alive 。如果没有http请求正在等着成为空闲socket的话,那么socket将关闭。这意味着,node的资源池在负载的情况下对keep-alive有利,但是仍然不需要开发人员使用keepalive来手动关闭http客户端。
如果你选择使用http keepalive, 可以创建一个agent对象,将 flag 设置为true
. (参见下面的constructor options ) ,这样agent会把没用到的socket放到池里,以便将来使用。他们会被显式的标志,让node不运行。但是,当不再使用它的时候,需要显式的调用destroy()
,这样socket将会被关闭。
当socket事件触发close
事件或特殊的agentremove
事件时,socket将会从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
})
options
{object} agent上的设置选项集合,有以下字段内容:keepalive
{boolean} 持资源池周围的socket,用于未来其它请求。默认值为false
。keepalivemsecs
{integer} 使用http keepalive的时候,通过正在保持活动的sockets发送tcp keepalive包的频繁程度。默认值为1000。仅当 keepalive为true时才相关。maxsockets
{number}在空闲状态下,还依然开启的socket的最大值。仅当keepalive
设置为true的时候有效。默认值为256。被http.request
使用的默认的http.globalagent
,会设置全部的值为默认。
必须在创建你自己的agent
对象后,才能配置这些值。
var http = require('http');
var keepaliveagent = new http.agent({ keepalive: true });
options.agent = keepaliveagent;
http.request(options, onresponsecallback);
默认值为infinity。决定了每台主机上的agent可以拥有的并发socket的打开数量,主机可以是host:port
或host:port:localaddress
。
默认值256.对于支持http keepalive的agent而言,这个方法设置了空闲状态下仍然打开的套接字数的最大值。
这个对象包含了当前agent使用中的socket数组。不要修改它。
使用http keepalive的时候,这个对象包含等待当前agent使用的socket数组。不要修改它。
这个对象包含了还没分配给socket的请求数组。不要修改它。
销毁任意一个被agent使用的socket。
通常情况下不要这么做。如果你正在使用一个允许keepalive的agent,当你知道不在使用它的时候,最好关闭agent。否则,socket会一直保存打开状态,直到服务器关闭。
获取一组请求选项的唯一名,来确定某个连接是否可重用。在http agent里,它会返回host:port:localaddress
。在http agent里, name包括ca,cert, ciphers, 和其他https/tls特殊选项来决定socket是否可以重用。
agent的全局实例,是http客户端的默认请求。
该对象在内部创建并从http.request()
返回。他是正在处理的请求,其头部已经在队列中。使用setheader(name, value)
,getheader(name)
, removeheader(name)
api可以改变header。当关闭连接的时候,header将会和第一个数据块一起发送。
为了获取响应,可以给请求对象的'response'
添加监听器。当接收到响应头的时候将会从请求对象里触发'response'
。'response'
事件执行时有一个参数,该参数为http.incomingmessage的实例。
在'response'
事件期间,可以给响应对象添加监视器,监听'data'
事件。
如果没有添加'response'
处理函数,响应将被完全忽略。如果你添加了'response'
事件处理函数,那你必须消费掉从响应对象获取的数据,可以在 'readable'
事件里调用response.read()
,或者添加一个'data'
处理函数,或者调用.resume()
方法。如果未读取数据,它将会消耗内存,最终产生 process out of memory
错误。
node不会检查content-length和body的长度是否相同。
该请求实现了writable stream接口。这是一个包含下列事件的eventemitter。
function (response) { }
当接收到请求的时候会触发,仅会触发一次。response
的参数是http.incomingmessage的实例。
options:
host
: 要请求的服务器域名或ip地址port
: 远程服务器的端口socketpath
: unix域socket (使用host:port或socketpath之一)function (socket) { }
socket附加到这个请求的时候触发。
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-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) { }
每当服务器响应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);
});
});
function () { }
当服务器发送'100 continue' http响应的时候触发,通常因为请求包含'expect: 100-continue'。该指令表示客户端应发送请求体。
刷新请求的头。
考虑效率因素,node.js通常会缓存请求的头直到你调用request.end()
,或写入请求的第一个数据块。然后,包装请求的头和数据到一个独立的tcp包里。
发送一个请求体的数据块。通过多次调用这个函数,用户能流式的发送请求给服务器,这种情况下,建议使用['transfer-encoding', 'chunked']
头。
chunk
参数必须是buffer或字符串。
回调参数可选,当这个数据块被刷新的时候会被调用。
发送请求完毕。如果body的数据没被发送,将会将他们刷新到流里。如果请求是分块的,该方法会发送终结符0\r\n\r\n 。
如果指定了data
,等同于先调用request.write(data, encoding)
,再调用request.end(callback)
。
如果有callback
,将会在请求流结束的时候调用。
终止一个请求. (v0.3.8开始新加入)。
如果socket被分配给这个请求,并完成连接,将会调用socket.settimeout() 。
如果socket被分配给这个请求,并完成连接,将会调用socket.setnodelay()。
如果socket被分配给这个请求,并完成连接,将会调用socket.setkeepalive()。
http.server或http.clientrequest创建了incomingmessage
对象,作为第一个参数传递给'response'
。它可以用来访问应答的状态,头文件和数据。
它实现了readable stream接口,以及以下额外的事件,方法和属性。
function () { }
表示底层连接已经关闭。和'end'
类似,这个事件每个应答只会发送一次。
客户端向服务器发送请求时,客户端发送的 http 版本;或者服务器想客户端返回应答时,服务器的http版本。通常是'1.1'
或'1.0'
。
另外,response.httpversionmajor
是第一个整数,response.httpversionminor
是第二个整数。
请求/响应头对象。
只读的头名称和值的映射。头的名字是小写,比如:
// prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*/*' }
console.log(request.headers);
接收到的请求/响应头字段列表。
注意,键和值在同一个列表中。它并非一个元组列表。所以,偶数偏移量为键,奇数偏移量为对应的值。
头名字不是小写敏感,也没用合并重复的头。
// 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);
请求/响应的尾部对象。只在'end'事件中存在。
接收到的原始的请求/响应尾部键和值。仅在'end'事件中存在。
msecs
{number}callback
{function}调用message.connection.settimeout(msecs, callback)
.
仅对从http.server获得的请求有效。
请求方法如果一个只读的字符串。例如:'get'
,'delete'
.
仅对从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分解,可以用require('url').parse(request.url)
,例如:
node> require('url').parse('/status?name=ryan')
{ href: '/status?name=ryan',
search: '?name=ryan',
query: 'name=ryan',
pathname: '/status' }
如果想从查询字符串中解析出参数,可以用require('querystring').parse
函数,或者将true
作为第二个参数传递给require('url').parse
。 例如:
node> require('url').parse('/status?name=ryan', true)
{ href: '/status?name=ryan',
search: '?name=ryan',
query: { name: 'ryan' },
pathname: '/status' }
仅对从http.clientrequest
获取的响应有效。
3位数的http响应状态码404
。
仅对从http.clientrequest
获取的响应有效。
http的响应消息。比如,ok
或internal server error
.
和连接相关联的net.socket
对象。
通过https支持,使用request.connection.verifypeer()
和request.connection.getpeercertificate()
获取客户端的身份信息。