HTTP#

稳定性:2 - 稳定

源代码: lib/http.js

该模块包含客户端和服务器,可以通过 require('node:http') (CommonJS) 或 import * as http from 'node:http' (ES 模块) 导入。

Node.js 中的 HTTP 接口旨在支持协议的许多传统上难以使用的功能。 特别是,大型的,可能经过分块编码的消息。 该接口非常谨慎,从不缓冲整个请求或响应,因此用户能够流式传输数据。

HTTP 消息头由这样的对象表示

{ "content-length": "123",
  "content-type": "text/plain",
  "connection": "keep-alive",
  "host": "example.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', 'example.com',
  'accepT', '*/*' ] 

类:http.Agent#

Agent 负责管理 HTTP 客户端的连接持久性和重用。 它维护给定主机和端口的挂起请求队列,为每个请求重用单个套接字连接,直到队列为空,此时套接字将被销毁或放入池中,并在其中保留以再次用于对同一主机和端口的请求。 它是被销毁还是被池化取决于 keepAlive 选项

池化连接为其启用了 TCP Keep-Alive,但是服务器可能仍然关闭空闲连接,在这种情况下,它们将从池中删除,并且当为该主机和端口发出新的 HTTP 请求时,将建立新的连接。 服务器也可能拒绝通过同一连接允许多个请求,在这种情况下,必须为每个请求重新建立连接,并且无法进行池化。 Agent 仍然会向该服务器发出请求,但是每个请求都将通过新的连接进行。

当连接被客户端或服务器关闭时,它将从池中删除。 池中任何未使用的套接字都将被取消引用,以便在没有未完成的请求时不会使 Node.js 进程保持运行。(请参阅 socket.unref())。

最佳实践是在不再使用时 destroy() Agent 实例,因为未使用的套接字会消耗 OS 资源。

当套接字发出 'close' 事件或 'agentRemove' 事件时,该套接字将从代理中删除。 当打算长时间保持一个 HTTP 请求打开而不将其保留在代理中时,可以执行以下操作

http.get(options, (res) => {
  // Do stuff
}).on('socket', (socket) => {
  socket.emit('agentRemove');
}); 

代理也可以用于单个请求。 通过将 {agent: false} 作为 http.get()http.request() 函数的选项提供,则将为客户端连接使用具有默认选项的一次性使用 Agent

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 <Object> 要在代理上设置的可配置选项集。 可以具有以下字段
    • keepAlive <boolean> 保持 socket 连接,即使没有未完成的请求,这样它们就可以用于未来的请求,而无需重新建立 TCP 连接。不要与 Connection 标头的 keep-alive 值混淆。 使用代理时,总是会发送 Connection: keep-alive 标头,除非显式指定 Connection 标头,或者将 keepAlivemaxSockets 选项分别设置为 falseInfinity,在这种情况下,将使用 Connection: close默认值: false
    • keepAliveMsecs <number> 当使用 keepAlive 选项时,指定 TCP Keep-Alive 数据包的初始延迟。 当 keepAlive 选项为 falseundefined 时,会被忽略。 默认值: 1000
    • maxSockets <number> 每个主机允许的最大 socket 连接数。 如果同一主机打开多个并发连接,则每个请求都将使用新的 socket,直到达到 maxSockets 值。 如果主机尝试打开超过 maxSockets 的连接数,则额外的请求将进入挂起的请求队列,并在现有连接终止时进入活动连接状态。 这确保在任何时间点,来自给定主机的活动连接最多为 maxSockets 个。 默认值: Infinity
    • maxTotalSockets <number> 允许的总 socket 最大数量(所有主机)。 每个请求都将使用新的 socket,直到达到最大值。 默认值: Infinity
    • maxFreeSockets <number> 每个主机在空闲状态下保持打开的最大 socket 数。 仅当 keepAlive 设置为 true 时才相关。 默认值: 256
    • scheduling <string> 选择下一个要使用的空闲 socket 时应用的调度策略。 它可以是 'fifo''lifo'。 两种调度策略的主要区别在于 'lifo' 选择最近使用的 socket,而 'fifo' 选择最不常用的 socket。 如果每秒请求的速率较低,则 'lifo' 调度将降低选择可能已被服务器因不活动而关闭的 socket 的风险。 如果每秒请求的速率很高,则 'fifo' 调度将最大化打开的 socket 数量,而 'lifo' 调度将使其尽可能低。 默认值: 'lifo'
    • timeout <number> Socket 超时(以毫秒为单位)。 这将在创建 socket 时设置超时。

socket.connect() 中的 options 也受支持。

要配置它们中的任何一个,必须创建一个自定义的 http.Agent 实例。

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

agent.createConnection(options[, callback])#

生成一个用于 HTTP 请求的 socket/stream。

默认情况下,此函数与 net.createConnection() 相同。 但是,如果需要更大的灵活性,自定义代理可能会覆盖此方法。

可以通过两种方式提供 socket/stream:通过从此函数返回 socket/stream,或通过将 socket/stream 传递给 callback

保证此方法返回 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了 <net.Socket> 以外的 socket 类型。

callback 的签名为 (err, stream)

agent.keepSocketAlive(socket)#

socket 从请求中分离并可以被 Agent 持久化时调用。 默认行为是

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

此方法可以被特定的 Agent 子类覆盖。 如果此方法返回一个 falsy 值,则 socket 将被销毁,而不是将其持久化以供下一次请求使用。

socket 参数可以是 <net.Socket> 的实例,它是 <stream.Duplex> 的子类。

agent.reuseSocket(socket, request)#

socket 在因 keep-alive 选项而持久化后连接到 request 时调用。 默认行为是

socket.ref(); 

此方法可以被特定的 Agent 子类覆盖。

socket 参数可以是 <net.Socket> 的实例,它是 <stream.Duplex> 的子类。

agent.destroy()#

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

通常没有必要这样做。 但是,如果使用启用了 keepAlive 的代理,则最好在不再需要代理时显式关闭代理。 否则,socket 可能会保持打开很长时间,直到服务器终止它们。

agent.freeSockets#

一个对象,当启用 keepAlive 时,它包含当前等待代理使用的 socket 数组。 不要修改。

freeSockets 列表中的 socket 将在 'timeout' 上自动销毁并从数组中删除。

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、cert、ciphers 和其他确定 socket 可重用性的 HTTPS/TLS 特定选项。

agent.maxFreeSockets#

默认设置为 256。 对于启用了 keepAlive 的代理,这会设置在空闲状态下保持打开的最大 socket 数。

agent.maxSockets#

默认设置为 Infinity。 确定代理每个来源可以打开多少个并发 socket。 来源是 agent.getName() 的返回值。

agent.maxTotalSockets#

默认设置为 Infinity。 确定代理可以打开多少个并发 socket。 与 maxSockets 不同,此参数适用于所有来源。

agent.requests#

一个对象,包含尚未分配给 socket 的请求队列。 不要修改。

agent.sockets#

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

类: http.ClientRequest#

此对象在内部创建并从 http.request() 返回。 它表示一个正在进行中的请求,其标头已排队。 仍然可以使用 setHeader(name, value)getHeader(name)removeHeader(name) API 修改标头。 实际的标头将与第一个数据块一起发送,或者在调用 request.end() 时发送。

要获取响应,请为请求对象添加 'response' 的监听器。 当收到响应标头时,将从请求对象发出 'response''response' 事件使用一个参数执行,该参数是 http.IncomingMessage 的一个实例。

'response' 事件期间,可以将监听器添加到响应对象;特别是监听 'data' 事件。

如果没有添加 'response' 处理程序,则响应将被完全丢弃。但是,如果添加了 'response' 事件处理程序,则必须使用响应对象中的数据,可以通过在每次出现 'readable' 事件时调用 response.read(),或者通过添加 'data' 处理程序,或者通过调用 .resume() 方法来实现。在数据被使用之前,'end' 事件不会触发。此外,在读取数据之前,它会消耗内存,最终可能导致“进程内存不足”错误。

为了向后兼容,只有在注册了 'error' 监听器时,res 才会发出 'error'

设置 Content-Length 标头以限制响应主体的大小。如果 response.strictContentLength 设置为 true,则 Content-Length 标头值不匹配将导致抛出 Error,其 code:'ERR_HTTP_CONTENT_LENGTH_MISMATCH'

Content-Length 值应以字节为单位,而不是字符。使用 Buffer.byteLength() 来确定正文的字节长度。

事件: 'abort'#

稳定性: 0 - 已弃用。请监听 'close' 事件。

当客户端中止请求时发出。此事件仅在首次调用 abort() 时发出。

事件: 'close'#

表示请求已完成,或者其底层连接过早终止(在响应完成之前)。

事件: 'connect'#

每次服务器使用 CONNECT 方法响应请求时都会发出。 如果没有监听此事件,则收到 CONNECT 方法的客户端将关闭其连接。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

一个客户端和服务器的例子,演示了如何监听 'connect' 事件

import { createServer, request } from 'node:http';
import { connect } from 'node:net';
import { URL } from 'node:url';

// Create an HTTP tunneling proxy
const proxy = createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
proxy.on('connect', (req, clientSocket, head) => {
  // Connect to an origin server
  const { port, hostname } = new URL(`http://${req.url}`);
  const serverSocket = connect(port || 80, hostname, () => {
    clientSocket.write('HTTP/1.1 200 Connection Established\r\n' +
                    'Proxy-agent: Node.js-Proxy\r\n' +
                    '\r\n');
    serverSocket.write(head);
    serverSocket.pipe(clientSocket);
    clientSocket.pipe(serverSocket);
  });
});

// Now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {

  // Make a request to a tunneling proxy
  const options = {
    port: 1337,
    host: '127.0.0.1',
    method: 'CONNECT',
    path: 'www.google.com:80',
  };

  const req = 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();
    });
  });
});const http = require('node:http');
const net = require('node:net');
const { URL } = require('node:url');

// Create an HTTP tunneling proxy
const proxy = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
proxy.on('connect', (req, clientSocket, head) => {
  // Connect to an origin server
  const { port, hostname } = new URL(`http://${req.url}`);
  const serverSocket = net.connect(port || 80, hostname, () => {
    clientSocket.write('HTTP/1.1 200 Connection Established\r\n' +
                    'Proxy-agent: Node.js-Proxy\r\n' +
                    '\r\n');
    serverSocket.write(head);
    serverSocket.pipe(clientSocket);
    clientSocket.pipe(serverSocket);
  });
});

// Now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {

  // Make a request to a tunneling proxy
  const options = {
    port: 1337,
    host: '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('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'#

当服务器发送 “100 Continue” HTTP 响应时发出,通常是因为请求包含 “Expect: 100-continue”。 这是一个指示客户端应该发送请求正文的指令。

事件: 'finish'#

当请求已发送时发出。更具体地说,当响应标头和正文的最后一个片段已交给操作系统以通过网络传输时,会发出此事件。这并不意味着服务器已经收到任何东西。

事件: 'information'#

当服务器发送 1xx 中间响应(不包括 101 Upgrade)时发出。 此事件的监听器将收到一个对象,其中包含 HTTP 版本、状态码、状态消息、键值标头对象以及包含原始标头名称及其各自值的数组。

import { request } from 'node:http';

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

// Make a request
const req = request(options);
req.end();

req.on('information', (info) => {
  console.log(`Got information prior to main response: ${info.statusCode}`);
});const http = require('node:http');

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

// Make a request
const req = http.request(options);
req.end();

req.on('information', (info) => {
  console.log(`Got information prior to main response: ${info.statusCode}`);
});

由于 101 Upgrade 状态与传统的 HTTP 请求/响应链断开,例如 Web 套接字、就地 TLS 升级或 HTTP 2.0,因此不会触发此事件。 要收到 101 Upgrade 通知,请监听 'upgrade' 事件。

事件: 'response'#

当收到对此请求的响应时发出。 此事件只发出一次。

事件: 'socket'#

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

事件: 'timeout'#

当底层套接字因不活动而超时时发出。 这仅通知套接字已空闲。 必须手动销毁请求。

另请参阅: request.setTimeout()

事件: 'upgrade'#

每次服务器使用升级响应请求时都会发出。 如果没有监听此事件,并且响应状态码为 101 Switching Protocols,则收到升级标头的客户端将关闭其连接。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

一个客户端服务器示例,演示了如何监听 'upgrade' 事件。

import http from 'node:http';
import process from 'node:process';

// Create an HTTP server
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
server.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
server.listen(1337, '127.0.0.1', () => {

  // make a request
  const options = {
    port: 1337,
    host: '127.0.0.1',
    headers: {
      'Connection': 'Upgrade',
      'Upgrade': 'websocket',
    },
  };

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

  req.on('upgrade', (res, socket, upgradeHead) => {
    console.log('got upgraded!');
    socket.end();
    process.exit(0);
  });
});const http = require('node:http');

// Create an HTTP server
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
server.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
server.listen(1337, '127.0.0.1', () => {

  // make a request
  const options = {
    port: 1337,
    host: '127.0.0.1',
    headers: {
      'Connection': 'Upgrade',
      'Upgrade': 'websocket',
    },
  };

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

  req.on('upgrade', (res, socket, upgradeHead) => {
    console.log('got upgraded!');
    socket.end();
    process.exit(0);
  });
});

request.abort()#

稳定性: 0 - 已弃用:请改用 request.destroy()

将请求标记为中止。 调用此方法将导致丢弃响应中的剩余数据并销毁套接字。

request.aborted#

稳定性: 0 - 已弃用。 请检查 request.destroyed

如果请求已中止,则 request.aborted 属性将为 true

request.connection#

稳定性: 0 - 已弃用。 请使用 request.socket

参见 request.socket

request.cork()#

参见 writable.cork()

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

完成发送请求。 如果有任何正文部分未发送,它将刷新它们到流。 如果请求是分块的,这将发送终止的 '0\r\n\r\n'

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

如果指定了 callback,则将在请求流完成时调用它。

request.destroy([error])#

  • error <Error> 可选,一个随 'error' 事件发出的错误。
  • 返回: <this>

销毁请求。 可选地发出 'error' 事件,并发出 'close' 事件。 调用此方法将导致丢弃响应中的剩余数据并销毁套接字。

有关更多详细信息,请参见 writable.destroy()

request.destroyed#

在调用 request.destroy() 后为 true

有关更多详细信息,请参见 writable.destroyed

request.finished#

稳定性: 0 - 已弃用。 请使用 request.writableEnded

如果调用了 request.end(),则 request.finished 属性将为 true。 如果请求是通过 http.get() 发起的,则会自动调用 request.end()

request.flushHeaders()#

刷新请求头。

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

这通常是理想的(它可以节省一个 TCP 往返),但如果直到稍后才发送第一个数据,则并非如此。 request.flushHeaders() 绕过此优化并启动请求。

request.getHeader(name)#

读取请求上的标头。 名称不区分大小写。 返回值的类型取决于提供给 request.setHeader() 的参数。

request.setHeader('content-type', 'text/html');
request.setHeader('Content-Length', Buffer.byteLength(body));
request.setHeader('Cookie', ['type=ninja', 'language=javascript']);
const contentType = request.getHeader('Content-Type');
// 'contentType' is 'text/html'
const contentLength = request.getHeader('Content-Length');
// 'contentLength' is of type number
const cookie = request.getHeader('Cookie');
// 'cookie' is of type string[] 

request.getHeaderNames()#

返回一个数组,其中包含当前传出标头的唯一名称。 所有标头名称都是小写的。

request.setHeader('Foo', 'bar');
request.setHeader('Cookie', ['foo=bar', 'bar=baz']);

const headerNames = request.getHeaderNames();
// headerNames === ['foo', 'cookie'] 

request.getHeaders()#

返回当前传出标头的浅拷贝。 由于使用了浅拷贝,因此可以改变数组值,而无需额外调用各种与标头相关的 http 模块方法。 返回对象的键是标头名称,值是相应的标头值。 所有标头名称都是小写的。

request.getHeaders() 方法返回的对象从 JavaScript Object 原型继承。 这意味着典型的 Object 方法,例如 obj.toString()obj.hasOwnProperty() 等,未定义,并且将不起作用

request.setHeader('Foo', 'bar');
request.setHeader('Cookie', ['foo=bar', 'bar=baz']);

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

request.getRawHeaderNames()#

返回一个数组,其中包含当前传出的原始标头的唯一名称。 标头名称以其精确的大小写形式返回。

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

const headerNames = request.getRawHeaderNames();
// headerNames === ['Foo', 'Set-Cookie'] 

request.hasHeader(name)#

如果由 name 标识的标头当前在传出标头中设置,则返回 true。 标头名称匹配不区分大小写。

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

request.maxHeadersCount#

限制最大响应标头计数。 如果设置为 0,则不应用限制。

request.path#

request.method#

request.host#

request.protocol#

request.removeHeader(name)#

删除已在 headers 对象中定义的标头。

request.removeHeader('Content-Type'); 

request.reusedSocket#

  • <boolean> 请求是否通过重用套接字发送。

当通过启用 keep-alive 的代理发送请求时,可能会重用底层套接字。 但是,如果服务器在不幸的时间关闭连接,客户端可能会遇到“ECONNRESET”错误。

import http from 'node:http';

// Server has a 5 seconds keep-alive timeout by default
http
  .createServer((req, res) => {
    res.write('hello\n');
    res.end();
  })
  .listen(3000);

setInterval(() => {
  // Adapting a keep-alive agent
  http.get('http://localhost:3000', { agent }, (res) => {
    res.on('data', (data) => {
      // Do nothing
    });
  });
}, 5000); // Sending request on 5s interval so it's easy to hit idle timeoutconst http = require('node:http');

// Server has a 5 seconds keep-alive timeout by default
http
  .createServer((req, res) => {
    res.write('hello\n');
    res.end();
  })
  .listen(3000);

setInterval(() => {
  // Adapting a keep-alive agent
  http.get('http://localhost:3000', { agent }, (res) => {
    res.on('data', (data) => {
      // Do nothing
    });
  });
}, 5000); // Sending request on 5s interval so it's easy to hit idle timeout

通过标记请求是否重用套接字,我们可以基于它进行自动错误重试。

import http from 'node:http';
const agent = new http.Agent({ keepAlive: true });

function retriableRequest() {
  const req = http
    .get('http://localhost:3000', { agent }, (res) => {
      // ...
    })
    .on('error', (err) => {
      // Check if retry is needed
      if (req.reusedSocket && err.code === 'ECONNRESET') {
        retriableRequest();
      }
    });
}

retriableRequest();const http = require('node:http');
const agent = new http.Agent({ keepAlive: true });

function retriableRequest() {
  const req = http
    .get('http://localhost:3000', { agent }, (res) => {
      // ...
    })
    .on('error', (err) => {
      // Check if retry is needed
      if (req.reusedSocket && err.code === 'ECONNRESET') {
        retriableRequest();
      }
    });
}

retriableRequest();

request.setHeader(name, value)#

为 headers 对象设置单个标头值。 如果此标头已存在于要发送的标头中,则其值将被替换。 在此处使用字符串数组以发送具有相同名称的多个标头。 非字符串值将未经修改地存储。 因此,request.getHeader() 可能会返回非字符串值。 但是,非字符串值将被转换为字符串以进行网络传输。

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

或者

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

当 value 是一个字符串时,如果它包含 latin1 编码之外的字符,则会抛出异常。

如果需要在 value 中传递 UTF-8 字符,请使用 RFC 8187 标准对 value 进行编码。

const filename = 'Rock 🎵.txt';
request.setHeader('Content-Disposition', `attachment; filename*=utf-8''${encodeURIComponent(filename)}`); 

request.setNoDelay([noDelay])#

一旦将套接字分配给此请求并连接,将调用 socket.setNoDelay()

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

一旦将套接字分配给此请求并连接,将调用 socket.setKeepAlive()

request.setTimeout(timeout[, callback])#

一旦将套接字分配给此请求并连接,将调用 socket.setTimeout()

request.socket#

对底层套接字的引用。 通常,用户不希望访问此属性。 特别是,由于协议解析器如何附加到套接字,因此套接字不会发出 'readable' 事件。

import http from 'node:http';
const options = {
  host: 'www.google.com',
};
const req = http.get(options);
req.end();
req.once('response', (res) => {
  const ip = req.socket.localAddress;
  const port = req.socket.localPort;
  console.log(`Your IP address is ${ip} and your source port is ${port}.`);
  // Consume response object
});const http = require('node:http');
const options = {
  host: 'www.google.com',
};
const req = http.get(options);
req.end();
req.once('response', (res) => {
  const ip = req.socket.localAddress;
  const port = req.socket.localPort;
  console.log(`Your IP address is ${ip} and your source port is ${port}.`);
  // Consume response object
});

此属性保证是 <net.Socket> 类(<stream.Duplex> 的子类)的一个实例,除非用户指定了 <net.Socket> 以外的套接字类型。

request.uncork()#

参见 writable.uncork()

request.writableEnded#

在调用 request.end() 后为 true。 此属性不指示数据是否已刷新,为此请改用 request.writableFinished

request.writableFinished#

如果所有数据都已刷新到底层系统,则为 true,紧接在发出 'finish' 事件之前。

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

发送正文的一个块。 可以多次调用此方法。 如果未设置 Content-Length,则数据将自动以 HTTP 分块传输编码进行编码,以便服务器知道数据何时结束。 添加 Transfer-Encoding: chunked 标头。 调用 request.end() 是完成发送请求所必需的。

encoding 参数是可选的,仅当 chunk 是一个字符串时才适用。 默认为 'utf8'

callback 参数是可选的,并且仅当块为非空时,才会在刷新此数据块时调用。

如果整个数据已成功刷新到内核缓冲区,则返回 true。 如果全部或部分数据已在用户内存中排队,则返回 false。 当缓冲区再次空闲时,将发出 'drain'

当使用空字符串或缓冲区调用 write 函数时,它不执行任何操作并等待更多输入。

类: http.Server#

事件: 'checkContinue'#

每次收到带有 HTTP Expect: 100-continue 的请求时发出。 如果未侦听此事件,服务器将自动响应适当的 100 Continue

处理此事件包括在客户端应继续发送请求正文时调用 response.writeContinue(),或者在客户端不应继续发送请求正文时生成适当的 HTTP 响应(例如,400 Bad Request)。

当发出并处理此事件时,将不会发出 'request' 事件。

事件: 'checkExpectation'#

每次收到带有 HTTP Expect 头的请求,且其值不是 100-continue 时触发。如果未监听此事件,服务器将自动以适当的方式响应 417 Expectation Failed

当发出并处理此事件时,将不会发出 'request' 事件。

事件: 'clientError'#

如果客户端连接发出 'error' 事件,它将被转发到这里。 此事件的侦听器负责关闭/销毁底层套接字。 例如,人们可能希望使用自定义 HTTP 响应更优雅地关闭套接字,而不是突然断开连接。 套接字**必须在侦听器结束之前关闭或销毁**。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

默认行为是尝试使用 HTTP '400 Bad Request' 关闭套接字,或者在 HPE_HEADER_OVERFLOW 错误的情况下使用 HTTP '431 Request Header Fields Too Large' 关闭套接字。 如果套接字不可写或当前附加的 http.ServerResponse 的标头已发送,则会立即销毁。

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

import http from 'node: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);const http = require('node: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 响应消息。

errError 的实例,带有两个额外的列

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

在某些情况下,客户端已经收到响应和/或套接字已经被销毁,例如在 ECONNRESET 错误的情况下。 在尝试向套接字发送数据之前,最好检查它是否仍然可写。

server.on('clientError', (err, socket) => {
  if (err.code === 'ECONNRESET' || !socket.writable) {
    return;
  }

  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
}); 

事件: 'close'#

服务器关闭时触发。

事件: 'connect'#

每次客户端请求 HTTP CONNECT 方法时触发。 如果未监听此事件,则请求 CONNECT 方法的客户端将关闭其连接。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

发出此事件后,请求的套接字将没有 'data' 事件侦听器,这意味着需要绑定它才能处理在该套接字上发送到服务器的数据。

事件: 'connection'#

当建立新的 TCP 流时,会触发此事件。 socket 通常是 net.Socket 类型的对象。 通常,用户不希望访问此事件。 特别是,由于协议解析器附加到套接字的方式,套接字不会发出 'readable' 事件。 也可以在 request.socket 访问 socket

用户也可以显式地发出此事件以将连接注入到 HTTP 服务器中。 在这种情况下,可以传递任何 Duplex 流。

如果在此处调用 socket.setTimeout(),则当套接字服务于请求时,超时将替换为 server.keepAliveTimeout(如果 server.keepAliveTimeout 非零)。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

事件: 'dropRequest'#

当套接字上的请求数达到 server.maxRequestsPerSocket 的阈值时,服务器将丢弃新请求并发出 'dropRequest' 事件,然后向客户端发送 503

事件: 'request'#

每次有请求时触发。 每个连接可能有多个请求(在 HTTP Keep-Alive 连接的情况下)。

事件: 'upgrade'#

每次客户端请求 HTTP 升级时触发。 监听此事件是可选的,客户端不能坚持协议更改。

发出此事件后,请求的套接字将没有 'data' 事件侦听器,这意味着需要绑定它才能处理在该套接字上发送到服务器的数据。

保证此事件传递一个 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了除 <net.Socket> 之外的套接字类型。

server.close([callback])#

停止服务器接受新连接,并关闭所有连接到此服务器的未发送请求或等待响应的连接。 请参见 net.Server.close()

const http = require('node:http');

const server = http.createServer({ keepAliveTimeout: 60000 }, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);
// Close the server after 10 seconds
setTimeout(() => {
  server.close(() => {
    console.log('server on port 8000 closed successfully');
  });
}, 10000); 

server.closeAllConnections()#

关闭连接到此服务器的所有已建立的 HTTP(S) 连接,包括连接到此服务器的发送请求或等待响应的活动连接。 这*不会*销毁升级到不同协议的套接字,例如 WebSocket 或 HTTP/2。

这是一种强制关闭所有连接的方式,应谨慎使用。 当与 server.close 结合使用时,建议在调用 server.close*之后*调用此方法,以避免在此调用和调用 server.close 之间创建新连接的竞争条件。

const http = require('node:http');

const server = http.createServer({ keepAliveTimeout: 60000 }, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);
// Close the server after 10 seconds
setTimeout(() => {
  server.close(() => {
    console.log('server on port 8000 closed successfully');
  });
  // Closes all connections, ensuring the server closes successfully
  server.closeAllConnections();
}, 10000); 

server.closeIdleConnections()#

关闭连接到此服务器的所有未发送请求或等待响应的连接。

从 Node.js 19.0.0 开始,无需结合 server.close 调用此方法来回收 keep-alive 连接。 使用它不会造成任何危害,并且它可以用于确保需要支持 19.0.0 之前版本的库和应用程序的向后兼容性。 当与 server.close 结合使用时,建议在调用 server.close*之后*调用此方法,以避免在此调用和调用 server.close 之间创建新连接的竞争条件。

const http = require('node:http');

const server = http.createServer({ keepAliveTimeout: 60000 }, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);
// Close the server after 10 seconds
setTimeout(() => {
  server.close(() => {
    console.log('server on port 8000 closed successfully');
  });
  // Closes idle connections, such as keep-alive connections. Server will close
  // once remaining active connections are terminated
  server.closeIdleConnections();
}, 10000); 

server.headersTimeout#

限制解析器等待接收完整 HTTP 标头的时间量。

如果超时到期,服务器将响应状态 408,而不将请求转发到请求侦听器,然后关闭连接。

必须将其设置为非零值(例如 120 秒),以防止潜在的拒绝服务攻击,以防服务器在前面没有反向代理的情况下部署。

server.listen()#

启动 HTTP 服务器以侦听连接。 此方法与 net.Server.listen() 来自 net.Server 完全相同。

server.listening#

  • <boolean> 指示服务器是否正在侦听连接。

server.maxHeadersCount#

限制最大传入标头计数。 如果设置为 0,则不应用限制。

server.requestTimeout#

设置从客户端接收整个请求的超时值(以毫秒为单位)。

如果超时到期,服务器将响应状态 408,而不将请求转发到请求侦听器,然后关闭连接。

必须将其设置为非零值(例如 120 秒),以防止潜在的拒绝服务攻击,以防服务器在前面没有反向代理的情况下部署。

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

设置套接字的超时值,并在 Server 对象上发出 'timeout' 事件,如果发生超时,则将套接字作为参数传递。

如果 Server 对象上存在 'timeout' 事件侦听器,则将使用超时的套接字作为参数调用它。

默认情况下,Server 不会对套接字进行超时。 但是,如果将回调分配给 Server 的 'timeout' 事件,则必须显式处理超时。

server.maxRequestsPerSocket#

  • <number> 每个套接字的请求数。默认值: 0 (无限制)

在关闭保持连接之前,套接字可以处理的最大请求数。

值为 0 将禁用此限制。

当达到限制时,它会将 Connection 标头值设置为 close,但实际上不会关闭连接,达到限制后发送的后续请求将收到 503 Service Unavailable 作为响应。

server.timeout#

  • <number> 超时时间,以毫秒为单位。默认值: 0 (无超时)

在假定套接字超时之前的不活动毫秒数。

值为 0 将禁用传入连接的超时行为。

套接字超时逻辑是在连接时设置的,因此更改此值只会影响到服务器的新连接,而不会影响到任何现有连接。

server.keepAliveTimeout#

  • <number> 超时时间,以毫秒为单位。默认值: 5000 (5 秒).

服务器在完成写入最后一个响应后,需要等待额外传入数据的不活动毫秒数,超过这个时间后套接字将被销毁。 如果服务器在 keep-alive 超时触发之前收到新数据,它将重置常规的不活动超时,即 server.timeout

值为 0 将禁用传入连接的 keep-alive 超时行为。 值为 0 会使 http 服务器的行为类似于 Node.js 8.0.0 之前的版本,这些版本没有 keep-alive 超时。

套接字超时逻辑是在连接时设置的,因此更改此值只会影响到服务器的新连接,而不会影响到任何现有连接。

server[Symbol.asyncDispose]()#

稳定性: 1 - 实验性

调用 server.close() 并返回一个 promise,该 promise 在服务器关闭时兑现。

类: http.ServerResponse#

此对象由 HTTP 服务器在内部创建,而不是由用户创建。 它作为第二个参数传递给 'request' 事件。

事件: 'close'#

指示响应已完成,或者其底层连接已提前终止(在响应完成之前)。

事件: 'finish'#

当响应已发送时触发。 更具体地说,当响应标头和正文的最后一个段已传递给操作系统以通过网络传输时,会触发此事件。 这并不意味着客户端已经收到任何东西。

response.addTrailers(headers)#

此方法将 HTTP 尾部标头(一种标头,但位于消息的末尾)添加到响应中。

只有在响应使用分块编码时,才会发出尾部;如果不是(例如,如果请求是 HTTP/1.0),它们将被静默丢弃。

HTTP 要求发送 Trailer 标头才能发出尾部,并在其值中包含标头字段的列表。 例如,

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

尝试设置包含无效字符的标头字段名称或值将导致 TypeError 被抛出。

response.connection#

稳定性: 0 - 已弃用。 请使用 response.socket

请参阅 response.socket

response.cork()#

参见 writable.cork()

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

此方法向服务器发出信号,表明所有响应标头和正文都已发送; 该服务器应将此消息视为已完成。 必须在每个响应上调用 response.end() 方法。

如果指定了 data,则其效果类似于调用 response.write(data, encoding),然后调用 response.end(callback)

如果指定了 callback,则会在响应流完成时调用它。

response.finished#

稳定性: 0 - 已弃用。 请使用 response.writableEnded

如果已调用 response.end(),则 response.finished 属性将为 true

response.flushHeaders()#

刷新响应头。 另请参阅:request.flushHeaders()

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 is 'text/html'
const contentLength = response.getHeader('Content-Length');
// contentLength is of type number
const setCookie = response.getHeader('set-cookie');
// setCookie is of type string[] 

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.req#

对原始 HTTP request 对象的引用。

response.sendDate#

如果为 true,则如果 Date 标头尚未出现在标头中,则会自动生成该标头并将其发送到响应中。 默认为 true。

仅应禁用此功能以进行测试; HTTP 要求响应中包含 Date 标头。

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() 的标头具有优先权。

// 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.writeHead() 方法并且尚未调用此方法,它将直接将提供的标头值写入到网络通道,而无需在内部缓存,并且 response.getHeader() 在标头上不会产生预期的结果。 如果需要逐步填充具有潜在未来检索和修改的标头,请使用 response.setHeader() 代替 response.writeHead()

response.setTimeout(msecs[, callback])#

将套接字的超时值设置为 msecs。 如果提供了回调,则将其作为侦听器添加到响应对象上的 'timeout' 事件。

如果未将 'timeout' 侦听器添加到请求、响应或服务器,则套接字会在超时时被销毁。 如果将处理程序分配给请求、响应或服务器的 'timeout' 事件,则必须显式处理超时的套接字。

response.socket#

引用底层套接字。 通常,用户不希望访问此属性。 特别是,由于协议解析器附加到套接字的方式,因此套接字不会发出 'readable' 事件。 在 response.end() 之后,该属性为空。

import http from 'node:http';
const server = http.createServer((req, res) => {
  const ip = res.socket.remoteAddress;
  const port = res.socket.remotePort;
  res.end(`Your IP address is ${ip} and your source port is ${port}.`);
}).listen(3000);const http = require('node:http');
const server = http.createServer((req, res) => {
  const ip = res.socket.remoteAddress;
  const port = res.socket.remotePort;
  res.end(`Your IP address is ${ip} and your source port is ${port}.`);
}).listen(3000);

此属性保证是 <net.Socket> 类(<stream.Duplex> 的子类)的一个实例,除非用户指定了 <net.Socket> 以外的套接字类型。

response.statusCode#

当使用隐式标头(未显式调用 response.writeHead())时,此属性控制在刷新标头时将发送给客户端的状态码。

response.statusCode = 404; 

在将响应标头发送到客户端后,此属性指示已发送的状态码。

response.statusMessage#

当使用隐式标头(未显式调用 response.writeHead())时,此属性控制在刷新标头时将发送给客户端的状态消息。 如果将其保留为 undefined,则将使用状态码的标准消息。

response.statusMessage = 'Not found'; 

在将响应标头发送到客户端后,此属性指示已发送的状态消息。

response.strictContentLength#

如果设置为 true,Node.js 将检查 Content-Length 标头值和正文的大小(以字节为单位)是否相等。 如果 Content-Length 标头值不匹配,将抛出一个 Error,其 code:'ERR_HTTP_CONTENT_LENGTH_MISMATCH'

response.uncork()#

参见 writable.uncork()

response.writableEnded#

response.end() 被调用后为 true。 此属性不指示数据是否已被刷新,为此请使用 response.writableFinished 代替。

response.writableFinished#

如果所有数据都已刷新到底层系统,则为 true,紧接在发出 'finish' 事件之前。

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

如果调用此方法并且尚未调用 response.writeHead(),则它将切换到隐式标头模式并刷新隐式标头。

这会发送响应正文的一个块。 可以多次调用此方法以提供正文的后续部分。

如果在 createServer 中将 rejectNonStandardBodyWrites 设置为 true,则当请求方法或响应状态不支持内容时,不允许写入正文。 如果尝试为 HEAD 请求或作为 204304 响应的一部分写入正文,则会同步抛出一个代码为 ERR_HTTP_BODY_NOT_ALLOWEDError

chunk 可以是字符串或缓冲区。 如果 chunk 是字符串,则第二个参数指定如何将其编码为字节流。 当此数据块被刷新时,将调用 callback

这是原始的 HTTP 正文,与可能使用的高级多部分正文编码无关。

第一次调用 response.write() 时,它会将缓冲的标头信息和正文的第一个块发送到客户端。 第二次调用 response.write() 时,Node.js 假定数据将被流式传输,并单独发送新数据。 也就是说,响应会缓冲到正文的第一个块。

如果整个数据已成功刷新到内核缓冲区,则返回 true。 如果全部或部分数据已在用户内存中排队,则返回 false。 当缓冲区再次空闲时,将发出 'drain'

response.writeContinue()#

向客户端发送 HTTP/1.1 100 Continue 消息,表明应发送请求正文。 请参阅 Server 上的 'checkContinue' 事件。

response.writeEarlyHints(hints[, callback])#

向客户端发送 HTTP/1.1 103 Early Hints 消息,其中包含 Link 标头,指示用户代理可以预加载/预连接链接的资源。 hints 是一个对象,其中包含要与早期提示消息一起发送的标头的值。 可选的 callback 参数将在响应消息写入后调用。

例子

const earlyHintsLink = '</styles.css>; rel=preload; as=style';
response.writeEarlyHints({
  'link': earlyHintsLink,
});

const earlyHintsLinks = [
  '</styles.css>; rel=preload; as=style',
  '</scripts.js>; rel=preload; as=script',
];
response.writeEarlyHints({
  'link': earlyHintsLinks,
  'x-trace-id': 'id for diagnostics',
});

const earlyHintsCallback = () => console.log('early hints message sent');
response.writeEarlyHints({
  'link': earlyHintsLinks,
}, earlyHintsCallback); 

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

向请求发送响应标头。 状态码是一个 3 位 HTTP 状态码,例如 404。 最后一个参数 headers 是响应标头。 (可选)可以提供人类可读的 statusMessage 作为第二个参数。

headers 可以是一个 Array,其中键和值在同一个列表中。 它不是元组列表。 因此,偶数偏移量是键值,奇数偏移量是关联的值。 数组的格式与 request.rawHeaders 相同。

返回对 ServerResponse 的引用,以便可以链式调用。

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

此方法只能在消息上调用一次,并且必须在调用 response.end() 之前调用它。

如果在调用此方法之前调用了 response.write()response.end(),则将计算隐式/可变标头并调用此函数。

当使用 response.setHeader() 设置标头时,它们将与传递给 response.writeHead() 的任何标头合并,并且传递给 response.writeHead() 的标头具有优先权。

如果调用此方法并且尚未调用 response.setHeader(),它将直接将提供的标头值写入网络通道,而不会在内部进行缓存,并且标头上的 response.getHeader() 将不会产生预期的结果。 如果希望逐步填充标头以及潜在的未来检索和修改,请改用 response.setHeader()

// 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 以字节为单位读取,而不是字符。 使用 Buffer.byteLength() 确定正文的长度(以字节为单位)。 Node.js 将检查 Content-Length 和已传输的正文的长度是否相等。

尝试设置包含无效字符的标头字段名称或值将导致抛出 [Error][]。

response.writeProcessing()#

向客户端发送 HTTP/1.1 102 Processing 消息,表明应发送请求正文。

类: http.IncomingMessage#

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

与作为 <stream.Duplex> 的子类的其 socket 值不同,IncomingMessage 本身继承自 <stream.Readable>,并且是单独创建的,用于解析和发出传入的 HTTP 标头和有效负载,因为在保持活动状态的情况下,底层套接字可能会被多次重复使用。

事件: 'aborted'#

稳定性: 0 - 已弃用。 请改为监听 'close' 事件。

当请求已中止时发出。

事件: 'close'#

当请求已完成时发出。

message.aborted#

稳定性: 0 - 已弃用。 从 <stream.Readable> 检查 message.destroyed

如果请求已中止,则 message.aborted 属性将为 true

message.complete#

如果已接收并成功解析完整的 HTTP 消息,则 message.complete 属性将为 true

此属性特别有用,可用于确定客户端或服务器是否在连接终止之前完全传输了消息

const req = http.request({
  host: '127.0.0.1',
  port: 8080,
  method: 'POST',
}, (res) => {
  res.resume();
  res.on('end', () => {
    if (!res.complete)
      console.error(
        'The connection was terminated while the message was still being sent');
  });
}); 

message.connection#

稳定性: 0 - 已弃用。 使用 message.socket

message.socket 的别名。

message.destroy([error])#

在接收 IncomingMessage 的套接字上调用 destroy()。 如果提供了 error,则会在套接字上发出 'error' 事件,并且 error 会作为参数传递给事件上的任何侦听器。

message.headers#

请求/响应标头对象。

标头名称和值的键值对。 标头名称是小写的。

// Prints something like:
//
// { '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-afterserveruser-agent 的重复项将被丢弃。要允许将上面列出的请求头的重复值合并,请在 http.request()http.createServer() 中使用 joinDuplicateHeaders 选项。更多信息请参见 RFC 9110 第 5.3 节。
  • set-cookie 始终是一个数组。重复项会添加到该数组中。
  • 对于重复的 cookie 请求头,这些值将使用 ; 连接在一起。
  • 对于所有其他请求头,这些值将使用 , 连接在一起。

message.headersDistinct#

类似于 message.headers,但是没有合并逻辑,并且值始终是字符串数组,即使是只收到一次的请求头也是如此。

// Prints something like:
//
// { 'user-agent': ['curl/7.22.0'],
//   host: ['127.0.0.1:8000'],
//   accept: ['*/*'] }
console.log(request.headersDistinct); 

message.httpVersion#

如果是服务器请求,则是客户端发送的 HTTP 版本。如果是客户端响应,则是连接到的服务器的 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#

原始的请求/响应尾部键和值,与接收到的完全一致。仅在 'end' 事件时填充。

message.setTimeout(msecs[, callback])#

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

message.socket#

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

对于 HTTPS 支持,请使用 request.socket.getPeerCertificate() 来获取客户端的身份验证详细信息。

此属性保证是 <net.Socket> 类的实例,它是 <stream.Duplex> 的子类,除非用户指定了 <net.Socket> 以外的套接字类型,或者在内部将其置空。

message.statusCode#

仅对从 http.ClientRequest 获取的响应有效。

3 位数的 HTTP 响应状态码。例如,404

message.statusMessage#

仅对从 http.ClientRequest 获取的响应有效。

HTTP 响应状态消息(原因短语)。例如,OKInternal Server Error

message.trailers#

请求/响应尾部对象。仅在 'end' 事件时填充。

message.trailersDistinct#

类似于 message.trailers,但是没有合并逻辑,并且值始终是字符串数组,即使是只收到一次的请求头也是如此。仅在 'end' 事件时填充。

message.url#

仅对从 http.Server 获取的请求有效。

请求 URL 字符串。这仅包含实际 HTTP 请求中存在的 URL。采取以下请求

GET /status?name=ryan HTTP/1.1
Accept: text/plain 

要将 URL 解析为各个部分

new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`); 

request.url'/status?name=ryan'process.env.HOST 未定义时

$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
  href: 'http://localhost/status?name=ryan',
  origin: 'http://localhost',
  protocol: 'http:',
  username: '',
  password: '',
  host: 'localhost',
  hostname: 'localhost',
  port: '',
  pathname: '/status',
  search: '?name=ryan',
  searchParams: URLSearchParams { 'name' => 'ryan' },
  hash: ''
} 

请确保将 process.env.HOST 设置为服务器的主机名,或者考虑完全替换此部分。如果使用 req.headers.host,请确保使用正确的验证,因为客户端可以指定自定义的 Host 请求头。

类: http.OutgoingMessage#

此类充当 http.ClientRequesthttp.ServerResponse 的父类。从 HTTP 事务参与者的角度来看,它是一个抽象的传出消息。

事件: 'drain'#

当消息的缓冲区再次空闲时发出。

事件: 'finish'#

当传输成功完成时发出。

事件: 'prefinish'#

在调用 outgoingMessage.end() 之后发出。当发出该事件时,所有数据都已处理,但不一定完全刷新。

outgoingMessage.addTrailers(headers)#

将 HTTP 尾部(请求头,但在消息的末尾)添加到消息中。

仅当消息是分块编码时,才会发出尾部。否则,尾部将被静默丢弃。

HTTP 要求发送 Trailer 请求头以发出尾部,其值中包含请求头字段名称的列表,例如:

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

尝试设置包含无效字符的请求头字段名称或值将导致抛出 TypeError

outgoingMessage.appendHeader(name, value)#

将单个请求头值附加到请求头对象。

如果该值是一个数组,则等效于多次调用此方法。

如果请求头之前没有值,则等效于调用 outgoingMessage.setHeader(name, value)

根据创建客户端请求或服务器时 options.uniqueHeaders 的值,这最终会导致请求头被多次发送,或者使用 ; 连接值来发送一次。

outgoingMessage.connection#

稳定性: 0 - 已弃用: 请改用 outgoingMessage.socket

outgoingMessage.socket 的别名。

outgoingMessage.cork()#

参见 writable.cork()

outgoingMessage.destroy([error])#

  • error <Error> 可选,要随 error 事件发出的错误
  • 返回: <this>

销毁消息。一旦套接字与消息关联并连接,该套接字也将被销毁。

outgoingMessage.end(chunk[, encoding][, callback])#

完成传出消息。如果主体的任何部分未发送,它会将它们刷新到基础系统。如果消息是分块的,它将发送终止块 0\r\n\r\n,并发送尾部(如果有)。

如果指定了 chunk,则等效于调用 outgoingMessage.write(chunk, encoding),然后调用 outgoingMessage.end(callback)

如果提供了 callback,则将在消息完成时调用它(等效于 'finish' 事件的侦听器)。

outgoingMessage.flushHeaders()#

刷新消息头。

出于效率原因,Node.js 通常会缓冲消息头,直到调用 outgoingMessage.end() 或写入消息数据的第一个块。 然后,它尝试将请求头和数据打包到单个 TCP 数据包中。

通常需要这样做(它可以节省 TCP 往返),但当第一个数据直到稍后才发送时则不是。 outgoingMessage.flushHeaders() 绕过优化并启动消息。

outgoingMessage.getHeader(name)#

获取具有给定名称的 HTTP 请求头的值。如果未设置该请求头,则返回的值将为 undefined

outgoingMessage.getHeaderNames()#

返回一个数组,其中包含当前传出请求头的唯一名称。 所有名称均为小写。

outgoingMessage.getHeaders()#

返回当前传出标头的浅拷贝。 由于使用了浅拷贝,因此可以修改数组值,而无需额外调用各种与标头相关的 HTTP 模块方法。 返回对象的键是标头名称,值是相应的标头值。 所有标头名称均为小写。

outgoingMessage.getHeaders() 方法返回的对象并非从 JavaScript Object 原型继承。 这意味着典型的 Object 方法,例如 obj.toString()obj.hasOwnProperty() 等未定义,将无法使用。

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

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

outgoingMessage.hasHeader(name)#

如果传出标头中当前设置了由 name 标识的标头,则返回 true。 标头名称不区分大小写。

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

outgoingMessage.headersSent#

只读。 如果已发送标头,则为 true,否则为 false

outgoingMessage.pipe()#

覆盖了从传统 Stream 类继承的 stream.pipe() 方法,该类是 http.OutgoingMessage 的父类。

调用此方法将抛出 Error,因为 outgoingMessage 是一个只写流。

outgoingMessage.removeHeader(name)#

删除已排队以进行隐式发送的标头。

outgoingMessage.removeHeader('Content-Encoding'); 

outgoingMessage.setHeader(name, value)#

设置单个标头值。 如果标头已存在于要发送的标头中,则其值将被替换。 使用字符串数组以发送具有相同名称的多个标头。

outgoingMessage.setHeaders(headers)#

为隐式标头设置多个标头值。 headers 必须是 HeadersMap 的实例,如果标头已存在于要发送的标头中,则其值将被替换。

const headers = new Headers({ foo: 'bar' });
outgoingMessage.setHeaders(headers); 

或者

const headers = new Map([['foo', 'bar']]);
outgoingMessage.setHeaders(headers); 

使用 outgoingMessage.setHeaders() 设置标头后,它们将与传递给 response.writeHead() 的任何标头合并,传递给 response.writeHead() 的标头具有优先权。

// Returns content-type = text/plain
const server = http.createServer((req, res) => {
  const headers = new Headers({ 'Content-Type': 'text/html' });
  res.setHeaders(headers);
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
}); 

outgoingMessage.setTimeout(msesc[, callback])#

  • msesc <number>
  • callback <Function> 发生超时时要调用的可选函数。 与绑定到 timeout 事件相同。
  • 返回: <this>

一旦套接字与消息关联并已连接,将使用 msecs 作为第一个参数调用 socket.setTimeout()

outgoingMessage.socket#

对底层套接字的引用。 通常,用户不希望访问此属性。

调用 outgoingMessage.end() 后,此属性将为 null。

outgoingMessage.uncork()#

请参阅 writable.uncork()

outgoingMessage.writableCorked#

已调用 outgoingMessage.cork() 的次数。

outgoingMessage.writableEnded#

如果已调用 outgoingMessage.end(),则为 true。 此属性不指示数据是否已刷新。 为此,请改用 message.writableFinished

outgoingMessage.writableFinished#

如果所有数据都已刷新到底层系统,则为 true

outgoingMessage.writableHighWaterMark#

如果已分配,则为底层套接字的 highWaterMark。 否则,当 writable.write() 开始返回 false 时,为默认缓冲区级别 (16384)。

outgoingMessage.writableLength#

缓冲的字节数。

outgoingMessage.writableObjectMode#

始终为 false

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

发送正文的块。 可以多次调用此方法。

仅当 chunk 是字符串时,encoding 参数才相关。 默认为 'utf8'

callback 参数是可选的,当此数据块刷新时将被调用。

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

http.METHODS#

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

http.STATUS_CODES#

所有标准 HTTP 响应状态代码以及每个代码的简短描述的集合。 例如,http.STATUS_CODES[404] === 'Not Found'

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

  • options <Object>

    • connectionsCheckingInterval:设置检查不完整请求中的请求和标头超时的间隔值(以毫秒为单位)。 默认值: 30000
    • headersTimeout:设置从客户端接收完整 HTTP 标头的超时值(以毫秒为单位)。 有关更多信息,请参阅 server.headersTimeout默认值: 60000
    • highWaterMark <number> 可选择覆盖所有 socketreadableHighWaterMarkwritableHighWaterMark。 这会影响 IncomingMessageServerResponsehighWaterMark 属性。 默认值: 请参阅 stream.getDefaultHighWaterMark()
    • insecureHTTPParser <boolean> 如果设置为 true,它将使用启用宽松标志的 HTTP 解析器。 应避免使用不安全的解析器。 有关更多信息,请参阅 --insecure-http-parser默认值: false
    • IncomingMessage <http.IncomingMessage> 指定要使用的 IncomingMessage 类。 用于扩展原始 IncomingMessage默认值: IncomingMessage
    • joinDuplicateHeaders <boolean> 如果设置为 true,则此选项允许使用逗号 (, ) 连接请求中多个标头的字段行值,而不是丢弃重复项。 有关更多信息,请参阅 message.headers默认值: false
    • keepAlive <boolean> 如果设置为 true,它将在收到新的传入连接后立即在套接字上启用 keep-alive 功能,类似于在 [socket.setKeepAlive([enable][, initialDelay])][socket.setKeepAlive(enable, initialDelay)] 中所做的操作。 默认值: false
    • keepAliveInitialDelay <number> 如果设置为正数,它将设置在空闲套接字上发送第一个 keepalive 探测之前的初始延迟。 默认值: 0
    • keepAliveTimeout:服务器在完成写入最后一个响应后需要等待其他传入数据的非活动毫秒数,之后套接字将被销毁。 有关更多信息,请参阅 server.keepAliveTimeout默认值: 5000
    • maxHeaderSize <number> 可选择覆盖此服务器接收的请求的 --max-http-header-size 的值,即请求标头的最大长度(以字节为单位)。 默认值: 16384 (16 KiB)。
    • noDelay <boolean> 如果设置为 true,它将在收到新的传入连接后立即禁用 Nagle 算法的使用。 默认值: true
    • requestTimeout:设置从客户端接收整个请求的超时值(以毫秒为单位)。 有关更多信息,请参阅 server.requestTimeout默认值: 300000
    • requireHostHeader <boolean> 如果设置为 true,它会强制服务器对任何缺少 Host 标头的 HTTP/1.1 请求消息(如规范所要求)响应 400(错误请求)状态代码。 默认值: true
    • ServerResponse <http.ServerResponse> 指定要使用的 ServerResponse 类。 用于扩展原始 ServerResponse默认值: ServerResponse
    • uniqueHeaders <Array> 应仅发送一次的响应标头的列表。 如果标头的值是一个数组,则这些项将使用 ; 连接。
    • rejectNonStandardBodyWrites <boolean> 如果设置为 true,则在写入没有正文的 HTTP 响应时会抛出错误。 默认值: false
  • requestListener <Function>

  • 返回: <http.Server>

返回 http.Server 的新实例。

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

import http from 'node:http';

// Create a local server to receive data from
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);const http = require('node:http');

// Create a local server to receive data from
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);
import http from 'node:http';

// Create a local server to receive data from
const server = http.createServer();

// Listen to the request event
server.on('request', (request, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);const http = require('node:http');

// Create a local server to receive data from
const server = http.createServer();

// Listen to the request event
server.on('request', (request, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);

http.get(options[, callback])#

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

由于大多数请求都是没有请求体的 GET 请求,Node.js 提供了这个方便的方法。此方法与 http.request() 的唯一区别是它默认将 method 设置为 GET 并自动调用 req.end()。 回调必须注意消费响应数据,原因在 http.ClientRequest 部分中说明。

callback 会被调用,并带有一个参数,该参数是 http.IncomingMessage 的一个实例。

JSON 获取示例

http.get('http://localhost:8000/', (res) => {
  const { statusCode } = res;
  const contentType = res.headers['content-type'];

  let error;
  // Any 2xx status code signals a successful response but
  // here we're only checking for 200.
  if (statusCode !== 200) {
    error = new Error('Request Failed.\n' +
                      `Status Code: ${statusCode}`);
  } else if (!/^application\/json/.test(contentType)) {
    error = new Error('Invalid content-type.\n' +
                      `Expected application/json but received ${contentType}`);
  }
  if (error) {
    console.error(error.message);
    // Consume response data to free up memory
    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(`Got error: ${e.message}`);
});

// Create a local server to receive data from
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000); 

http.globalAgent#

Agent 的全局实例,用作所有 HTTP 客户端请求的默认值。 通过启用 keepAlive 和 5 秒的 timeout,与默认的 Agent 配置不同。

http.maxHeaderSize#

只读属性,用于指定 HTTP 标头的最大允许大小(以字节为单位)。 默认为 16 KiB。 可以使用 --max-http-header-size 命令行选项进行配置。

可以通过传递 maxHeaderSize 选项来覆盖服务器和客户端请求的此设置。

http.request(options[, callback])#

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

  • url <string> | <URL>
  • options <Object>
    • agent <http.Agent> | <boolean> 控制 Agent 的行为。 可能的值
      • undefined (默认): 为此主机和端口使用 http.globalAgent
      • Agent 对象: 显式使用传入的 Agent
      • false: 导致使用具有默认值的新 Agent
    • auth <string> 用于计算 Authorization 标头的基本身份验证 ('user:password')。
    • createConnection <Function> 一个函数,用于在未使用 agent 选项时生成用于请求的套接字/流。 这可以用于避免创建自定义 Agent 类,仅为了覆盖默认的 createConnection 函数。 详情参见 agent.createConnection()。 任何 Duplex 流都是有效的返回值。
    • defaultPort <number> 协议的默认端口。 默认: 如果使用了 Agent,则为 agent.defaultPort,否则为 undefined
    • family <number> 解析 hosthostname 时要使用的 IP 地址族。 有效值为 46。 未指定时,将同时使用 IP v4 和 v6。
    • headers <Object> 包含请求头的对象。
    • hints <number> 可选的 dns.lookup() 提示
    • host <string> 要向其发出请求的服务器的域名或 IP 地址。 默认: 'localhost'
    • hostname <string> host 的别名。 为了支持 url.parse(),如果同时指定了 hosthostname,则将使用 hostname
    • insecureHTTPParser <boolean> 如果设置为 true,它将使用启用了宽松标志的 HTTP 解析器。 应该避免使用不安全的解析器。 参阅 --insecure-http-parser 了解更多信息。 默认: false
    • joinDuplicateHeaders <boolean> 它使用 , 连接请求中多个标头的字段行值,而不是丢弃重复项。 参阅 message.headers 了解更多信息。 默认: false
    • localAddress <string> 用于网络连接的本地接口。
    • localPort <number> 要连接的本地端口。
    • lookup <Function> 自定义查找函数。 默认: dns.lookup()
    • maxHeaderSize <number> 可选地覆盖 --max-http-header-size 的值(响应标头的最大长度,以字节为单位),以用于从服务器收到的响应。 默认: 16384 (16 KiB)。
    • method <string> 指定 HTTP 请求方法的字符串。 默认: 'GET'
    • path <string> 请求路径。 应该包含查询字符串(如果有)。 例如 '/index.html?page=12'。 当请求路径包含非法字符时,会抛出异常。 目前,仅拒绝空格,但将来可能会更改。 默认: '/'
    • port <number> 远程服务器的端口。 默认: 如果设置了 defaultPort,则为 defaultPort,否则为 80
    • protocol <string> 要使用的协议。 默认: 'http:'
    • setDefaultHeaders <boolean>: 指定是否自动添加默认标头,例如 ConnectionContent-LengthTransfer-EncodingHost。 如果设置为 false,则必须手动添加所有必要的标头。 默认为 true
    • setHost <boolean>: 指定是否自动添加 Host 标头。 如果提供,则此设置将覆盖 setDefaultHeaders。 默认为 true
    • signal <AbortSignal>: 可用于中止正在进行的请求的 AbortSignal。
    • socketPath <string> Unix 域套接字。 如果指定了 hostport 之一,则不能使用,因为它们指定了 TCP 套接字。
    • timeout <number>: 一个数字,指定套接字超时(以毫秒为单位)。 这将在连接套接字之前设置超时。
    • uniqueHeaders <Array> 一个请求标头列表,应该只发送一次。 如果标头的值是一个数组,则这些项目将使用 ; 连接。
  • callback <Function>
  • 返回: <http.ClientRequest>

socket.connect() 中的 options 也受支持。

Node.js 维护每个服务器的多个连接以进行 HTTP 请求。 此函数允许透明地发出请求。

url 可以是一个字符串或一个 URL 对象。 如果 url 是一个字符串,它会被 new URL() 自动解析。 如果它是一个 URL 对象,它将被自动转换为一个普通的 options 对象。

如果同时指定了 urloptions,则会将这些对象合并,options 属性优先。

可选的 callback 参数将作为 'response' 事件的一次性监听器添加。

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

import http from 'node:http';
import { Buffer } from 'node:buffer';

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

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

const 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.error(`problem with request: ${e.message}`);
});

// Write data to request body
req.write(postData);
req.end();const http = require('node:http');

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

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

const 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.error(`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' 标头将禁用默认的 chunked 编码。

  • 发送 'Expect' 头部会立即发送请求头。通常,当发送 'Expect: 100-continue' 时,应该同时设置超时和 'continue' 事件的监听器。更多信息请参见 RFC 2616 第 8.2.3 节。

  • 发送 Authorization 头部会覆盖使用 auth 选项来计算基本认证。

使用 URL 作为 options 的示例

const options = new URL('http://abc:[email protected]');

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

在一个成功的请求中,以下事件将按以下顺序发出

  • 'socket'
  • 'response'
    • 'data'res 对象上发出多次(如果响应体为空,例如在大多数重定向中,则不会发出 'data'
    • 'end'res 对象上发出
  • 'close'

如果发生连接错误,将发出以下事件

  • 'socket'
  • 'error'
  • 'close'

如果在收到响应之前过早关闭连接,将按以下顺序发出以下事件

  • 'socket'
  • 'error',错误消息为 'Error: socket hang up',代码为 'ECONNRESET'
  • 'close'

如果在收到响应之后过早关闭连接,将按以下顺序发出以下事件

  • 'socket'
  • 'response'
    • 'data'res 对象上发出多次
  • (连接在此处关闭)
  • 'aborted'res 对象上发出
  • 'close'
  • 'error'res 对象上发出,错误消息为 'Error: aborted',代码为 'ECONNRESET'
  • 'close'res 对象上发出

如果在分配 socket 之前调用了 req.destroy(),将按以下顺序发出以下事件

  • (此处调用了 req.destroy())
  • 'error',错误消息为 'Error: socket hang up',代码为 'ECONNRESET',或者调用 req.destroy() 时使用的错误
  • 'close'

如果在连接成功之前调用了 req.destroy(),将按以下顺序发出以下事件

  • 'socket'
  • (此处调用了 req.destroy())
  • 'error',错误消息为 'Error: socket hang up',代码为 'ECONNRESET',或者调用 req.destroy() 时使用的错误
  • 'close'

如果在收到响应之后调用了 req.destroy(),将按以下顺序发出以下事件

  • 'socket'
  • 'response'
    • 'data'res 对象上发出多次
  • (此处调用了 req.destroy())
  • 'aborted'res 对象上发出
  • 'close'
  • 'error'res 对象上发出,错误消息为 'Error: aborted',代码为 'ECONNRESET',或者调用 req.destroy() 时使用的错误
  • 'close'res 对象上发出

如果在分配 socket 之前调用了 req.abort(),将按以下顺序发出以下事件

  • (此处调用了 req.abort())
  • 'abort'
  • 'close'

如果在连接成功之前调用了 req.abort(),将按以下顺序发出以下事件

  • 'socket'
  • (此处调用了 req.abort())
  • 'abort'
  • 'error',错误消息为 'Error: socket hang up',代码为 'ECONNRESET'
  • 'close'

如果在收到响应之后调用了 req.abort(),将按以下顺序发出以下事件

  • 'socket'
  • 'response'
    • 'data'res 对象上发出多次
  • (此处调用了 req.abort())
  • 'abort'
  • 'aborted'res 对象上发出
  • 'error'res 对象上发出,错误消息为 'Error: aborted',代码为 'ECONNRESET'
  • 'close'
  • 'close'res 对象上发出

设置 timeout 选项或使用 setTimeout() 函数不会中止请求,也不会执行任何操作,除了添加一个 'timeout' 事件。

传递一个 AbortSignal,然后对相应的 AbortController 调用 abort(),其行为与对请求调用 .destroy() 相同。 具体来说,将发出 'error' 事件,其错误消息为 'AbortError: The operation was aborted',代码为 'ABORT_ERR',并具有 cause (如果已提供)。

http.validateHeaderName(name[, label])#

  • name <string>
  • label <string> 错误消息的标签。默认值: 'Header name'

对提供的 name 执行底层验证,这些验证在调用 res.setHeader(name, value) 时完成。

将非法值作为 name 传递将导致抛出一个 TypeError,并通过 code: 'ERR_INVALID_HTTP_TOKEN' 标识。

在将头部传递给 HTTP 请求或响应之前,无需使用此方法。HTTP 模块会自动验证此类头部。

例子

import { validateHeaderName } from 'node:http';

try {
  validateHeaderName('');
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code); // --> 'ERR_INVALID_HTTP_TOKEN'
  console.error(err.message); // --> 'Header name must be a valid HTTP token [""]'
}const { validateHeaderName } = require('node:http');

try {
  validateHeaderName('');
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code); // --> 'ERR_INVALID_HTTP_TOKEN'
  console.error(err.message); // --> 'Header name must be a valid HTTP token [""]'
}

http.validateHeaderValue(name, value)#

对提供的 value 执行底层验证,这些验证在调用 res.setHeader(name, value) 时完成。

将非法值作为 value 传递将导致抛出一个 TypeError

  • 未定义值错误通过 code: 'ERR_HTTP_INVALID_HEADER_VALUE' 标识。
  • 无效值字符错误通过 code: 'ERR_INVALID_CHAR' 标识。

在将头部传递给 HTTP 请求或响应之前,无需使用此方法。HTTP 模块会自动验证此类头部。

示例

import { validateHeaderValue } from 'node:http';

try {
  validateHeaderValue('x-my-header', undefined);
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'); // --> true
  console.error(err.message); // --> 'Invalid value "undefined" for header "x-my-header"'
}

try {
  validateHeaderValue('x-my-header', 'oʊmɪɡə');
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code === 'ERR_INVALID_CHAR'); // --> true
  console.error(err.message); // --> 'Invalid character in header content ["x-my-header"]'
}const { validateHeaderValue } = require('node:http');

try {
  validateHeaderValue('x-my-header', undefined);
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'); // --> true
  console.error(err.message); // --> 'Invalid value "undefined" for header "x-my-header"'
}

try {
  validateHeaderValue('x-my-header', 'oʊmɪɡə');
} catch (err) {
  console.error(err instanceof TypeError); // --> true
  console.error(err.code === 'ERR_INVALID_CHAR'); // --> true
  console.error(err.message); // --> 'Invalid character in header content ["x-my-header"]'
}

http.setMaxIdleHTTPParsers(max)#

设置空闲 HTTP 解析器的最大数量。

WebSocket#

与浏览器兼容的 WebSocket 实现。