- HTTP
- Class: http.Agent
- new Agent([options])
- Class: http.ClientRequest
- 事件:’abort’
- 事件:’checkExpectation’
- 事件:’connect’
- 事件:’continue’
- 事件:’response’
- 事件:’socket’
- 事件:’upgrade’
- request.abort()
- request.end([data][, encoding][, callback])
- request.flushHeaders()
- request.setNoDelay([noDelay])
- request.setSocketKeepAlive([enable][, initialDelay])
- request.setTimeout(timeout[, callback])
- request.write(chunk[, encoding][, callback])
- Class: http.Server
- 事件:’checkContinue’
- 事件:’clientError’
- 事件:’close’
- 事件:’connect’
- 事件:’connection’
- 事件:’request’
- 事件:’upgrade’
- server.close([callback])
- server.listen(handle[, callback])
- server.listen(path[, callback])
- server.listen(port[, hostname][, backlog][, callback])
- server.listening
- server.maxHeadersCount
- server.setTimeout(msecs, callback)
- server.timeout
- Class: http.ServerResponse
- 事件:’close’
- 事件:’finish’
- response.addTrailers(headers)
- response.end([data][, encoding][,callback])
- response.finished
- response.getHeader(name)
- response.headerSent
- response.removeHeader(name)
- response.sendDate
- response.setHeader(name, value)
- response.setTimeout(msecs,callback)
- response.statusCode
- response.statusMessage
- response.write(chunk[, encoding][, callback])
- response.writeContinue()
- response.writeHead(statusCode[, statusMessage][, headers])
- Class: http.IncomingMessage
- 事件:’close’
- message.headers
- message.httpVersion
- message.method
- message.rawHeaders
- message.rawTrailers
- message.setTimeout(msecs, callback)
- message.statusCode
- message.statusMessage
- message.socket
- message.trailers
- message.url
- http.METHODS
- http.STATUS_CODES
- http.createClient([port][, host])
- http.createServer([requestListener])
- http.get(options[, callback])
- http.globalAgent
- http.request(options[, callback])
HTTP
通过 require('htt')
加载 HTTP 模块可以创建和使用 HTTP 服务器和客户端。
Node.js 中的 HTTP 接口对协议有良好的支持,包括那些传统上比较难处理的特性,比如大规模、块编码信息。这些接口不会缓存完整的请求或响应,从而允许开发者使用数据流。
HTTP 的头信息类似如下所示:
{
'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*'
}
头信息中的键都是小写的,值是不能修改的。
为了支持尽可能多的 HTTP 应用程序,Node.js 的 HTTP API 通常都是比较偏底层的。通常只能处理流和信息。它可以将信息解析成报文头或报文体,但不能直接报文头和报文体。
查看 message.headers 可以了解更多如何处理重复报文头的信息。
接收到的原始报文头会被保存在 rawHeaders
属性中,该属性通常是一个类似 [key, value, key2, value2, ...]
的数组,比如之前提到的头信息对象有可能包含如下所示的 rasHeaders
:
[
'ConTent-Length', '123456',
'content-LENGTH', '123',
'content-type', 'text/plain',
'CONNECTION', 'keep-alive',
'Host', 'mysite.com',
'accepT', '*/*'
]
Class: http.Agent
HTTP Agent 常用于 HTTP 客户端请求的 socket 池中。
HTTP Agent 默认为客户端的请求设置 Connection:keep-alive
。如果 socket 处于空闲状态,则 socket 将会自动被关闭,这也就是说,使用 keep-alive
简化了开发者对 Node.js 请求池的管理。
如果开发者决定使用 HTTP keep-alive
,可以通过
开发者可以通过创建 HTTP Agent 对象时修改初始化属性使用 HTTP keep-alive
,该对象将会复用空闲的 socket。此类对象都会被明确标记,防止它们常驻 Node.js 的进程。不过,通过 destory()
方法显式注销 keep-alive
的对象是一个更好的做法。
当 socket 触发一个 close
或者 agentRemove
事件时,agent 池就会移除该 socket。这也就是说,如果开发者想让 socket 长时间运行,且在运行后自动关闭,那么就可以通过触发这两类事件实现:
http.get(options, (res) => {
// Do stuff
}).on('socket', (socket) => {
socket.emit('agentRemove');
});
此外,也可以通过设置 agent: false
不适用资源池:
http.get({
hostname: 'localhost',
port: 80,
path: '/',
agent: false // create a new agent just for this one request
}, (res) => {
// Do stuff with response
})
new Agent([options])
options
,对象,用于配置 agent 对象的可选参数,该对象拥有以下属性keepAlive
,布尔值,决定允许其他请求复用 socket 池中空闲的 socket,默认值为false
keepAliveMsecs
,数值,当keepAlive
为 true 时,该属性用于决定通过在线的 socket 发送 TCP KeepAlive 的频率,默认值为 1000macSockets
,数值,决定每个主机允许的最大 socket 量,默认值为Infinity
maxFreeSockets
,数值,当keepAlive
为 true 时,该属性决定空闲状态下开启 socket 的最大量,默认值为256
用于 http.request()
的 http.globalAgent()
在默认情况下会对每一个 agent 对象使用默认值。如果要设置其中某个对象的属性,必须创建自定义的 http.Agent
对象:
const http = require('http');
var keepAliveAgent = new http.Agent({ keepAlive: true });
options.agent = keepAliveAgent;
http.request(options, onResponseCallback);
agent.createConnection(optionsp[, callback])
该方法用于创建一个用于 HTTP 请求的 socket 或 stream 实例。
默认情况下,该方法和 [net.createConnection()][]
相同。但是,该方法可以通过修改 Agent 实例的默认配置,进而获得更适合的 Agent 对象。
有两种方式可以获取到 socket 或 stream 实例:一是通过该方法的返回值获取;一是从 callback
的参数获取。
callabck
接收两个参数 (err, stream)
。
agent.destory()
该方法用与注销 Agent 实例所使用的全部 socket。
通产来说开发者无需显式注销 socket。不过,如果是 keep-alive
的 Agent 实例,那么最好由开发者显式注销 socket。因为对于此类 socket,除非服务器终端这些它们,否则它们就会一直存在。
agent.freeSockets
该属性是一个对象,包含了 keep-alive
的 Agent 实例所拥有的空闲 socket。不建议修改该属性。
agent.getName(options)
该方法为一组请求设置一个独一无二的标识符,用于标志一个链接是否可以复用。对于 http agent,该方法返回 hostlocalAddress
;对于 https agent,该方法的返回值会包含 CA、cert、密钥和其他 HTTPS/TLS 所指定的 socket 复用配置项。
agent.maxFreeSockets
该属性的默认值为 256。对于 keep-alive
的 HTTP Agent 实例,该属性用于指定空闲状态下开启 socket 的最大量。
agent.maxSockets
该属性的默认值为 Infinity
,用于指定同一源地址上 Agent 实例所能打开的 socket 的最大并发量。原地址可以是 host:port
或 hostlocalAddress
。
agent.requrests
该属性是一个对象,包含尚未分配给 socket 的请求队列。不建议修改该属性。
agent.sockets
该属性是一个对象,包含 Agent 实例正在使用 socket。不建议修改该属性。
Class: http.ClientRequest
该对象由 http.request()
创建并作为返回值返回到外部。该对象用于表示一个头信息已加入处理队列的请求。虽然头信息已加入请求队列,但仍然可以通过 setHeader(name, value)
、getHeader(name)
和 removeHeader(name)
来修改。当第一次发送数据或关闭连接时,头信息会随数据块一起发送出去。
通过监听 response
事件可以接收相应信息。当请求对象接收到响应头信息之后,就会触发 response
事件。response
事件接收一个参数,该参数是 http.IncomingMessage
的实例。
在 response
事件发生期间,可以给响应对象添加监听器,特别是用于监听 data
事件的监听器。
如果未对 response
事件设置处理函数,则响应信息就会被忽略。不过,如果添加了 response
事件的处理函数,则无论是使用 response.read()
,或者添加 data
事件处理器,还是调用 .resume()
方法,都必须对响应对象的数据进行处理。只有数据经过处理之后,才会触发 end
事件。此外,除非读取数据,否则将会占用不必要的内容,直至触发 process out of memory
错误。
注意,Node.js 不会的对内容和消息体的长度进行比较。
该请求对象实现自 Writable Stream
接口,它是拥有可以触发如下事件 EventEmitter 实例:
事件:’abort’
function () {}
当客户端取消请求时触发该事件,且该方法只在第一次调用 abort()
时触发。
事件:’checkExpectation’
function (request, response) {}
每当接请求对象收到预期的 http 头消息(不包含 Expect:100-continue
)时就会触发该事件。如果没有监听该事件,服务器就会自动发送一个包含 417 预期失败的响应对象。
注意,当该事件被触发并处理之后,request
事件将不会再被触发。
事件:’connect’
function (response, socket, head) { }
每次服务器通过 CONNECT
方法响应请求对象时,都会触发该事件。如果该事件未被监听,接收到 CONNECT
方法的客户端就会关闭连接。
下面代码演示了如何在客户端和服务器端监听 connect
事件:
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
var proxy = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
var srvUrl = url.parse(`http://${req.url}`);
var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
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', () => {
// 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', (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', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
事件:’continue’
function () {}
当请求对象包含 Expect: 100-continue
时,服务器通常会发送一个包含 100 Continue
的 HTTP 响应信息,此时就会触发该事件。该事件的作用是告诉客户端可以发送请求体了。
事件:’response’
function (response) {}
当请求对象接收到响应信息时就会触发该事件,且只触发一次,其中 response
参数是 http.IncomingMessage
的实例。
可选配置项:
host
,请求的服务器域名或 IP 地址port
,远程服务器的端口号socketPath
,Unix 域名 Socket(host:port
或 socketPath)
事件:’socket’
function (socket) {}
当一个 socket 被分配给请求兑现过之后就会触发该事件。
事件:’upgrade’
function (response, socket, head) {}
每次服务器相应一个 upgrade 请求时就会触发该事件。如果为监听该事件,收到 upgrade 头信息的客户端就会关闭连接。
下面代码演示了如何在客户端和服务器端监听 connect
事件:
const http = require('http');
// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', (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', () => {
// 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', (res, socket, upgradeHead) => {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
request.abort()
该方法用于终止请求。调用该方法将会使剩余的相应信息被丢弃且销毁 socket。
request.end([data][, encoding][, callback])
该方法用于结束发送请求,如果调用该方法时消息体的某些部分尚未发送,则这些部分将会被丢弃给 Stream 实例;如果请求是分块发送的,则调用该方法会直接发送终止块 '0\r\n\r\n'
。
如果指定了 data
参数,相当于先调用了 response.write(data, encoding)
,然后调用了 request.end(callback)
。
如果指定了 callback
,则当 request stream 结束时调用该回调函数。
request.flushHeaders()
该方法用于刷新请求头信息。
处于性能方面的原因,Node.js 通常会缓存请求头信息,除非开发者显式调用 request.end()
或写入第一个请求数据块。然后,系统就会将请求头信息和数据打包进一个 TCP 包。
虽然通常这已经满足了开发者的需求(可以节省一次 TCP 握手),但是发送第一块数据的时间可能会有点久。request.flushHeaders()
便于开发者忽略这些优化而发起请求。
request.setNoDelay([noDelay])
当请求对象分配到 socket 并连接之后就会调用 socket.setNoDelay()
方法。
request.setSocketKeepAlive([enable][, initialDelay])
当请求对象分配到 socket 并连接之后就会调用 socket.setKeepAlive()
方法。
request.setTimeout(timeout[, callback])
当请求对象分配到 socket 并连接之后就会调用 socket.setTimeout()
方法。
timeout
,数值,决定请求超时的时间callback
,函数,请求超时后调用的回调函数
request.write(chunk[, encoding][, callback])
该方法用于发送请求体的数据块。多次调用该方法,可以从客户端向服务端发送请求体。对于发送请求体这种任务,建议创建请求对象时配置头信息 ['Transfer-Encoding', 'chunked']
。
chunk
参数可以是一个 Buffer 实例或字符串。
可选参数 encoding
只有当 chunk
为字符串时才可用,默认值为 utf8
。
可选参数 callback
只有当数据被刷新掉时才会触发。
该函数的返回类型为 request 对象。
Class: http.Server
该类继承自 net.Server
,可以触发以下事件:
事件:’checkContinue’
function (request, response) {}
每当接请求对象收到 Expect:100-continue
http 头消息时就会触发该事件。如果没有监听该事件,服务器就会自动发送一个包含 100 Continue 的响应对象。
如果客户端需要继续发送请求体或者生成适当的 HTTP 响应(比如 400,无效请求),则可以通过调用 response.writeContinue()
处理该事件。
注意,当该事件被触发并处理之后,request
事件将不会再被触发。
事件:’clientError’
function (exception, socket) {}
如果客户端在连接过程中触发一个 error
事件,就会被转义到该事件上。
触发错误的 socket
对象是 net.Socket
的实例。
事件:’close’
function () {}
当服务器关闭时触发该事件。
事件:’connect’
function (request, socket, head) {}
每次客户端通过 CONNECT
方法发起请求时,都会触发该事件。如果该事件未被监听,接收到 CONNECT
方法的客户端就会关闭连接。
request
参数是 request 事件中的请求对象socket
是服务器和客户端之间的网络套接字head
是一个 Buffer 实例,隧道 stream 的第一个数据块,值可能为空
触发该事件之后,请求的 socket 将不会给 data
事件绑定监听器,这也就是说开发者需要显式声明 data
事件的监听器,用于处理经 socket 发送给服务器的数据。
事件:’connection’
function (socket) {}
新建 TCP 流时会触发该事件。socket
是一个 net.Socket
的实例。通常开发者并不会使用该事件,但有时候协议解析器绑定 socket 的方式,并不会让 socket 触发 readable
事件。socket
也可以通过 request.connection
方法获得。
事件:’request’
function (request, response) {}
每次接收到请求对象时都会触发该事件。注意,每个链接可能有多个请求对象。request
是 http.IncomingMessage
的实例,response
是 http.ServerResponse
的实例。
事件:’upgrade’
function (request, socket, head) {}
每次客户端请求 http upgrade 时就会触发该事件。如果为监听该事件,收到 upgrade 头信息的客户端就会关闭连接。
request
参数是 request 事件中的请求对象socket
是服务器和客户端之间的网络套接字head
是一个 Buffer 实例,隧道 stream 的第一个数据块,值可能为空
触发该事件之后,请求的 socket 将不会给 data
事件绑定监听器,这也就是说开发者需要显式声明 data
事件的监听器,用于处理经 socket 发送给服务器的数据。
server.close([callback])
该方法用于终止服务器接收新的连接请求。
server.listen(handle[, callback])
handle
,对象callback
,函数
handle
对象可以是一个 server、socket(任意以下划线开头的 _handle
成员) 或 {fd: <n>}
对象。
使用该方法会锁定无法根据指定的 handle
接收连接,并默认为文件描述符或者 handle
已经绑定到了端口和域名 socket 上。
Windows 不支持对文件描述符的监听。
该方法是异步执行的方法,最后一个参数 callback
用于为 listening
时间添加监听器。
该方法的返回值是一个 server
对象。
server.listen(path[, callback])
给方法启动一个 UNIX socket 服务器,根据指定的 path
监听连接请求。
该方法是异步执行的方法,最后一个参数 callback
用于为 listening
时间添加监听器。
server.listen(port[, hostname][, backlog][, callback])
该方法根据指定的 port
和 hostname
接收连接。如果未指定 hostname
,则当 IPv6 可用时,服务器会接受任意的 IPv6 地址,否则就接收任意的 IPv4 地址。如果端口值为 0,则随机分配一个端口号。
如果要监听 UNIX socket,则需要使用文件名,而不是端口或域名。
backlog
参数指定了等待连接队列的最大长度。该参数的实际值由操作系统通过 sysctl 配置项决定,比如 Linux 中的 tcp_max_syn_backlog
和 somaxconn
。该参数的默认值为 511
,而不是 522。
该方法是异步执行的方法,最后一个参数 callback
用于为 listening
时间添加监听器。
server.listening
该属性是一个布尔值,用于标识服务器是否在监听连接请求。
server.maxHeadersCount
该属性限制请求头的最大数量,默认值为 1000。如果值为 0,则表示不限制。
server.setTimeout(msecs, callback)
msecs
,数值callback
,函数
该方法为 socket 设置超时时间,并触发 timeout
事件。如果触发了超时,则参数为 socket。
如果 server 对象监听了 timeout
事件并设置了监听器,那么超时时就会调用该监听器,且参数为超时的 socket。
默认你情况下,服务器的超时事件是两分钟,如果 socket 超时就会别自动销毁。不过,如果开发者为服务器的 timeout
事件设定了自定义的监听器,则由开发者负责销毁 socket。
server.timeout
- 数值,默认值为 120000(两分钟)
该属性指定 socket 处于空闲状态的超时时间。
注意,socket 超时的逻辑在连接时初始化,所以之后该属性的修改只对新创建的连接有效,不会影响现有的 socket。
如果该属性的值为 0,则对连接禁用任何类型的超时处理。
Class: http.ServerResponse
该对象由 HTTP 服务器创建,而不是由开发者创建。它常作为 request
事件的第二个参数。
该响应对象实现自 Writable Stream
接口,它是拥有可以触发如下事件 EventEmitter 实例:
事件:’close’
function () {}
有两种行为会触发该事件:一是在调用 response.end()
之前中断底层连接;一是刷新数据。
事件:’finish’
function () {}
响应信息发送之后会触发该事件。更准确地说,当响应信息的最后一部分被操作系统传输给网络时触发该事件。这并不表示客户端是否收到了数据。
该事件触发之后,响应对象不会再触发其他事件。
response.addTrailers(headers)
该方法用于给 response 对象添加 HTTP trailing header(信息尾部的头信息)。
只有响应对象使用了块编码时,才会触发 Trailer。如果没有使用块编码(比如使用 HTTP/1.0 的 request),则会被毫无声息地抛弃。
注意,如果要触发 Trailer,则 HTTP 需要发送 Trailer
头信息,该头信息包含以下属性和值:
response.writeHead(200, { 'Content-Type': 'text/plain','Trailer': 'Content-MD5' });
response.write(fileData);
response.addTrailers({'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667'});
response.end();
如果修改头信息时使用了无效字符作为键值,则会导致系统抛出 TypeError。
response.end([data][, encoding][,callback])
该方法用于通知服务器所有的额响应信息已经发送完成。每一个响应对象都必须调用该方法。
如果指定了 data
,则相当于先调用了 resposne.write(data, encoding)
,然后调用了 response.end(callback)
。
如果指定了 callback
,那么在响应信息流结束后就会调用该回调函数。
response.finished
该属性是一个布尔值,用于标识响应过程是否结束,默认值为 false
。执行 response.end()
之后,该值变为 true
。
response.getHeader(name)
该方法用于读取已进入队列尚未发送给客户端的头信息。注意,这里的 name
需要注意大小写。该方法只能在头信息刷新之后调用。
var contentType = response.getHeader('content-type');
response.headerSent
该属性是一个只读的布尔值。如果头信息已被发送,则值为 true,否则为 false。
response.removeHeader(name)
该方法从头待发送队列中删除指定的头信息。
response.removeHeader('Content-Encoding');
response.sendDate
当该属性为 true 时,如果头信息没有日期,则会自动在响应信息中生成日期并发送出去,默认值为 true。
建议只在测试时禁用该属性,因为 HTTP 需要知道响应信息的
response.setHeader(name, value)
该方法用于配置头信息。如果该头信息即将被发送,则相应的值会被替换。如果你需要发送多个名字相同的头信息,可以使用字符串数组。
response.setHeader('Content-Type', 'text/html');
// or
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
如果修改头信息时使用了无效字符作为键值,则会导致系统抛出 TypeError。
使用 response.setHeader()
配置头信息之后,这些头信息会被其他头信息合并并传递给 response.writeHead()
,但是传递给 response.writeHead()
的头信息优先级较高。
// returns content-type = text/plain
const server = http.createServer((req,res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
});
response.setTimeout(msecs,callback)
msecs
,数值callback
,函数
该方法为 socket 设置超时时间。如果传入了回调函数,则该回调函数会被视为 timeout
事件的监听器。
如果请求对象、响应对象或服务器监听了 timeout
事件,那么 socket 超时时就会被销毁。如果开发者为服务器、请求对象或响应对象的 timeout
事件设定了自定义的监听器,则由开发者负责销毁 socket。
该方法的返回值是 resposne
对象。
response.statusCode
当使用隐式头信息(没有显式调用 response.writeHead()
的头信息)时,该属性决定了头信息刷新后发送给客户端的状态码。
response.statusCode = 404;
响应头信息发送给客户端之后,该属性表示已发送的状态码。
response.statusMessage
当使用隐式头信息(没有显式调用 response.writeHead()
的头信息)时,该属性决定了头信息刷新后发送给客户端的状态信息。如果该属性的值以 undefined
发送,则会使用标准的状态码的状态信息。
response.statusMessage = 'Not found';
响应头信息发送给客户端之后,该属性表示已发送的状态信息。
response.write(chunk[, encoding][, callback])
如果调用该方法之前没有调用 response.writeHead()
,那么该方法将会切换到隐式头信息模式并刷新隐式头信息。
该方法用于发送一块响应体。该方法可以被多次调用,以保证响应体成功发送出去了。
chunk
可以是一个字符串或 Buffer 实例。如果 chunk
是一个字符串,那么第二个参数则指定了该字符串转化为字节码 stream 的编码格式。encoding
的默认值为 utf8
。数据块刷新时会调用回调函数 callback
。
注意,这是原始的 HTTP body,和 higher-level multi-part body 编码无关。
第一次调用 response.write()
时,将会发送缓存中的头信息和第一块 body 信息给客户端。第二次调用 response.write()
时,Node.js 将会默认独立发送流数据,也就是说,响应信息已经缓存在第一块 body 中了。
如果所有的数据已经成功刷新进了 kenel buffer,那么该方法返回 true
;如果尚有数据存在于内存中,则该方法返回 false
。当 buffer 为空时将会触发 drain
事件。
response.writeContinue()
该方法向客户端发送一个 HTTP1.1 100 Continue 的消息,用于指示应该发送请求体了。
response.writeHead(statusCode[, statusMessage][, headers])
该方法向请求对象发送一个响应头。状态码是一个三位的 HTTP 状态码,比如 404。最后一个参数 headers
是响应头信息。可选参数 statusMessage
是易于辨识状态信息。
var body = 'hello world';
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain' });
每次消息只能调用该方法一次,且必须在 response.end()
之前调用。
如果你在调用 response.write()
和 response.end()
之后调用该方法,那么就会产生隐式或可变的头信息。
使用 response.setHeader()
配置头信息之后,这些头信息会被其他头信息合并并传递给 response.writeHead()
,但是传递给 response.writeHead()
的头信息优先级较高。
// returns content-type = text/plain
const server = http.createServer((req,res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
});
注意,content-length
是字节数而不是字符数。上述代码之所以正常运行,是因为这里的 hello world
只是字节字符。如果 body 包含高级编码字符,就必须使用 Buffer.byteLength()
根据指定的编码格式计算字节数。此外,Node.js 并不会 content 和 body 的长度是否一致。
如果修改头信息时使用了无效字符作为键值,则会导致系统抛出 TypeError。
Class: http.IncomingMessage
IncomingMessage
对象可以由 http.Server
或 http.ClientRequest
创建,并且可以作为 request
和 response
事件监听器的第一个参数。它可以用于访问响应的状态、头信息和数据。
该对象实现了 Readable Stream
接口,具有以下事件、方法和属性:
事件:’close’
function () {}
当底层链接关闭时触发该事件。和 end
事件一样,该事件对于每个响应对象只发生一次。
message.headers
该属性是包含请求或响应头信息的对象。
该属性内部以键值对的形式存储头信息,头信息的键名必须是小写:
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*/*' }
console.log(request.headers);
根据头信息中的键名,对于重复的原始头信息分为以下多种处理方式:
- 重复的 age、authorization、content-length、content-type、etag、expires、from、host、if-modified-since、if-unmodified-since、last-modified、location、max-forwards、proxy-authorization、referer、retry-after, or user-agent 会被丢弃
set-cookie
是一个数组,重复的键值会被添加到该数组中- 对于头信息其他键名的键值,使用
,
拼接在一起
message.httpVersion
该属性表示客户端支持的 HTTP 版本,通常为 ‘1.1’ 或 ‘1.0’。
此外,也可以通过 message.httpVersionMajor
获取大版本号,通过 message.httpVersionMinor
获取小版本号。
message.method
该属性只对来自 http.Server
的请求有效。
请求方法是一个只读字符串,比如 ‘GET’、’DELETE’。
message.rawHeaders
该属性是一个接收到的原始请求或响应头信息的列表。
注意,键名和键值同处于该列表中,偶数索引为键名,奇数索引为键值。
头信息的键名不限制大小写,即使存在重复的键名也不会被合并。
// 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.rawTrailers
该属性包含了接收到的原始请求或响应 trailer 的键值对,且只存在与 end
事件中。
message.setTimeout(msecs, callback)
msecs
,数值callback
,函数
相当于调用 message.connection.setTimeout(msecs, callback)
。
该方法的返回值是 message
对象。
message.statusCode
该属性只对来自 http.ClientRequest
的响应有效。
该属性的值是 3 位 HTTP 响应状态码,比如 404
。
message.statusMessage
该属性只对来自 http.ClientRequest
的响应有效。
该属性的值用于表示 HTTP 响应状态信息,比如 OK
或 Internal Server Error
。
message.socket
该属性表示与当前链接有关的 net.Socket
对象。
在 HTTPS 中,使用 request.socket.getPeerCertificate()
方法可以获取客户端的验证资料。
message.trailers
该属性包含了请求或响应的 trailer 对象,且只存在与 end
事件中。
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 拆解开来,可以使用 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
或给 require('url').parse
方法传递 true
参数:
$ node
> require('url').parse('/status?name=ryan', true)
{
href: '/status?name=ryan',
search: '?name=ryan',
query: {name: 'ryan'},
pathname: '/status'
}
http.METHODS
- 数组
该属性是一个数组,包含解析器所支持的 HTTP 方法。
http.STATUS_CODES
- 对象
该对象包含所有标准的 HTTP 响应状态码,以及相应的描述信息,比如 http.STATUS_CODES[404] === 'Not Found'
。
http.createClient([port][, host])
使用 http.request() 替代。
http.createServer([requestListener])
该方法返回一个 http.Server
新建的实例。
requestListener
是一个函数,将会被系统自动添加给 request
事件。
http.get(options[, callback])
由于大部分的请求都是没有 body 的 GET
请求,所以 Node.js 提供了这一方法。该方法与 http.request()
唯一的不同在于,它的默认 HTTP 方法就是 GET
,并会自动调用 req.end()
。
http.get('http://www.google.com/index.html', (res) => {
console.log(`Got response: ${res.statusCode}`);
// consume response body
res.resume();
}).on('error', (e) => {
console.log(`Got error: ${e.message}`);
});
http.globalAgent
该属性是 Agent 的全局性实例,也是所有 HTTP 客户端请求的默认目标。
http.request(options[, callback])
Node.js 和每个服务器之间又存在链接,用于发送 HTTP 请求。开发者也可以使用该方法发出请求。
options
可以是对象或字符串。如果是字符串,则系统调用 url.parse()
解析该参数。options
包含的属性包括:
protocal
,使用的协议,默认值为http:
hsot
,发出请求的服务器的域名或 IP 地址hostname
,host
的别名,就url.parse()
的支持度而言,hostname
要优于host
family
,解析 host 或 hostname 时使用的 IP 地址簇。有效值为 4 和 6。如果未指定该参数,则 IPv4 和 IPv6 都可以使用。port
,远程服务器的端口号,默认值为 80localAddress
,绑定网络连接的本地接口socketPath
,Unix Domain Socket(host:port 或 socketPath)method
,字符串形式的 HTTP 请求方法,默认值为GET
path
,请求路径,默认值为/
。如果存在查询字符串,则应该包含查询字符串,比如'/index.html?page=12'
。如果请求路径包含非法字符,则系统会抛出异常。目前,只有空格是不允许的,未来可能对此进行修改。headers
,包含请求头信息的对象。auth
,基本的验证信息,比如用于计算验证头信息的user:password
agent
,用于控制 Agent 的行为。当使用 Agent 时,请求默认使用Connection: keep-alive
。可选值包括:undefined
,默认值,在这个主机和端口上使用http.globalAgent
Agent
,对象,在Agent
中显式使用传入的参数false
,退出 Agent 连接池,默认请求Connection: close
createConnection
,函数,当未使用agent
参数时,该方法用于生成 request 需要的 socket 或 stream。该方法可以避免创建一个只为了重写createConnection
函数的自定义的 Agent。
可选参数 callback
会被设为 response
事件的一次性监听器。
http.request()
方法返回一个 http.ClientRequest
的实例。ClientRequest
的实例是一个可写 stream。如果开发者需要使用 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, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.')
})
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
注意,在上面代码的最后调用了 req.end()
。对于 http.request
方法,必须调用 req.end()
方法显式结束请求,即使未向请求体写入任何数据。
如果请求过程中出现了任何错误(DNS 解析、TCP 级别或 HTTP 解析),就会在返回的请求对象中触发一个 error
事件。对于所有的 error
事件,如果没有注册监听器,则该错误会抛出到全局。
下面是几个需要特别注意的头信息:
- 发送一个包含
Connection: keep-alive
的头信息会让 Node.js 保持服务器的链接,知道下次请求的到来 - 发送一个包含
Content-length
的头信息会替换默认的块编码格式 - 发送一个包含
Expect
的头信息会立即发送请求头。通常来说,如果发送的是Expect: 100-continue'
,则开发者需要设置超时时间并监听continue
事件。 - 发送一个包含验证信息的头信息会替代使用
auth
参数计算出来的验证信息