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())。

Agent 实例不再使用时,最好 destroy() 它,因为未使用的套接字会消耗操作系统资源。

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

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 请求的套接字/流。

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

可以通过两种方式提供套接字/流:通过从此函数返回套接字/流,或者通过将套接字/流传递给 callback

除非用户指定了 <net.Socket> 以外的套接字类型,否则此方法保证返回 <net.Socket> 类(<stream.Duplex> 的子类)的实例。

callback 的签名是 (err, stream)

agent.keepSocketAlive(socket)#

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

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

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

socket 参数可以是 <net.Socket><stream.Duplex> 的子类)的一个实例。

agent.reuseSocket(socket, request)#

在由于保持活动选项而持久化之后,当 socket 连接到 request 时调用。默认行为是

socket.ref(); 

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

socket 参数可以是 <net.Socket><stream.Duplex> 的子类)的一个实例。

agent.destroy()#

销毁代理当前正在使用的任何套接字。

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

agent.freeSockets#

当启用 keepAlive 时,一个对象,其中包含当前正在等待代理使用的套接字数组。不要修改。

freeSockets 列表中的套接字将在 '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、证书、密码和其他确定套接字可重用性的 HTTPS/TLS 特定选项。

agent.maxFreeSockets#

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

agent.maxSockets#

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

agent.maxTotalSockets#

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

agent.requests#

一个对象,其中包含尚未分配给套接字的请求队列。不要修改。

agent.sockets#

一个对象,其中包含代理当前正在使用的套接字数组。不要修改。

类: 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 sockets、就地 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)#

读取请求上的一个 header。名称不区分大小写。返回值的类型取决于提供给 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()#

返回一个包含当前传出 header 的唯一名称的数组。所有 header 名称都是小写的。

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

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

request.getHeaders()#

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

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()#

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

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

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

request.hasHeader(name)#

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

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

request.maxHeadersCount#

限制最大响应 header 计数。 如果设置为 0,则不应用任何限制。

request.path#

request.method#

request.host#

request.protocol#

request.removeHeader(name)#

删除 headers 对象中已定义的 header。

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

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

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

如果该值是一个字符串,如果它包含 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 header。 调用 request.end() 是完成发送请求所必需的。

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

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

如果整个数据已成功刷新到内核缓冲区,则返回 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 中的 server.listen() 相同。

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 秒).

服务器在完成写入最后一个响应后需要等待其他传入数据的毫秒数,然后才能销毁套接字。 如果服务器在保持活动超时触发之前收到新数据,它将重置常规不活动超时,即 server.timeout

值为 0 将禁用传入连接的保持活动超时行为。 值为 0 使 http 服务器的行为类似于 Node.js 8.0.0 之前的版本,该版本没有保持活动超时。

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

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()#

返回一个包含当前传出 header 的唯一名称的数组。所有 header 名称都是小写的。

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

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

response.getHeaders()#

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

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)#

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

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 对象。

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

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])#

设置 Socket 的超时值为 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_ALLOWED 的同步 Error

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])#

使用 Link 标头向客户端发送 HTTP/1.1 103 Early Hints 消息,指示用户代理可以预加载/预连接链接的资源。 hints 是一个对象,包含要与 early 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 消息,指示应发送请求正文。

Class: http.IncomingMessage#

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

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

Event: '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 的 socket 上调用 destroy()。 如果提供了 error,则会在 socket 上触发 '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> 的子类,除非用户指定的 socket 类型不是 <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>

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

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>

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

outgoingMessage.socket#

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

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

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 并将 timeout 设置为 5 秒,从而与默认的 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> 基本身份验证 ('user:password') 以计算 Authorization 标头。
    • 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,否则为 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' 标头将禁用默认的块编码。

  • 发送 'Expect' 标头将立即发送请求标头。 通常,在发送 'Expect: 100-continue' 时,应该同时设置超时和 'continue' 事件的监听器。 有关更多信息,请参阅 RFC 2616 第 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'

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

  • 'socket'
  • 'error' 事件,带有消息 'Error: socket hang up' 和代码 'ECONNRESET' 的错误
  • 'close'

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

  • 'socket'
  • 'response'
    • res 对象上 'data' 事件会触发多次
  • (连接在此处关闭)
  • res 对象上 'aborted' 事件
  • 'close'
  • res 对象上 'error' 事件,带有消息 'Error: aborted' 和代码 'ECONNRESET' 的错误
  • res 对象上 'close' 事件

如果在分配套接字之前调用了 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'
    • res 对象上 'data' 事件会触发多次
  • (在此处调用了 req.destroy())
  • res 对象上 'aborted' 事件
  • 'close'
  • res 对象上 'error' 事件,带有消息 'Error: aborted' 和代码 'ECONNRESET' 的错误,或者调用 req.destroy() 时使用的错误
  • res 对象上 'close' 事件

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

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

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

  • 'socket'
  • (在此处调用了 req.abort())
  • 'abort'
  • 'error' 事件,带有消息 'Error: socket hang up' 和代码 'ECONNRESET' 的错误
  • 'close'

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

  • 'socket'
  • 'response'
    • res 对象上 'data' 事件会触发多次
  • (在此处调用了 req.abort())
  • 'abort'
  • res 对象上 'aborted' 事件
  • res 对象上 'error' 事件,带有消息 'Error: aborted' 和代码 'ECONNRESET'
  • 'close'
  • res 对象上 'close' 事件

设置 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 的浏览器兼容实现。