Node.js v10.13.0 文档


目录

http#

中英对照

稳定性: 2 - 稳定的

要使用 HTTP 服务器与客户端,可以 require('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, ...] 数组。 例如,上面的消息头对象有一个类似以下的 rawHeaders 列表:

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

http.Agent 类#

中英对照

Agent 负责为 HTTP 客户端管理连接的持续与复用。 它为一个给定的主机与端口维护着一个等待请求的队列,且为每个请求重复使用一个单一的 socket 连接直到队列为空,此时 socket 会被销毁或被放入一个连接池中,在连接池中等待被有着相同主机与端口的请求再次使用。 是否被销毁或被放入连接池取决于 keepAlive 选项

连接池中的连接的 TCP Keep-Alive 是开启的,但服务器仍然可能关闭闲置的连接,在这种情况下,这些连接会被移出连接池,且当一个新的 HTTP 请求被创建时再为指定的主机与端口创建一个新的连接。 服务器也可能拒绝允许同一连接上有多个请求,在这种情况下,连接会为每个请求重新创建,且不能被放入连接池。 Agent 仍然会创建请求到服务器,但每个请求会出现在一个新的连接。

但一个连接被客户端或服务器关闭时,它会被移出连接池。 连接池中任何未被使用的 socket 会被释放,从而使 Node.js 进程在没有请求时不用保持运行。 (查看 socket.unref())。

Agent 实例不再被使用时,建议 destroy() 它,因为未被使用的 socket 也会消耗操作系统资源。

当 socket 触发 'close' 事件或 'agentRemove' 事件时,它会被移出代理。 当打算长时间保持打开一个 HTTP 请求且不想它留在代理中,则可以如下处理:

http.get(options, (res) => {
  // 处理事情
}).on('socket', (socket) => {
  socket.emit('agentRemove');
});

代理也可被用于单独的请求。 使用 {agent: false} 作为 http.get() 函数或 http.request() 函数的选项,则会为客户端连接创建一个默认配置的一次性使用的 Agent

agent:false:

http.get({
  hostname: 'localhost',
  port: 80,
  path: '/',
  agent: false  // 创建一个新的代理,只用于本次请求
}, (res) => {
  // 对响应进行处理
});

new Agent([options])#

中英对照

  • options <Object> 代理的配置选项。有以下字段

    • keepAlive <boolean> 保持 socket 可用即使没有请求,以便它们可被将来的请求使用而无需重新建立一个 TCP 连接。默认为 false
    • keepAliveMsecs <number> 当使用了 keepAlive 选项时,该选项指定 TCP Keep-Alive 数据包的初始延迟。 当 keepAlive 选项为 falseundefined 时,该选项无效。 默认为 1000
    • maxSockets <number> 每个主机允许的最大 socket 数量。 默认为 Infinity
    • maxFreeSockets <number> 在空闲状态下允许打开的最大 socket 数量。 仅当 keepAlivetrue 时才有效。 默认为 256
    • timeout <number> socket 超时毫秒数。

http.request() 默认使用的 http.globalAgent 的选项均为各自的默认值。

若要配置其中任何一个,则需要创建自定义的 http.Agent 实例。

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

agent.createConnection(options[, callback])#

中英对照

创建一个用于 HTTP 请求的 socket 或流。

默认情况下,该函数类似于 net.createConnection()。 但是如果期望更大的灵活性,自定义的代理可以重写该方法。

socket 或流可以通过以下两种方式获取:从该函数返回,或传入 callback

callback(err, stream) 参数。

agent.keepSocketAlive(socket)#

中英对照

socket 从请求中分离且可被 Agent 继续使用时调用。

默认行为是:

socket.setKeepAlive(true, this.keepAliveMsecs);
socket.unref();
return true;

该方法可被 Agent 子类重写。 如果方法返回 false 值, 则 socket 会被销毁而不是在下一次请求时持续使用。

agent.reuseSocket(socket, request)#

中英对照

socketkeep-alive 选项保持持久化且被附加到 request 时调用。

默认行为是:

socket.ref();

该方法可被 Agent 子类重写.

agent.destroy()#

中英对照

销毁当前正被代理使用的任何 socket。

通常不需要这么做。 但是如果使用的代理启用了 keepAlive,则当确定它不再被使用时,最好显式地关闭代理。 否则,在服务器终止它们之前,socket 可能还会长时间保持打开。

agent.freeSockets#

中英对照

返回一个对象,包含当前正在等待被启用了 keepAlive 的代理使用的 socket 数组。 不要修改该属性。

agent.getName(options)#

中英对照

  • options <Object> 为名称生成程序提供信息的选项。

    • host <string> 请求发送至的服务器的域名或 IP 地址。
    • port <number> 远程服务器的端口。
    • localAddress <string> 当发送请求时,为网络连接绑定的本地接口。
    • family <integer> 如果不是 undefined,则必须是 4 或 6。
  • 返回: <string>

为请求选项的集合获取一个唯一的名称,用来判断一个连接是否可以被复用。 对于 HTTP 代理,返回 host:port:localAddresshost:port:localAddress:family。 对于 HTTPS 代理,名称会包含 CA、证书、密码、以及其他 HTTPS/TLS 特有的用于判断 socket 复用性的选项。

agent.maxFreeSockets#

中英对照

默认为 256。 对于已启用 keepAlive 的代理,该属性可设置要保留的空闲 socket 的最大数量。

agent.maxSockets#

中英对照

默认为 Infinity。 该属性可设置代理为每个来源打开的并发 socket 的最大数量。 来源是 agent.getName() 的返回值。

agent.requests#

中英对照

返回一个对象,包含还未被分配到 socket 的请求队列。 不要修改。

agent.sockets#

中英对照

返回一个对象,包含当前正被代理使用的 socket 数组。 不要修改。

http.ClientRequest 类#

中英对照

该对象在 http.request() 内部被创建并返回。 它表示着一个正在处理的请求,其请求头已进入队列。 请求头仍可使用 setHeader(name, value)getHeader(name)removeHeader(name) 进行修改。 实际的请求头会与第一个数据块一起发送或当调用 request.end() 时发送。

要获取响应,需为 'response' 事件添加一个监听器到请求对象上。 当响应头被接收到时,'response' 事件会从请求对象上被触发 。 'response' 事件被执行时带有一个参数,该参数是一个 http.IncomingMessage 实例。

'response' 事件期间,可以添加监听器到响应对象上,比如监听 'data' 事件。

如果没有添加 'response' 事件处理函数,则响应会被整个丢弃。 如果添加了 'response' 事件处理函数,则必须消耗完响应对象的数据,可通过调用 response.read()、或添加一个 'data' 事件处理函数、或调用 .resume() 方法。 数据被消耗完时会触发 'end' 事件。 在数据被读取完之前会消耗内存,可能会造成 'process out of memory' 错误。

Node.js 不会检查 Content-Length 与已传输的请求主体的长度是否相等。

请求类继承自,其他的实现如下:

'abort' 事件#

中英对照

当请求已被客户端终止时触发。 该事件仅在首次调用 abort() 时触发。

'connect' 事件#

中英对照

每当服务器响应 CONNECT 请求时触发。 如果该事件未被监听,则接收到 CONNECT 方法的客户端会关闭连接。

例子,用一对客户端和服务端来演示如何监听 'connect' 事件:

const http = require('http');
const net = require('net');
const url = require('url');

// 创建一个 HTTP 代理服务器。
const proxy = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
  // 连接到服务器。
  const srvUrl = url.parse(`http://${req.url}`);
  const 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);
  });
});

// 代理服务器正在运行。
proxy.listen(1337, '127.0.0.1', () => {

  // 发送请求到代理服务器。
  const options = {
    port: 1337,
    hostname: '127.0.0.1',
    method: 'CONNECT',
    path: 'www.google.com:80'
  };

  const req = http.request(options);
  req.end();

  req.on('connect', (res, socket, head) => {
    console.log('已连接');

    // 通过代理服务器发送请求。
    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' 事件#

中英对照

当服务器发送了一个 100 Continue 的 HTTP 响应时触发,通常是因为请求包含 Expect: 100-continue。 这是客户端将要发送请求主体的指令。

'information' 事件#

中英对照

在服务器发送 1xx 代号的响应时触发(101 Upgrade 响应除外)。 该事件会调用一个回调函数,其参数是一个存有状态码的对象。

const http = require('http');

const options = {
  hostname: '127.0.0.1',
  port: 8080,
  path: '/length_request'
};

// 发送请求。
const req = http.request(options);
req.end();

req.on('information', (res) => {
  console.log(`在主响应之前获得信息: ${res.statusCode}`);
});

101 Upgrade 状态不会触发该事件,因为它们会断开传统的HTTP的请求/响应链,例如改用 Web Socket、现 场TLS 升级、采用 HTTP 2.0。 若要获知 101 Upgrade 通知,请监听 'upgrade' 事件。

'response' 事件#

中英对照

当请求的响应被接收到时触发。 该事件只触发一次。

'socket' 事件#

中英对照

当 socket 被分配到请求后触发。

'timeout' 事件#

中英对照

当底层 socket 超时的时候触发。 该方法只会通知空闲的 socket。 请求必须手动停止。

参考 request.setTimeout()

'upgrade' 事件#

中英对照

每当服务器响应 upgrade 请求时触发。 如果该事件未被监听,则接收到 upgrade 请求头的客户端会关闭连接。

例子,用一对客户端和服务端来演示如何监听 'upgrade' 事件:

const http = require('http');

// 创建一个 HTTP 服务器。
const 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);
});

// 服务器正在运行。
srv.listen(1337, '127.0.0.1', () => {

  // 发送请求。
  const options = {
    port: 1337,
    hostname: '127.0.0.1',
    headers: {
      'Connection': 'Upgrade',
      'Upgrade': 'websocket'
    }
  };

  const req = http.request(options);
  req.end();

  req.on('upgrade', (res, socket, upgradeHead) => {
    console.log('收到请求');
    socket.end();
    process.exit(0);
  });
});

request.abort()#

中英对照

标记请求为终止。 调用该方法将使响应中剩余的数据被丢弃且 socket 被销毁。

request.aborted#

中英对照

如果请求已被终止,则该属性的值为请求被终止的时间,从 1 January 1970 00:00:00 UTC 到现在的毫秒数。

request.connection#

中英对照

参考 request.socket

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

中英对照

结束发送请求。 如果部分请求主体还未被发送,则会刷新它们到流中。 如果请求是分块的,则会发送终止字符 '0\r\n\r\n'

如果指定了 data,则相当于调用 request.write(data, encoding) 之后再调用 request.end(callback)

如果指定了 callback,则当请求流结束时会被调用。

request.flushHeaders()#

中英对照

刷新请求头。

出于效率的考虑,Node.js 通常会缓存请求头直到 request.end() 被调用或第一块请求数据被写入。 然后 Node.js 会将请求头和数据打包成一个单一的 TCP 数据包。

通常那是期望的(因为它节省了 TCP 往返),除非第一个数据块很长时间之后才被发送。 request.flushHeaders() 可以绕过最优选择并提前开始请求。

request.getHeader(name)#

中英对照

读取请求头。 请求头的键名是大小写不敏感的。

返回值得类型取决于传入 request.setHeader() 的参数。 例子:

request.setHeader('content-type', 'text/html');
request.setHeader('Content-Length', Buffer.byteLength(body));
request.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
const contentType = request.getHeader('Content-Type');
// contentType 的值为 'text/html'。
const contentLength = request.getHeader('Content-Length');
// contentLength 是一个数值。
const setCookie = request.getHeader('set-cookie');
// setCookie 是一个字符串数组。

request.maxHeadersCount#

中英对照

响应头的最大数量限制。 如果设为 0,则不限制。

request.removeHeader(name)#

中英对照

从请求头对象中移除一个请求头。

request.removeHeader('Content-Type');

request.setHeader(name, value)#

中英对照

为请求头对象设置请求头的值。 如果请求头已存在则替换。 使用字符串数组可以发送多个同名的请求头。 非字符串的值会保留原样,所以 request.getHeader() 会返回非字符串的值。 非字符串的值在网络传输时会转换为字符串。

例子:

request.setHeader('Content-Type', 'application/json');

或:

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

request.setNoDelay([noDelay])#

中英对照

当 socket 被分配给请求且已连接,则 socket.setNoDelay() 会被调用。

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

中英对照

当 socket 被分配给请求且已连接,则 socket.setKeepAlive() 会被调用。

request.setTimeout(timeout[, callback])#

中英对照

当 socket 被分配给请求且已连接,则 socket.setTimeout() 会被调用。

request.socket#

中英对照

指向底层的 socket。 通常不需要访问该属性。 由于协议解析器绑定到 socket 的方式,socket 不会触发'readable'事件。 也可以通过 request.connection 访问 socket

例子:

const http = require('http');
const options = {
  host: 'nodejs.cn',
};
const req = http.get(options);
req.end();
req.once('response', (res) => {
  const ip = req.socket.localAddress;
  const port = req.socket.localPort;
  console.log(`你的 IP 地址是 ${ip},端口是 ${port}`);
  // 消费响应对象。
});

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

中英对照

发送请求主体的一个数据块。 通过多次调用该方法,完整的请求主体可被发送到服务器。 当创建请求时,建议使用 ['Transfer-Encoding', 'chunked'] 请求头。

encoding 参数是可选的,仅当 chunk 是字符串时才有效。 默认为 'utf8'

callback 参数是可选的,当数据块被刷新且不为空时调用。

如果完整的数据被成功地刷新到内部缓冲,则返回 true。 如果失败或部分数据还在内存中等待队列,则返回 false。 当缓冲再次可用时触发 'drain' 事件。

当调用 write 函数传入空字符串或空 buffer 时,不会进行任何操作。

http.Server 类#

中英对照

该类继承自 net.Server,且具有以下额外的事件:

'checkContinue' 事件#

中英对照

每当接收到一个带有 HTTP Expect: 100-continue 请求头的请求时触发。 如果该事件未被监听,则服务器会自动响应 100 Continue

处理该事件时,如果客户端应该继续发送请求主体,则调用 response.writeContinue(),否则生成一个适当的 HTTP 响应(例如 400 错误请求)。

当该事件被触发且处理后,'request' 事件不会被触发。

'checkExpectation' 事件#

中英对照

每当接收到一个带有 HTTP Expect 请求头(值不为 100-continue)的请求时触发。 如果该事件未被监听,则服务器会自动响应 417 Expectation Failed

当该事件被触发且处理后,'request' 事件不会被触发。

'clientError' 事件#

中英对照

如果客户端触发了一个 'error' 事件,则它会被传递到这里。 该事件的监听器负责关闭或销毁底层的 socket。 例如,用户可能希望更温和地用自定义的 HTTP 响应关闭 socket,而不是突然地切断连接。

默认情况下,如果可以会使用 HTTP '400 Bad Request' 响应关闭 socket,否则 socket 会被立即销毁。

socket 参数是发生错误的 net.Socket 对象。

const http = require('http');

const server = http.createServer((req, res) => {
  res.end();
});
server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.listen(8000);

'clientError' 事件发生时,不会有 requestresponse 对象,所以发送的任何 HTTP 响应,包括响应头和内容,必须被直接写入到 socket 对象。 必须确保响应是一个被正确格式化的 HTTP 响应消息。

err 是一个 Error 实例,包含以下两部分:

  • bytesParsed: Node.js 正确解析的请求包的字节数。
  • rawPacket: 当前请求的原始数据包。

'close' 事件#

中英对照

当服务器关闭时触发。

'connect' 事件#

中英对照

每当客户端发送 HTTP CONNECT 请求时触发。 如果该事件未被监听,则发送 CONNECT 请求的客户端会关闭连接。

当该事件被触发后,请求的 socket 上没有 'data' 事件监听器,这意味着需要绑定 'data' 事件监听器,用来处理 socket 上被发送到服务器的数据。

'connection' 事件#

中英对照

当新的 TCP 流被建立时触发。 socket 是一个 net.Socket 类型的对象。 通常用户无需访问该事件。 因为协议解析器绑定到 socket 的方式,socket 不会触发 'readable' 事件。 socket 也可以通过 request.connection 访问。

该事件也可以通过注入连接到 HTTP 服务器显式地调用。 在这种情况下,可以传入 Duplex 流。

'request' 事件#

中英对照

每次接收到一个请求时触发。 每个连接可能有多个请求(在 HTTP keep-alive 连接的情况下)。

'upgrade' 事件#

中英对照

每当客户端发送 HTTP upgrade 请求时触发。 如果该事件未被监听,则发送 upgrade 请求的客户端会关闭连接。

当该事件被触发后,请求的 socket 上没有 'data' 事件监听器,这意味着需要绑定 'data' 事件监听器,用来处理 socket 上被发送到服务器的数据。

server.close([callback])#

中英对照

停止服务端接收新的连接。 参考 net.Server.close()

server.listen()#

中英对照

开启 HTTP 服务器监听连接。 与 net.Serverserver.listen() 相同。

server.listening#

中英对照

  • <boolean> 表明服务器是否正在监听连接。

server.maxHeadersCount#

中英对照

限制请求头的最大数量。 如果设为 0,则没有限制。

server.setTimeout([msecs][, callback])#

中英对照

设置 socket 的超时时间。 如果发生超时,则触发服务器对象的 'timeout' 事件,并传入 socket 作为参数。

默认情况下,服务器的超时时间是 2 分钟,且超时后的 socket 会被自动销毁。 如果为服务器的 'timeout' 事件分配了一个回调函数,则超时必须被显式地处理。

server.timeout#

中英对照

  • <number> 超时时间,以毫秒为单位。默认为 120000(2 分钟)。

socket 被认定为超时的空闲毫秒数。

值设为 0 可禁用请求连接的超时行为。

socket 的超时逻辑是在连接上设定的,所以改变这个值只影响服务器新建的连接,而不会影响任何已存在的连接。

server.keepAliveTimeout#

中英对照

  • <number> 超时毫秒. 默认为 5000(5 秒)。

服务器完成最后的响应之后需要等待的额外的传入数据的活跃毫秒数, socket 才能被销毁。 如果服务器在 keep-alive 计时已激活时接收到新的数据, 则会重置常规的非活动计时, 即 server.timeout

值为 0 时禁用传入连接 keep-alive 的超时行为。

socket 的超时逻辑是在连接上设定的,所以改变这个值只影响服务器新建的连接,而不会影响任何已存在的连接。

http.ServerResponse 类#

中英对照

该对象在 HTTP 服务器内部被创建。 作为第二个参数被传入 'request' 事件。

该类继承自,其他实现如下:

'close' 事件#

中英对照

当底层连接在 response.end() 被调用或能够刷新之前被终止时触发。

'finish' 事件#

中英对照

当响应已被发送时触发。 更具体地说,当响应头和响应主体的最后一部分已被交给操作系统通过网络进行传输时,触发该事件。 这并不意味着客户端已接收到任何东西。

response.addTrailers(headers)#

中英对照

该方法会添加 HTTP 尾部响应头(一种在消息尾部的响应头)到响应。

仅当响应使用分块编码时,尾部响应头才会被发送;否则(比如请求为 HTTP/1.0),尾部响应头会被丢弃。

发送尾部响应头之前,需先发送 Trailer 响应头,并在值里带上尾部响应头字段的列表。 例如:

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

如果尾部响应头字段的名称或值包含无效字符,则抛出 TypeError 错误。

response.connection#

中英对照

参考 response.socket

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

中英对照

该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。 每次响应都必须调用 response.end() 方法。

如果指定了 data,则相当于调用 response.write(data, encoding) 之后再调用 response.end(callback)

如果指定了 callback,则当响应流结束时被调用。

response.finished#

中英对照

返回一个布尔值,表示响应是否已完成。 默认为 false。 执行 response.end() 之后,该值会变为 true

response.getHeader(name)#

中英对照

读取一个已入队列但尚未发送到客户端的响应头。 名称不区分大小写。 返回值的类型取决于传入 response.setHeader() 的参数。

response.setHeader('Content-Type', 'text/html');
response.setHeader('Content-Length', Buffer.byteLength(body));
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
const contentType = response.getHeader('content-type');
// contentType 的值为 'text/html'。
const contentLength = response.getHeader('Content-Length');
// contentLength 是一个数值。
const setCookie = response.getHeader('set-cookie');
// setCookie 是一个字符串数组。

response.getHeaderNames()#

中英对照

返回包含当前响应头名称的数组。 响应头名称均为小写。

response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);

const headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']

response.getHeaders()#

中英对照

返回当前响应头文件的浅拷贝。 由于使用了浅拷贝,因此数组值可能会改变,无需对各种与响应头相关的 http 模块方法进行额外调用。 返回对象的键是响应头名称,值是各自的响应头值。 所有响应头名称都是小写的。

response.getHeaders() 返回的对象不会原型继承 JavaScript Object。 这意味着,没有定义典型的 Object 方法,如 obj.toString()obj.hasOwnProperty() 和其他方法,并且不起作用。

例子:

response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);

const headers = response.getHeaders();
// headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }

response.hasHeader(name)#

中英对照

如果响应头有设置 name 响应头,则返回 true。 响应头名称匹配不区分大小写。

例子:

const hasContentType = response.hasHeader('content-type');

response.headersSent#

中英对照

返回一个布尔值(只读)。 如果响应头已被发送则为 true,否则为 false

response.removeHeader(name)#

中英对照

从隐式发送的队列中移除一个响应头。

例子:

response.removeHeader('Content-Encoding');

response.sendDate#

中英对照

当为 true 时,如果响应头里没有日期响应头,则日期响应头会被自动生成并发送。默认为 true

该属性只可在测试时被禁用,因为 HTTP 响应需要包含日期响应头。

response.setHeader(name, value)#

中英对照

为一个隐式的响应头设置值。 如果该响应头已存在,则值会被覆盖。 如果要发送多个名称相同的响应头,则使用字符串数组。 非字符串的值会保留原样,所以 response.getHeader() 会返回非字符串的值。 非字符串的值在网络传输时会转换为字符串。

例子:

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

或:

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

如果响应头字段的名称或值包含无效字符,则抛出 TypeError 错误。

response.setHeader() 设置的响应头会与 response.writeHead() 设置的响应头合并,且 response.writeHead() 的优先。

// 返回 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])#

中英对照

设置 socket 的超时时间为 msecs。 如果提供了回调函数,则它会作为监听器被添加到响应对象的 'timeout' 事件。

如果没有 'timeout' 监听器被添加到请求、响应或服务器,则 socket 会在超时后被销毁。 如果在请求、响应或服务器的 'timeout' 事件上分配了回调函数,则超时的 socket 必须被显式地处理。

response.socket#

中英对照

指向底层的 socket。 通常不需要访问该属性。 由于协议解析器绑定到 socket 的方式,socket 不会触发'readable'事件。 调用 response.end() 之后,该属性会变为 null。 也可以通过 response.connection 来访问 socket

例子:

const http = require('http');
const server = http.createServer((req, res) => {
  const ip = res.socket.remoteAddress;
  const port = res.socket.remotePort;
  console.log(`你的 IP 地址是 ${ip},端口是 ${port}`);
}).listen(3000);

response.statusCode#

中英对照

当使用隐式的响应头时(没有显式地调用 response.writeHead()),该属性控制响应头刷新时将被发送到客户端的状态码。

例子:

response.statusCode = 404;

响应头被发送到客户端后,该属性表示被发出的状态码。

response.statusMessage#

中英对照

当使用隐式的响应头时(没有显式地调用 response.writeHead()),该属性控制响应头刷新时将被发送到客户端的状态信息。 如果该值为 undefined,则使用状态码的标准信息。

例子:

response.statusMessage = 'Not found';

响应头被发送到客户端后,该属性表示被发出的状态信息。

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

中英对照

如果该方法被调用且 response.writeHead() 没有被调用,则它会切换到隐式响应头模式并刷新隐式响应头。

该方法会发送一块响应主体。 它可被多次调用,以便提供连续的响应主体片段。

http 模块中,当请求是 HEAD 请求时,响应主体被省略。 类似地,204304 响应不能包括消息体。

chunk 可以是一个字符串或一个 buffer。 如果 chunk 是一个字符串,则第二个参数指定如何将它编码成一个字节流。 encoding 默认为 'utf8'。 当数据块被刷新时,callback 会被调用。

注意:这是原始的 HTTP 主体,且与可能被使用的高级主体编码无关。

response.write() 首次被调用时,会发送缓冲的响应头信息和响应主体的第一块数据到客户端。 response.write() 第二次被调用时,Node.js 能够确定数据会被接收,于是开始传输新数据。 也就是说,响应的完成取决于响应主体的第一块数据。

如果全部数据被成功刷新到内核缓冲区,则返回 true。 如果全部或部分数据还在内存中排队,则返回 false。 当缓冲区再次空闲时,则触发 'drain' 事件。

response.writeContinue()#

中英对照

发送一个 HTTP/1.1 100 Continue 消息到客户端,表示请求主体可以开始发送。 参阅 Server'checkContinue' 事件。

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

中英对照

发送一个响应头给请求。 状态码是一个三位数的 HTTP 状态码,如 404。 最后一个参数 headers 是响应头。 第二个参数 statusMessage 是可选的状态描述。

例子:

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

该方法在消息中只能被调用一次,且必须在 response.end() 被调用之前调用。

如果在调用该方法之前调用 response.write()response.end(),则隐式的响应头会被处理并调用该函数。

response.setHeader() 设置的响应头会与 response.writeHead() 设置的响应头合并,且 response.writeHead() 的优先。

// 返回 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' 只包含单字节字符。 如果响应主体包含高级编码的字符,则应使用 Buffer.byteLength() 来确定在给定编码中的字节数。 Node.js 不会检查 Content-Length 与已发送的响应主体的长度是否相同。

如果响应头字段的名称或值包含无效字符,则抛出 TypeError 错误。

response.writeProcessing()#

中英对照

发送 HTTP/1.1 102 进度消息给客户端,表明可以发送请求体。

http.IncomingMessage 类#

中英对照

IncomingMessage 对象由 http.Serverhttp.ClientRequest 创建,并作为第一个参数分别递给 'request''response' 事件。 它可以用来访问响应状态、消息头、以及数据。

它实现了可读流接口,还有以下额外的事件、方法、以及属性。

'aborted' 事件#

中英对照

当请求被终止时触发。

'close' 事件#

中英对照

当底层连接被关闭时触发。 同 'end' 事件一样,该事件每个响应只触发一次。

message.aborted#

中英对照

如果请求已中止,则返回 true

message.destroy([error])#

中英对照

调用接收到 IncomingMessage 的 socket 上的 destroy() 方法。 如果提供了 error,则触发 'error' 事件,且把 error 作为参数传入事件的监听器。

message.headers#

中英对照

请求头或响应头的对象。

头信息的名称与值的键值对。 头信息的名称为小写。 例如:

// 输出类似以下的东西:
//
// { 'user-agent': 'curl/7.22.0',
//   host: '127.0.0.1:8000',
//   accept: '*/*' }
console.log(request.headers);

原始头信息中的重复数据会按以下方式根据头信息名称进行处理:

  • 重复的 ageauthorizationcontent-lengthcontent-typeetagexpiresfromhostif-modified-sinceif-unmodified-sincelast-modifiedlocationmax-forwardsproxy-authorizationrefererretry-after 、或 user-agent 会被丢弃。
  • set-cookie 始终是一个数组。重复的会被添加到数组。
  • 对于其他头信息,其值使用 , 拼接。

message.httpVersion#

中英对照

在服务器请求中,该属性返回客户端发送的 HTTP 版本。 在客户端响应中,该属性返回连接到的服务器的 HTTP 版本。 可能的值有 '1.1''1.0'

message.httpVersionMajor 返回 HTTP 版本的第一个整数值,message.httpVersionMinor 返回 HTTP 版本的第二个整数值。

message.method#

中英对照

仅在 http.Server 返回的请求中有效。

返回一个字符串,表示请求的方法。 该属性只读。 例如:'GET''DELETE'

message.rawHeaders#

中英对照

接收到的原始的请求头或响应头列表。

键和值在同一个列表中。 偶数位的是键,奇数位的是对应的值。

头信息的名称不会被转换为小写,重复的也不会被合并。

// 输出类似以下的东西:
//
// [ 'user-agent',
//   '该值不会生效,因为只能有一个 user-agent',
//   '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)#

中英对照

调用 message.connection.setTimeout(msecs, callback)

message.socket#

中英对照

返回与连接关联的 net.Socket 对象。

通过 HTTPS 的支持,使用 request.socket.getPeerCertificate() 获取客户端的认证信息。

message.statusCode#

中英对照

仅在 http.ClientRequest 返回的响应中有效。

返回一个三位数的 HTTP 响应状态码。 如 404

message.statusMessage#

中英对照

仅在 http.ClientRequest 返回的响应中有效。

返回 HTTP 响应状态消息(原因描述)。 如 OKInternal Server Error

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')
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=ryan',
  query: 'name=ryan',
  pathname: '/status',
  path: '/status?name=ryan',
  href: '/status?name=ryan' }

如果想从查询字符串中提取参数,可以使用 require('querystring').parse 函数、或为 require('url').parse 的第二个参数传入 true。 例子:

$ node
> require('url').parse('/status?name=ryan', true)
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=ryan',
  query: { name: 'ryan' },
  pathname: '/status',
  path: '/status?name=ryan',
  href: '/status?name=ryan' }

http.METHODS#

中英对照

返回解析器支持的 HTTP 方法的列表。

http.STATUS_CODES#

中英对照

返回标准的 HTTP 响应状态码的集合,以及各自的简短描述。 例如,http.STATUS_CODES[404] === 'Not Found'

http.createServer([options][, requestListener])#

中英对照

  • options <Object>

    • IncomingMessage <http.IncomingMessage> 指定要使用的 IncomingMessage 类。 用于拓展原始的 IncomingMessage 类。 默认为 IncomingMessage
    • ServerResponse <http.ServerResponse> 指定要使用的 ServerResponse 类。 用于拓展原始的 ServerResponse 类。 默认为 ServerResponse
  • requestListener <Function>
  • 返回: <http.Server>

返回一个新建的 http.Server 实例。

requestListener 是一个函数,会被自动添加到 'request' 事件。

http.get(options[, callback])#

http.get(url[, options][, callback])#

中英对照

因为大多数请求都是 GET 请求且不带请求主体,所以 Node.js 提供了该便捷方法。 该方法与 http.request() 唯一的区别是它设置请求方法为 GET 且自动调用 req.end()。 回调函数务必消耗掉响应数据,原因详见 http.ClientRequest 章节。

callback 被调用时只传入一个参数,该参数是 http.IncomingMessage 的一个实例。

例子,获取 JSON:

http.get('http://nodejs.org/dist/index.json', (res) => {
  const { statusCode } = res;
  const contentType = res.headers['content-type'];

  let error;
  if (statusCode !== 200) {
    error = new Error('请求失败。\n' +
                      `状态码: ${statusCode}`);
  } else if (!/^application\/json/.test(contentType)) {
    error = new Error('无效的 content-type.\n' +
                      `期望 application/json 但获取的是 ${contentType}`);
  }
  if (error) {
    console.error(error.message);
    // 消耗响应数据以释放内存
    res.resume();
    return;
  }

  res.setEncoding('utf8');
  let rawData = '';
  res.on('data', (chunk) => { rawData += chunk; });
  res.on('end', () => {
    try {
      const parsedData = JSON.parse(rawData);
      console.log(parsedData);
    } catch (e) {
      console.error(e.message);
    }
  });
}).on('error', (e) => {
  console.error(`报错: ${e.message}`);
});

http.globalAgent#

中英对照

Agent 的全局实例,作为所有 HTTP 客户端请求的默认 Agent

http.request(options[, callback])#

http.request(url[, options][, callback])#

中英对照

  • url <string> | <URL>
  • options <Object>

    • protocol <string> 使用的协议。默认为 http:
    • host <string> 请求发送至的服务器的域名或 IP 地址。默认为 localhost。  * hostname <string> host 的别名。为了支持 url.parse()hostname 优先于 host
    • family <number> 当解析 hosthostname 时使用的 IP 地址族。 有效值是 46。当未指定时,则同时使用 IP v4 和 v6。
    • port <number> 远程服务器的端口。默认为 80
    • localAddress <string> 为网络连接绑定的本地接口。
    • socketPath <string> Unix 域 Socket(使用 host:port 或 socketPath)。
    • method <string> 指定 HTTP 请求方法的字符串。默认为 'GET'
    • path <string> 请求的路径。 应包括查询字符串(如有的话)。如 '/index.html?page=12'。 当请求的路径中包含非法字符时,会抛出异常。 目前只有空字符会被拒绝,但未来可能会变化。 默认为 '/'
    • headers <Object> 包含请求头的对象。
    • auth <string> 基本身份验证,如 'user:password' 用来计算 Authorization 请求头。
    • agent <http.Agent> | <boolean> 控制 Agent 的行为。 可能的值有:

      • undefined (默认): 对该主机和端口使用 http.globalAgent
      • Agent 对象:显式地使用传入的 Agent
      • false: 创建一个新的使用默认值的 Agent
    • createConnection <Function> 当不使用 agent 选项时,为请求创建一个 socket 或流。 这可以用于避免仅仅创建一个自定义的 Agent 类来覆盖默认的 createConnection 函数。详见 agent.createConnection()。 返回值为 Duplex 流。
    • timeout <number>: 指定 socket 超时的毫秒数。 设置了 socket 等待连接的超时时间。
    • setHost <boolean>: 指定是否自动添加 Host 请求头。默认为 true
  • callback <Function>
  • 返回: <http.ClientRequest>

Node.js 为每台服务器维护多个连接来进行 HTTP 请求。 该函数允许显式地发出请求。

url 可以是字符串或 URL 对象。 如果 url 是字符串,指定它会被自动使用 url.parse() 解析。 如果 urlURL 对象, 则它会被自动转换成 options 对象。

如果 urloptions 都指定了,则两个对象会被合并,其中 options 对象优先。

callback 参数会作为单次监听器被添加到 'response' 事件。

http.request() 返回一个 http.ClientRequest 类的实例。 ClientRequest 实例是一个可写流。 如果需要通过 POST 请求上传一个文件,则写入到 ClientRequest 对象。

例子:

const postData = querystring.stringify({
  'msg' : 'Hello World!'
});

const options = {
  hostname: 'www.google.com',
  port: 80,
  path: '/upload',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': Buffer.byteLength(postData)
  }
};

const req = http.request(options, (res) => {
  console.log(`状态码: ${res.statusCode}`);
  console.log(`响应头: ${JSON.stringify(res.headers)}`);
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
    console.log(`响应主体: ${chunk}`);
  });
  res.on('end', () => {
    console.log('响应中已无数据。');
  });
});

req.on('error', (e) => {
  console.error(`请求遇到问题: ${e.message}`);
});

// 写入数据到请求主体
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 事件的监听器都需要被设置。 详见 RFC2616 章节 8.2.3。

  • 发送 Authorization 请求头会替代 auth 选项计算基本身份验证。

例子,使用 URL 作为 options

const options = new URL('http://abc:xyz@example.com');

const req = http.request(options, (res) => {
  // ...
});

如果请求成功,则以下事件会被依次触发:

  • 'socket' 事件。
  • 'response' 事件。

    • 多次触发 res 对象的 'data' 事件(如果响应主体为空,则不会触发 'data' 事件,比如重定向)。
    • res 对象的 'end' 事件。
  • 'close' 事件。

如果连接出错,则以下事件会被依次触发:

  • 'socket' 事件。
  • 'error' 事件。
  • 'close' 事件。

如果连接成功之前调用 req.abort(),则以下事件会被依次触发:

  • 'socket' 事件。
  • (此时调用 req.abort())
  • 'abort' 事件。
  • 'close' 事件。
  • 'error' 事件并带上错误信息 'Error: socket hang up' 和错误码 'ECONNRESET'

如果响应接收到之后调用 req.abort(),则以下事件会被依次触发:

  • 'socket' 事件。
  • 'response' 事件。

    • 多次触发 res 对象的 'data' 事件。
  • (此时调用 req.abort())
  • 'abort' 事件。
  • 'close' 事件。

    • res 对象的 'aborted' 事件。
    • res 对象的 'end' 事件。
    • res 对象的 'close' 事件。