http.ClientRequest类


该对象在内部创建并由 http.request()。它表示着一个正在处理的请求,其头部已经进入请求队列。该头部仍可以很容易地通过 setHeader(name, value)getHeader(name)removeHeader(name) API 进行修改。实际头部将与第一数据块或关闭连接时一起被发送。

为了获得响应对象,将一个 'response' 监听器添加到请求对象上。当收到响应头时,请求对象会发出一个 'response' 事件。'response' 事件只有一个执行参数,该参数是一个 http.IncomingMessage 实例。

'response' 事件期间,可以为响应对象添加监听器;尤其是监听 'data' 事件。

如果没有添加 'response' 处理函数,那么响应会被完全忽略。然而,如果你添加了 'response' 处理函数,那么你必须消耗从响应对象中获得的数据,每当发生 'readable' 事件时调用 response.read(),或添加一个 'data' 处理函数,或通过调用 .resume() 方法。直到数据被消耗完之前,不会发生 'end' 事件。同样,如果数据未被读取,它将会消耗内存,最终产生 ‘process out of memory’ 错误。

注意:Node.js 不会检查 Content-Length 和已发送的 body 的长度是否相等。

该请求实现了 可写流 接口。这是一个包含下列事件的 EventEmitter

‘connect’ 事件

function (response, socket, head) { }

每当服务器响应一个带有 CONNECT 方法的请求时都会发生。如果没有监听该事件,客户端接收到 CONNECT 方法后会将有自己的连接关闭。

一对客户端和服务端组合会向你展示如何监听 'connect' 事件。

  1. const http = require('http');
  2. const net = require('net');
  3. const url = require('url');
  4. // Create an HTTP tunneling proxy
  5. var proxy = http.createServer((req, res) => {
  6. res.writeHead(200, {
  7. 'Content-Type': 'text/plain'
  8. });
  9. res.end('okay');
  10. });
  11. proxy.on('connect', (req, cltSocket, head) => {
  12. // connect to an origin server
  13. var srvUrl = url.parse(`http://${req.url}`);
  14. var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
  15. cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
  16. 'Proxy-agent: Node.js-Proxy\r\n' +
  17. '\r\n');
  18. srvSocket.write(head);
  19. srvSocket.pipe(cltSocket);
  20. cltSocket.pipe(srvSocket);
  21. });
  22. });
  23. // now that proxy is running
  24. proxy.listen(1337, '127.0.0.1', () => {
  25. // make a request to a tunneling proxy
  26. var options = {
  27. port: 1337,
  28. hostname: '127.0.0.1',
  29. method: 'CONNECT',
  30. path: 'www.google.com:80'
  31. };
  32. var req = http.request(options);
  33. req.end();
  34. req.on('connect', (res, socket, head) => {
  35. console.log('got connected!');
  36. // make a request over an HTTP tunnel
  37. socket.write('GET / HTTP/1.1\r\n' +
  38. 'Host: www.google.com:80\r\n' +
  39. 'Connection: close\r\n' +
  40. '\r\n');
  41. socket.on('data', (chunk) => {
  42. console.log(chunk.toString());
  43. });
  44. socket.on('end', () => {
  45. proxy.close();
  46. });
  47. });
  48. });

‘response’ 事件

function (response) { }

当收到该请求的响应时发生。该事件只发生一次。response 的参数会是一个 http.IncomingMessage 的实例。

‘socket’ 事件

function (socket) { }

在该请求分配到一个 socket 后发生。

‘continue’ 事件

function () { }

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

‘upgrade’ 事件

function (response, socket, head) { }

每当服务器响应一个升级请求时发生。如果没有监听该事件,客户端接收到一个升级头部后会将有自己的连接关闭。

一对客户端和服务端组合会向你展示如何监听 'upgrade' 事件。

  1. const http = require('http');
  2. // Create an HTTP server
  3. var srv = http.createServer((req, res) => {
  4. res.writeHead(200, {
  5. 'Content-Type': 'text/plain'
  6. });
  7. res.end('okay');
  8. });
  9. srv.on('upgrade', (req, socket, head) => {
  10. socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
  11. 'Upgrade: WebSocket\r\n' +
  12. 'Connection: Upgrade\r\n' +
  13. '\r\n');
  14. socket.pipe(socket); // echo back
  15. });
  16. // now that server is running
  17. srv.listen(1337, '127.0.0.1', () => {
  18. // make a request
  19. var options = {
  20. port: 1337,
  21. hostname: '127.0.0.1',
  22. headers: {
  23. 'Connection': 'Upgrade',
  24. 'Upgrade': 'websocket'
  25. }
  26. };
  27. var req = http.request(options);
  28. req.end();
  29. req.on('upgrade', (res, socket, upgradeHead) => {
  30. console.log('got upgraded!');
  31. socket.end();
  32. process.exit(0);
  33. });
  34. });

‘abort’ 事件

function () { }

当请求已经被客户端中止时发出。该事件只发生在第一次调用 abort()

‘checkExpectation’ 事件

function (request, response) { }

每当收到一个带有 http Expect ,但值不是 ‘100-continue’ 的请求头部时发生。如果没有监听该事件,服务器会自动响应一个适当的 417 Expectation Failed

注意,当事件发生和处理后,request 事件将不会发生。

request.setTimeout(timeout[, callback])

一旦 socket 被分配给该请求,关联的 socket.setTimeout() 会被调用。

  • timeout {Number} 请求被认为是超时的毫秒数。

  • callback {Function} 可选的,当发生超时时调用的函数。同样绑定到 timeout 事件。

request.setNoDelay([noDelay])

一旦 socket 被分配给该请求,关联的 socket.setNoDelay() 会被调用。

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

一旦 socket 被分配给该请求,关联的 socket.setKeepAlive() 会被调用。

request.flushHeaders()

强制刷新请求头。

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

这通常是你想要的(它节省了 TCP 往返),除了当第一个数据块直到很久之后才会被发送的情况。request.flushHeaders() 让你绕过优化并提前开始请求。

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

发送一个主体数据块。通过多次调用该方法,用户可以以流的形式将请求主体发送到服务器 —— 在这种情况下,当创建请求时,建议使用 ['Transfer-Encoding', 'chunked'] 头部行。

chunk 参数应该是一个 Buffer 或字符串。

encoding 参数是可选的,并仅适用于 chunk 是字符串的情况。默认为 'utf8'

callback 参数是可选的,并在数据块刷新时调用。

返回 request

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

完成发送请求。如果主体中的任何部分未被发送,它会将它们刷新流中。如果请求被分块,它将发送终止 '0\r\n\r\n'

如果指定了 data,这等同于在 request.end(callback) 之后调用 response.write(data, encoding)

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

request.abort()

标志着请求终止。调用该方法将导致剩余的响应数据被丢弃,并销毁 socket。