在线工具
网站地图    收藏    合作   
<

快捷菜单 返回顶部

node中文API-http超文本传输协议

http 超文本传输协议#

中英对照

稳定性: 2 - 稳定

源代码: lib/http.js

要使用 HTTP 服务器和客户端,则必须 require('http')

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 实例,因为未使用的套接字会消耗操作系统资源。

当套接字触发 'close' 事件或 'agentRemove' 事件时,则套接字将从代理中删除。 当打算让 HTTP 请求长时间打开而不将其保留在代理中时,可以执行类似以下的操作:

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

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

agent:false:

http.get({
  hostname: 'localhost',
  port: 80,
  path: '/',
  agent: false  // 仅为这个请求创建新代理
}, (res) => {
  // 使用响应做些事情
});

new Agent([options])#

中英对照

  • options <Object> 要在代理上设置的可配置选项集。 可以有以下字段:
    • keepAlive <boolean> 即使没有未完成的请求,也要保留套接字,这样它们就可以用于未来的请求,而无需重新建立 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.request() 使用的默认 http.globalAgent 将所有这些值设置为各自的默认值。

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

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

agent.createConnection(options[, callback])#

中英对照

生成用于 HTTP 请求的套接字/流。

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

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

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

callback 的参数为 (err, stream)

agent.keepSocketAlive(socket)#

中英对照

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

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

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

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'

Node.js 不会检查内容长度和已经传输的正文的长度是否相等。

'abort' 事件#

中英对照

稳定性: 0 - 弃用. Listen for 'close' event 。

当请求被客户端中止时触发。 此事件仅在第一次调用 abort() 时触发。

'connect' 事件#

中英对照

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

除非用户指定 <net.Socket> 以外的套接字类型,否则此事件保证传入 <net.Socket> 类(<stream.Duplex> 的子类)的实例。

演示如何监听 'connect' 事件的客户端和服务器对:

const http = require('http');
const net = require('net');
const { URL } = require('url');

// 创建 HTTP 隧道代理
const proxy = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('okay');
});
proxy.on('connect', (req, clientSocket, head) => {
  // 连接到源服务器
  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);
  });
});

// 现在代理正在运行
proxy.listen(1337, '127.0.0.1', () => {

  // 向隧道代理发出请求
  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!');

    // 通过 HTTP 隧道发出请求
    socket.write('GET / HTTP/1.1\r\n' +
                 'Host: www.google.com:80\r\n' +
                 'Connection: close\r\n' +
                 '\r\n');
    socket.on('data', (chunk) => {
      console.log(chunk.toString());
    });
    socket.on('end', () => {
      proxy.close();
    });
  });
});

'continue' 事件#

中英对照

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

'information' 事件#

中英对照

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

const http = require('http');

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

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

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

101 升级状态不会触发此事件,因为它们脱离了传统的 HTTP 请求/响应链,例如 Web 套接字、就地 TLS 升级或 HTTP 2.0。 要收到 101 升级通知,请改为监听 'upgrade' 事件。

'response' 事件#

中英对照

当接收到对此请求的响应时触发。 此事件仅触发一次。

'socket' 事件#

中英对照

除非用户指定 <net.Socket> 以外的套接字类型,否则此事件保证传入 <net.Socket> 类(<stream.Duplex> 的子类)的实例。

'timeout' 事件#

中英对照

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

另见: request.setTimeout()

'upgrade' 事件#

中英对照

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

除非用户指定 <net.Socket> 以外的套接字类型,否则此事件保证传入 <net.Socket> 类(<stream.Duplex> 的子类)的实例。

演示如何监听 'upgrade' 事件的客户端服务器对。

const http = require('http');

// 创建 HTTP 服务器
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); // 回声
});

// 现在该服务器正在运行
server.listen(1337, '127.0.0.1', () => {

  // 发出请求
  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 - 弃用. Check request.destroyed

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

request.connection#

中英对照

稳定性: 0 - 弃用. 改为使用 request.socket.

参见 request.socket

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' 是 'text/html'
const contentLength = request.getHeader('Content-Length');
// 'contentLength' 是数字类型
const cookie = request.getHeader('Cookie');
// 'cookie' 是 string[] 类型

request.getRawHeaderNames()#

中英对照

返回包含当前传出原始标头的唯一名称的数组。 标头名称返回并设置了它们的确切大小写。

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

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

request.maxHeadersCount#

中英对照

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

request.path#

中英对照

request.method#

中英对照

request.host#

中英对照

request.protocol#

中英对照

request.removeHeader(name)#

中英对照

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

request.removeHeader('Content-Type');

request.reusedSocket#

中英对照

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

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

const http = require('http');

// 服务器默认有 5 秒保持活动超时
http
  .createServer((req, res) => {
    res.write('hello\n');
    res.end();
  })
  .listen(3000);

setInterval(() => {
  // 调整保持活动代理
  http.get('http://localhost:3000', { agent }, (res) => {
    res.on('data', (data) => {
      // 什么都不做
    });
  });
}, 5000); // 以 5 秒的间隔发送请求,因此很容易达到空闲超时

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

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

function retriableRequest() {
  const req = http
    .get('http://localhost:3000', { agent }, (res) => {
      // ...
    })
    .on('error', (err) => {
      // 检查是否需要重试
      if (req.reusedSocket && err.code === 'ECONNRESET') {
        retriableRequest();
      }
    });
}

retriableRequest();

request.setHeader(name, value)#


自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com