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 仍然會向該伺服器發出請求,但每個請求都將透過一個新的連線進行。

當連線被客戶端或伺服器關閉時,它會從池中移除。池中任何未使用的套接字都將被取消引用(unrefed),這樣在沒有未完成請求時,Node.js 程序就不會保持執行。(參見 socket.unref())。

在不再使用 Agent 例項時,呼叫 destroy() 是一個好習慣,因為未使用的套接字會消耗作業系統資源。

當套接字發出 'close' 事件或 'agentRemove' 事件時,套接字會從代理中移除。如果打算長時間保持一個 HTTP 請求開啟而不將其保留在代理中,可以這樣做:

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

一個代理也可以用於單個請求。透過向 http.get()http.request() 函式提供 {agent: false} 作為選項,將為客戶端連線使用一個具有預設選項的一次性 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
    • agentKeepAliveTimeoutBuffer <number> 在確定套接字過期時間時,從伺服器提供的 keep-alive: timeout=... 提示中減去的毫秒數。這個緩衝有助於確保代理在伺服器關閉套接字之前稍微早一點關閉它,從而減少了在一個即將被伺服器關閉的套接字上傳送請求的機會。預設值: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> 套接字超時時間,單位為毫秒。這將在套接字建立時設定超時。
    • proxyEnv <Object> | <undefined> 用於代理配置的環境變數。詳情請見內建代理支援預設值:undefined
      • HTTP_PROXY <string> | <undefined> HTTP 請求應使用的代理伺服器 URL。如果未定義,HTTP 請求不使用代理。
      • HTTPS_PROXY <string> | <undefined> HTTPS 請求應使用的代理伺服器 URL。如果未定義,HTTPS 請求不使用代理。
      • NO_PROXY <string> | <undefined> 指定不應透過代理路由的端點的模式。
      • http_proxy <string> | <undefined>HTTP_PROXY 相同。如果兩者都設定了,http_proxy 優先。
      • https_proxy <string> | <undefined>HTTPS_PROXY 相同。如果兩者都設定了,https_proxy 優先。
      • no_proxy <string> | <undefined>NO_PROXY 相同。如果兩者都設定了,no_proxy 優先。
    • defaultPort <number> 當請求中未指定埠時使用的預設埠。預設值:80
    • protocol <string> 用於代理的協議。預設值:'http:'

也支援 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 子類覆蓋。如果此方法返回一個假值,套接字將被銷燬,而不是為下一次請求持久化。

socket 引數可以是 <net.Socket> 的例項,它是 <stream.Duplex> 的子類。

agent.reuseSocket(socket, request)#

socket 因為 keep-alive 選項被持久化後附加到 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 設定為 trueContent-Length 頭部值不匹配將導致丟擲一個 Error,其 code'ERR_HTTP_CONTENT_LENGTH_MISMATCH'

Content-Length 值應以位元組為單位,而不是字元。使用 Buffer.byteLength() 來確定主體的位元組長度。

事件:'abort'#

穩定性:0 - 已棄用。請改用監聽 'close' 事件。

當請求被客戶端中止時發出。此事件僅在第一次呼叫 abort() 時發出。

事件:'close'#

表示請求已完成,或者其底層連線在響應完成前被過早終止。

事件:'connect'#

每當伺服器以 CONNECT 方法響應請求時發出。如果未監聽此事件,接收到 CONNECT 方法的客戶端的連線將被關閉。

除非使用者指定了除 <net.Socket> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

一個演示如何監聽 '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 請求/響應鏈,例如 WebSocket、就地 TLS 升級或 HTTP 2.0。要接收 101 Upgrade 的通知,請改為監聽 'upgrade' 事件。

事件:'response'#

當收到對此請求的響應時發出。此事件僅發出一次。

事件:'socket'#

除非使用者指定了除 <net.Socket> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

事件:'timeout'#

當底層套接字因不活動而超時時發出。這隻通知套接字已處於空閒狀態。必須手動銷燬請求。

另請參閱:request.setTimeout()

事件:'upgrade'#

每當伺服器以升級響應請求時發出。如果未監聽此事件且響應狀態碼為 101 Switching Protocols,則接收到升級頭的客戶端連線將被關閉。

除非使用者指定了除 <net.Socket> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

一個演示如何監聽 '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)#

移除已在頭物件中定義的頭。

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('https://: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('https://: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('https://: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('https://:3000', { agent }, (res) => {
      // ...
    })
    .on('error', (err) => {
      // Check if retry is needed
      if (req.reusedSocket && err.code === 'ECONNRESET') {
        retriableRequest();
      }
    });
}

retriableRequest();

request.setHeader(name, value)#

為頭物件設定單個頭值。如果此頭已存在於待發送的頭中,其值將被替換。在此處使用字串陣列可以傳送多個同名的頭。非字串值將不加修改地儲存。因此,request.getHeader() 可能返回非字串值。但是,非字串值在網路傳輸時將被轉換為字串。

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

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

當值為字串時,如果它包含 latin1 編碼之外的字元,將丟擲異常。

如果需要在值中傳遞 UTF-8 字元,請使用 RFC 8187 標準對值進行編碼。

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> 之外的套接字型別,否則此屬性保證是 <net.Socket> 類(<stream.Duplex> 的子類)的例項。

request.uncork()#

參見 writable.uncork()

request.writableEnded#

在呼叫 request.end() 之後為 true。此屬性不表示資料是否已重新整理,請改用 request.writableFinished

request.writableFinished#

如果在發出 'finish' 事件之前,所有資料都已重新整理到底層系統,則為 true

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> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

預設行為是嘗試使用 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 響應訊息。

err 是一個 Error 例項,帶有兩個額外的列:

  • 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> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

此事件發出後,請求的套接字將不會有 'data' 事件監聽器,這意味著需要繫結它來處理傳送到該套接字上的伺服器的資料。

事件:'connection'#

當建立新的 TCP 流時,會發出此事件。socket 通常是 net.Socket 型別的物件。通常使用者不希望訪問此事件。特別是,由於協議解析器如何附加到套接字,套接字不會發出 'readable' 事件。也可以透過 request.socket 訪問 socket

此事件也可以由使用者顯式發出,以將連線注入 HTTP 伺服器。在這種情況下,可以傳遞任何 Duplex 流。

如果在此處呼叫 socket.setTimeout(),當套接字處理完一個請求後,超時將被替換為 server.keepAliveTimeout(如果 server.keepAliveTimeout 非零)。

除非使用者指定了除 <net.Socket> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

事件:'dropRequest'#

當套接字上的請求數達到 server.maxRequestsPerSocket 的閾值時,伺服器將丟棄新請求併發出 'dropRequest' 事件,然後向客戶端傳送 503

事件:'request'#

每次有請求時發出。每個連線可能有多個請求(在 HTTP Keep-Alive 連線的情況下)。

事件:'upgrade'#

每當客戶端的 HTTP 升級請求被接受時發出。預設情況下,所有 HTTP 升級請求都會被忽略(即只發出常規的 'request' 事件,遵循正常的 HTTP 請求/響應流程),除非您監聽此事件,在這種情況下,它們都會被接受(即會發出 'upgrade' 事件,未來的通訊必須直接透過原始套接字處理)。您可以透過使用伺服器的 shouldUpgradeCallback 選項來更精確地控制這一點。

監聽此事件是可選的,客戶端不能堅持協議更改。

此事件發出後,請求的套接字將不會有 'data' 事件監聽器,這意味著需要繫結它來處理傳送到該套接字上的伺服器的資料。

如果升級被 shouldUpgradeCallback 接受,但沒有註冊事件處理程式,則套接字將被銷燬,導致客戶端連線立即關閉。

除非使用者指定了除 <net.Socket> 之外的套接字型別,否則此事件保證傳遞一個 <net.Socket> 類的例項,該類是 <stream.Duplex> 的子類。

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

設定套接字的超時值,並在發生超時時在伺服器物件上發出 'timeout' 事件,並將套接字作為引數傳遞。

如果伺服器物件上有 'timeout' 事件監聽器,則它將以超時的套接字作為引數被呼叫。

預設情況下,伺服器不會使套接字超時。但是,如果為伺服器的 'timeout' 事件分配了回撥函式,則必須顯式處理超時。

server.maxRequestsPerSocket#

  • 型別:<number> 每個套接字的請求數。預設值: 0 (無限制)

套接字在關閉 keep-alive 連線之前可以處理的最大請求數。

值為 0 將停用該限制。

當達到限制時,它會將 Connection 頭部的值設定為 close,但實際上不會關閉連線,達到限制後傳送的後續請求將得到 503 Service Unavailable 的響應。

server.timeout#

  • 型別:<number> 超時時間(毫秒)。預設值: 0(無超時)

在套接字被認為超時之前的不活動毫秒數。

值為 0 將停用對傳入連線的超時行為。

套接字超時邏輯是在連線時設定的,因此更改此值僅影響到伺服器的新連線,而不影響任何現有連線。

server.keepAliveTimeout#

  • 型別:<number> 超時時間(毫秒)。預設值: 5000 (5 秒)。

伺服器在完成寫入最後一個響應後,需要等待額外傳入資料的不活動毫秒數,超過此時間套接字將被銷燬。

此超時值與 server.keepAliveTimeoutBuffer 選項結合使用以確定實際的套接字超時,計算方式為:socketTimeout = keepAliveTimeout + keepAliveTimeoutBuffer 如果伺服器在 keep-alive 超時觸發之前收到新資料,它將重置常規的不活動超時,即 server.timeout

值為 0 將停用傳入連線的 keep-alive 超時行為。值為 0 使 HTTP 伺服器的行為類似於 8.0.0 之前的 Node.js 版本,這些版本沒有 keep-alive 超時。

套接字超時邏輯是在連線時設定的,因此更改此值僅影響到伺服器的新連線,而不影響任何現有連線。

server.keepAliveTimeoutBuffer#

  • 型別:<number> 超時時間(毫秒)。預設值: 1000 (1 秒)。

一個額外的緩衝時間,新增到 server.keepAliveTimeout 以延長內部套接字超時。

此緩衝透過將套接字超時略微延長到宣告的 keep-alive 超時之後,幫助減少連線重置 (ECONNRESET) 錯誤。

此選項僅適用於新的傳入連線。

server[Symbol.asyncDispose]()#

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

將 Socket 的超時值設定為 msecs。如果提供了回撥函式,則將其作為響應物件上 'timeout' 事件的監聽器新增。

如果沒有向請求、響應或伺服器新增 'timeout' 監聽器,則套接字在超時時會被銷燬。如果為請求、響應或伺服器的 'timeout' 事件分配了處理程式,則必須顯式處理超時的套接字。

response.socket#

對底層套接字的引用。通常使用者不會希望訪問此屬性。特別是,由於協議解析器如何附加到套接字,套接字不會發出 'readable' 事件。在 response.end() 之後,該屬性被置為 null。

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> 之外的套接字型別,否則此屬性保證是 <net.Socket> 類(<stream.Duplex> 的子類)的例項。

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#

如果在發出 'finish' 事件之前,所有資料都已重新整理到底層系統,則為 true

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

如果呼叫此方法且未呼叫 response.writeHead(),它將切換到隱式標頭模式並重新整理隱式標頭。

這會發送一塊響應主體。此方法可以多次呼叫以提供主體的後續部分。

如果在 createServer 中將 rejectNonStandardBodyWrites 設定為 true,則當請求方法或響應狀態不支援內容時,不允許寫入主體。如果嘗試為 HEAD 請求或作為 204304 響應的一部分寫入主體,則會丟擲一個同步的 Error,其程式碼為 ERR_HTTP_BODY_NOT_ALLOWED

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 可以是一個數組,其中鍵和值在同一個列表中。它*不是*一個元組列表。因此,偶數偏移量是鍵值,奇數偏移量是相關聯的值。陣列的格式與 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 和已傳輸的主體長度是否相等。

嘗試設定包含無效字元的標頭欄位名稱或值將導致丟擲 TypeError

response.writeProcessing()#

向客戶端傳送一個 HTTP/1.1 102 Processing 訊息,表示應傳送請求主體。

類:http.IncomingMessage#

IncomingMessage 物件由 http.Serverhttp.ClientRequest 建立,並分別作為 'request''response' 事件的第一個引數傳遞。它可用於訪問響應狀態、標頭和資料。

不同於其 socket 值(<stream.Duplex> 的子類),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> 以外的套接字型別或內部置為 null。

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: 'https:///status?name=ryan',
  origin: 'https://',
  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(msecs[, callback])#

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

傳送一塊主體。此方法可以多次呼叫。

encoding 引數僅在 chunk 是字串時相關。預設為 '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 (Bad Request) 狀態碼(根據規範要求)。預設值:true
    • ServerResponse <http.ServerResponse> 指定要使用的 ServerResponse 類。用於擴充套件原始的 ServerResponse預設值: ServerResponse
    • shouldUpgradeCallback(request) <Function> 一個回撥函式,它接收一個傳入請求並返回一個布林值,以控制應接受哪些升級嘗試。接受的升級將觸發一個 'upgrade' 事件(或者如果沒有註冊監聽器,它們的套接字將被銷燬),而被拒絕的升級將像任何非升級請求一樣觸發一個 'request' 事件。此選項預設為 () => server.listenerCount('upgrade') > 0
    • 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() 的唯一區別是它預設將方法設定為 GET 並自動呼叫 req.end()。回撥函式必須注意消費響應資料,原因在 http.ClientRequest 部分有說明。

callback 被呼叫時帶有一個引數,該引數是 http.IncomingMessage 的例項。

JSON 獲取示例:

http.get('https://: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 客戶端請求的預設值。與預設 Agent 配置的不同之處在於,它啟用了 keepAlive 並且超時時間為 5 秒。

http.maxHeaderSize#

只讀屬性,指定 HTTP 標頭允許的最大大小(以位元組為單位)。預設為 16 KiB。可使用 --max-http-header-size CLI 選項進行配置。

對於伺服器和客戶端請求,可以透過傳遞 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 選項時,為請求生成一個套接字/流。這可以用來避免僅僅為了覆蓋預設的 createConnection 函式而建立一個自定義的 Agent 類。有關更多詳細資訊,請參閱 agent.createConnection()。任何 Duplex 流都是有效的返回值。
    • defaultPort <number> 協議的預設埠。預設值: 如果使用 Agent,則為 agent.defaultPort,否則為 undefined
    • family <number> 解析 hosthostname 時使用的 IP 地址族。有效值為 46。如果未指定,將同時使用 IP v4 和 v6。
    • headers <Object> | <Array> 包含請求頭的物件或字串陣列。陣列的格式與 message.rawHeaders 相同。
    • 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'
    • 'data'res 物件上任意次數(如果響應體為空,則根本不會發出 '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> 的瀏覽器相容實現。

內建代理支援#

穩定性:1.1 - 活躍開發

當 Node.js 建立全域性代理時,如果設定了 NODE_USE_ENV_PROXY 環境變數為 1 或啟用了 --use-env-proxy,全域性代理將使用 proxyEnv: process.env 構建,從而根據環境變數啟用代理支援。也可以透過在構造代理時傳遞 proxyEnv 選項來建立具有代理支援的自定義代理。如果只想從環境變數繼承配置,該值可以是 process.env,或者是一個具有覆蓋環境的特定設定的物件。

檢查 proxyEnv 的以下屬性來配置代理支援。

  • HTTP_PROXYhttp_proxy: HTTP 請求的代理伺服器 URL。如果兩者都設定了,http_proxy 優先。
  • HTTPS_PROXYhttps_proxy: HTTPS 請求的代理伺服器 URL。如果兩者都設定了,https_proxy 優先。
  • NO_PROXYno_proxy: 逗號分隔的繞過代理的主機列表。如果兩者都設定了,no_proxy 優先。

如果請求是向 Unix 域套接字發出的,代理設定將被忽略。

代理 URL 格式#

代理 URL 可以使用 HTTP 或 HTTPS 協議:

  • HTTP 代理: http://proxy.example.com:8080
  • HTTPS 代理: https://proxy.example.com:8080
  • 帶身份驗證的代理: http://username:password@proxy.example.com:8080

NO_PROXY 格式#

NO_PROXY 環境變數支援多種格式

  • * - 為所有主機繞過代理
  • example.com - 精確主機名匹配
  • .example.com - 域名字尾匹配 (匹配 sub.example.com)
  • *.example.com - 萬用字元域名匹配
  • 192.168.1.100 - 精確 IP 地址匹配
  • 192.168.1.1-192.168.1.100 - IP 地址範圍
  • example.com:8080 - 帶特定埠的主機名

多個條目應以逗號分隔。

示例#

要啟動一個 Node.js 程序,併為透過預設全域性代理傳送的所有請求啟用代理支援,可以使用 NODE_USE_ENV_PROXY 環境變數

NODE_USE_ENV_PROXY=1 HTTP_PROXY=http://proxy.example.com:8080 NO_PROXY=localhost,127.0.0.1 node client.js 

--use-env-proxy 標誌。

HTTP_PROXY=http://proxy.example.com:8080 NO_PROXY=localhost,127.0.0.1 node --use-env-proxy client.js 

要建立一個具有內建代理支援的自定義代理

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

// Creating a custom agent with custom proxy support.
const agent = new http.Agent({ proxyEnv: { HTTP_PROXY: 'http://proxy.example.com:8080' } });

http.request({
  hostname: 'www.example.com',
  port: 80,
  path: '/',
  agent,
}, (res) => {
  // This request will be proxied through proxy.example.com:8080 using the HTTP protocol.
  console.log(`STATUS: ${res.statusCode}`);
}); 

另外,以下方法也同樣有效

const http = require('node:http');
// Use lower-cased option name.
const agent1 = new http.Agent({ proxyEnv: { http_proxy: 'http://proxy.example.com:8080' } });
// Use values inherited from the environment variables, if the process is started with
// HTTP_PROXY=http://proxy.example.com:8080 this will use the proxy server specified
// in process.env.HTTP_PROXY.
const agent2 = new http.Agent({ proxyEnv: process.env });