HTTP#

穩定度:2 - 穩定

此模組包含用戶端與伺服器,可透過 require('node:http') (CommonJS) 或 import * as http from 'node:http' (ES 模組) 匯入。

Node.js 中的 HTTP 介面旨在支援該協定中傳統上難以使用的許多功能,特別是大型且可能採用分塊編碼 (chunk-encoded) 的訊息。此介面謹慎地不對整個請求或回應進行緩衝,以便使用者能夠串流傳輸資料。

HTTP 訊息標頭由類似這樣的物件表示

{ "content-length": "123",
  "content-type": "text/plain",
  "connection": "keep-alive",
  "host": "example.com",
  "accept": "*/*" }

鍵名(Key)為小寫。值(Value)不會被修改。

為了支援全方位的 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 用戶端的連線持續性與重用。它為給定的主機和連接埠維護一個待處理請求佇列,為每個請求重用單個 Socket 連線,直到佇列為空,此時 Socket 會被銷毀或放入集區 (pool) 中保留,以便再次用於對同一主機和連接埠的請求。銷毀還是放入集區取決於 keepAlive 選項

集區連線會啟用 TCP Keep-Alive,但伺服器仍可能關閉閒置連線,在這種情況下,連線將從集區中移除,並在對該主機和連接埠發出新的 HTTP 請求時建立新連線。伺服器也可能拒絕在同一連線上允許多個請求,在這種情況下,每個請求都必須重新建立連線且無法放入集區。Agent 仍會向該伺服器發送請求,但每個請求都將透過新連線進行。

當連線由用戶端或伺服器關閉時,它會從集區中移除。集區中任何未使用的 Socket 都將被 unref,以便在沒有待處理請求時不讓 Node.js 程序繼續運行。(詳見 socket.unref())。

Agent 實例不再使用時,將其 destroy() 是良好的實作方式,因為未使用的 Socket 會消耗作業系統資源。

當 Socket 發出 'close' 事件或 'agentRemove' 事件時,會從代理中移除。如果打算長時間保持一個 HTTP 請求開啟而不將其保留在代理中,可以執行如下操作

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

代理也可以用於單個請求。透過將 {agent: false} 作為選項提供給 http.get()http.request() 函式,將為該用戶端連線使用具有預設選項的一次性 Agent

agent:false:

http.get({
  hostname: 'localhost',
  port: 80,
  path: '/',
  agent: false,  // Create a new agent just for this one request
}, (res) => {
  // Do stuff with response
});

new Agent([options])#

  • options <Object> 代理的可設定選項集。可以包含以下欄位
    • keepAlive <boolean> 即使沒有待處理的請求也保留 Socket,以便將來請求時無需重新建立 TCP 連線。請勿與 Connection 標頭的 keep-alive 值混淆。使用代理時一律會發送 Connection: keep-alive 標頭,除非明確指定了 Connection 標頭,或者當 keepAlivemaxSockets 選項分別設定為 falseInfinity 時,這種情況下將使用 Connection: close預設值: false
    • keepAliveMsecs <number> 使用 keepAlive 選項時,指定 TCP Keep-Alive 封包的初始延遲。當 keepAlive 選項為 falseundefined 時會被忽略。預設值: 1000
    • agentKeepAliveTimeoutBuffer <number> 在確定 Socket 過期時間時,從伺服器提供的 keep-alive: timeout=... 提示中減去的毫秒數。此緩衝區有助於確保代理比伺服器稍早關閉 Socket,從而降低在即將被伺服器關閉的 Socket 上發送請求的機會。預設值: 1000
    • maxSockets <number> 每個主機允許的最大 Socket 數量。如果同一主機開啟多個並行連線,則每個請求將使用新 Socket,直到達到 maxSockets 值。如果主機嘗試開啟比 maxSockets 更多的連線,額外的請求將進入待處理請求佇列,並在現有連線終止時進入活動連線狀態。這確保了在任何時間點,來自給定主機的活動連線最多為 maxSockets預設值: Infinity
    • maxTotalSockets <number> 所有主機總共允許的最大 Socket 數量。每個請求將使用新 Socket,直到達到最大值。預設值: Infinity
    • maxFreeSockets <number> 每個主機處於空閒狀態下保留開啟的最大 Socket 數量。僅在 keepAlive 設定為 true 時相關。預設值: 256
    • scheduling <string> 挑選下一個要使用的閒置 Socket 時套用的排程策略。可以是 'fifo''lifo'。這兩種排程策略的主要區別在於 'lifo' 選擇最近使用的 Socket,而 'fifo' 選擇最久未使用的 Socket。在每秒請求率較低的情況下,'lifo' 排程將降低挑選到可能已被伺服器因非活動狀態而關閉的 Socket 的風險。在每秒請求率較高的情況下,'fifo' 排程將使開啟的 Socket 數量最大化,而 'lifo' 排程則會儘可能保持較低。預設值: 'lifo'
    • timeout <number> Socket 逾時(以毫秒為單位)。這將在建立 Socket 時設定逾時。
    • 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])#

  • options <Object> 包含連線詳細資訊的選項。關於選項格式,請查看 net.createConnection()。對於自定義代理,此物件會傳遞給自定義的 createConnection 函式。
  • callback <Function> (選用,主要用於自定義代理)自定義 createConnection 實作在建立 Socket 時呼叫的函式,特別是用於非同步操作。
  • 回傳: <stream.Duplex> 已建立的 Socket。這由預設實作或自定義的同步 createConnection 實作回傳。如果自定義 createConnection 使用 callback 進行非同步操作,則此回傳值可能不是獲取 Socket 的主要方式。

產生用於 HTTP 請求的 Socket/串流。

預設情況下,此函式的行為與 net.createConnection() 完全相同,同步回傳建立的 Socket。此預設實作不使用簽章中的選用 callback 參數。

然而,自定義代理可以覆寫此方法以提供更大的靈活性,例如非同步建立 Socket。當覆寫 createConnection

  1. 同步 Socket 建立:覆寫方法可以直接回傳 Socket/串流。
  2. 非同步 Socket 建立:覆寫方法可以接收 callback 並將建立的 Socket/串流傳遞給它(例如 callback(null, newSocket))。如果在 Socket 建立過程中發生錯誤,應將其作為第一個參數傳遞給 callback(例如 callback(err))。

代理將使用 options 和此內部 callback 來呼叫提供的 createConnection 函式。代理提供的 callback 簽章為 (err, stream)

agent.keepSocketAlive(socket)#

socket 與請求分離且可以由 Agent 持久保留時呼叫。預設行為是

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

此方法可由特定的 Agent 子類別覆寫。如果此方法回傳虛值(falsy value),Socket 將被銷毀,而不是持久保留以供下一個請求使用。

socket 參數可以是 <net.Socket> 的實例,或 <stream.Duplex> 的子類別。

agent.reuseSocket(socket, request)#

socket 因 keep-alive 選項被持久保留後再附加到 request 時呼叫。預設行為是

socket.ref();

此方法可由特定的 Agent 子類別覆寫。

socket 參數可以是 <net.Socket> 的實例,或 <stream.Duplex> 的子類別。

agent.destroy()#

銷毀代理目前正在使用的任何 Socket。

通常不需要執行此操作。但是,如果使用啟用了 keepAlive 的代理,則最好在不再需要代理時明確將其關閉。否則,Socket 可能會保持開啟相當長一段時間,直到伺服器將其終止。

agent.freeSockets#

一個包含 Socket 陣列的物件,當啟用了 keepAlive 時,這些 Socket 目前正在等待代理使用。請勿修改。

freeSockets 列表中的 Socket 在 'timeout' 時會自動銷毀並從陣列中移除。

agent.getName([options])#

  • options <Object> 一組提供名稱生成資訊的選項
    • host <string> 發出請求的伺服器域名或 IP 地址
    • port <number> 遠端伺服器的連接埠
    • localAddress <string> 發出請求時用於綁定網路連線的本地介面
    • family <integer> 如果不等於 undefined,則必須為 4 或 6。
  • 傳回:<string>

獲取一組請求選項的唯一名稱,以確定連線是否可以重用。對於 HTTP 代理,這回傳 host:port:localAddresshost:port:localAddress:family。對於 HTTPS 代理,名稱包括 CA、cert、ciphers 以及其他決定 Socket 可重用性的 HTTPS/TLS 特定選項。

agent.maxFreeSockets#

預設設定為 256。對於啟用了 keepAlive 的代理,這設定了將保持在空閒狀態開啟的最大 Socket 數量。

agent.maxSockets#

預設設定為 Infinity。決定代理每個來源(Origin)可以開啟多少個並發 Socket。來源是 agent.getName() 的回傳值。

agent.maxTotalSockets#

預設設定為 Infinity。決定代理總共可以開啟多少個並發 Socket。與 maxSockets 不同,此參數套用於所有來源。

agent.requests#

一個物件,包含尚未分配給 Socket 的請求佇列。請勿修改。

agent.sockets#

一個物件,包含代理目前正在使用的 Socket 陣列。請勿修改。

類別: http.ClientRequest#

此物件在內部建立並由 http.request() 回傳。它代表一個進行中的請求,其標頭已排入佇列。標頭仍可使用 setHeader(name, value)getHeader(name)removeHeader(name) API 進行修改。實際的標頭將與第一個資料區塊一起發送,或在呼叫 request.end() 時發送。

要獲取回應,請為請求物件新增 'response' 事件監聽器。當接收到回應標頭時,請求物件會發出 'response''response' 事件執行時帶有一個參數,即 http.IncomingMessage 的實例。

'response' 事件期間,可以為回應物件新增監聽器;特別是監聽 'data' 事件。

如果未新增 'response' 處理程序,回應將被完全捨棄。然而,如果新增了 'response' 事件處理程序,則必須消耗回應物件中的資料,無論是在有 'readable' 事件時呼叫 response.read(),或是新增 'data' 處理程序,亦或是呼叫 .resume() 方法。在資料被消耗之前,'end' 事件不會觸發。此外,在讀取資料之前,它會消耗記憶體,最終可能導致「程序記憶體耗盡」(process out of memory) 錯誤。

為了向後相容,只有在註冊了 '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> 以外的 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 請求/回應鏈(例如 Web Socket、就地 TLS 升級或 HTTP 2.0),因此不會觸發此事件。若要接收 101 Upgrade 通知,請改為監聽 'upgrade' 事件。

事件:'response'#

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

事件: 'socket'#

除非使用者指定了 <net.Socket> 以外的 Socket 類型,否則保證傳遞給此事件的參數是 <net.Socket> 類別(<stream.Duplex> 的子類別)的實例。

事件:'timeout'#

當底層 Socket 因非活動狀態而逾時時發出。這僅通知 Socket 已閒置。必須手動銷毀請求。

另請參閱:request.setTimeout()

事件: 'upgrade'#

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

除非使用者指定了 <net.Socket> 以外的 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, stream, head) => {
  stream.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
               'Upgrade: WebSocket\r\n' +
               'Connection: Upgrade\r\n' +
               '\r\n');

  stream.pipe(stream); // 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, stream, upgradeHead) => {
    console.log('got upgraded!');
    stream.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, stream, head) => {
  stream.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
               'Upgrade: WebSocket\r\n' +
               'Connection: Upgrade\r\n' +
               '\r\n');

  stream.pipe(stream); // 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, stream, upgradeHead) => {
    console.log('got upgraded!');
    stream.end();
    process.exit(0);
  });
});

request.abort()#

穩定性: 0 - 已棄用:請改用 request.destroy()

將請求標記為中止。呼叫此方法將導致回應中剩餘的資料被捨棄且 Socket 被銷毀。

request.aborted#

穩定性: 0 - 已棄用。請改為檢查 request.destroyed

如果請求已被中止,則 request.aborted 屬性將為 true

request.connection#

穩定度:0 - 已棄用。請改用 request.socket

請參閱 request.socket

request.cork()#

參見 writable.cork()

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

結束發送請求。如果主體的任何部分尚未發送,它會將其排清至串流。如果請求是分塊的(chunked),這將發送終止符 '0\r\n\r\n'

如果指定了 data,則等同於先呼叫 request.write(data, encoding) 再呼叫 request.end(callback)

如果指定了 callback,則在請求串流結束時呼叫。

request.destroy([error])#

  • error <Error> 選配,隨 'error' 事件發出的錯誤。
  • 傳回:<this>

銷毀請求。可選擇發出一個 'error' 事件,並發出一個 'close' 事件。呼叫此方法將導致回應中剩餘的資料被捨棄且 Socket 被銷毀。

詳見 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> 請求是否透過重用的 Socket 發送。

透過啟用 keep-alive 的代理發送請求時,底層 Socket 可能會被重用。但如果伺服器在不凑巧的時間關閉連線,用戶端可能會遇到 'ECONNRESET' 錯誤。

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

// 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
const http = require('node:http');
const agent = new http.Agent({ keepAlive: true });

// 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

透過標記請求是否重用 Socket,我們可以據此進行自動錯誤重試。

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 且連線成功後,將呼叫 socket.setNoDelay()

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

一旦為此請求分配了 Socket 且連線成功後,將呼叫 socket.setKeepAlive()

request.setTimeout(timeout[, callback])#

一旦為此請求分配了 Socket 且連線成功後,將呼叫 socket.setTimeout()

request.socket#

底層 Socket 的引用。通常使用者不會想要訪問此屬性。特別是,由於協定解析器附加到 Socket 的方式,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> 以外的 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 分塊傳輸編碼(Chunked transfer encoding)進行編碼,以便伺服器知道資料何時結束。會新增 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' 事件,它將被轉發到這裡。此事件的監聽器負責關閉/銷毀底層 Socket。例如,開發者可能希望使用自定義的 HTTP 回應更優雅地關閉 Socket,而不是突然切斷連線。在監聽器結束前,Socket 必須被關閉或銷毀

除非使用者指定了 <net.Socket> 以外的 Socket 類型,否則保證傳遞給此事件的參數是 <net.Socket> 類別(<stream.Duplex> 的子類別)的實例。

預設行為是嘗試使用 HTTP '400 Bad Request' 關閉 Socket,若發生 HPE_HEADER_OVERFLOW 錯誤,則使用 HTTP '431 Request Header Fields Too Large'。如果 Socket 不可寫入或目前附加的 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:當前請求的原始封包。

在某些情況下,用戶端已經收到回應及/或 Socket 已經被銷毀,例如 ECONNRESET 錯誤。在嘗試向 Socket 發送資料之前,最好先檢查它是否仍具備寫入能力。

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> 以外的 Socket 類型,否則保證傳遞給此事件的參數是 <net.Socket> 類別(<stream.Duplex> 的子類別)的實例。

發出此事件後,請求的 Socket 將不再有 'data' 事件監聽器,這意味著需要綁定監聽器才能處理在該 Socket 上發送到伺服器的資料。

事件:'connection'#

此事件在建立新的 TCP 串流時發出。socket 通常是 net.Socket 類型的物件。通常使用者不會想要訪問此事件。特別是,由於協定解析器附加到 Socket 的方式,Socket 不會發出 'readable' 事件。也可以透過 request.socket 訪問 socket

使用者也可以明確觸發此事件,以向 HTTP 伺服器寫入連線。在這種情況下,可以傳遞任何 Duplex 串流。

如果在處呼叫 socket.setTimeout(),則在 Socket 提供過請求後(若 server.keepAliveTimeout 非零),逾時時間將被替換為 server.keepAliveTimeout

除非使用者指定了 <net.Socket> 以外的 Socket 類型,否則保證傳遞給此事件的參數是 <net.Socket> 類別(<stream.Duplex> 的子類別)的實例。

事件: 'dropRequest'#

當 Socket 上的請求數達到 server.maxRequestsPerSocket 的閾值時,伺服器將捨棄新請求並改為發出 'dropRequest' 事件,然後向用戶端發送 503

事件:'request'#

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

事件: 'upgrade'#

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

監聽此事件是選用的,用戶端不能強求協定變更。

如果升級被 shouldUpgradeCallback 接受但未註冊事件處理程序,則 Socket 將被銷毀,導致用戶端的連線立即關閉。

在極少數情況下,如果傳入的請求包含主體,該主體將照常解析(與升級串流分開),且原始串流資料僅在解析完成後開始。為確保從串流讀取不會因等待讀取請求主體而受阻,對串流的任何讀取都將自動啟動請求主體的傳輸。如果您想讀取請求主體,請確保在開始從升級串流讀取之前進行讀取(即附加 'data' 監聽器)。

stream 參數通常是請求使用的 <net.Socket> 實例,但在某些情況下(如帶有請求主體)它可能是雙工串流。如果需要,您可以透過 request.socket 訪問請求底層的原始連線,除非使用者指定了其他 Socket 類型,否則保證它是 <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)的 Socket。

這是一種強制關閉所有連線的方式,應謹慎使用。當與 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 秒),以防止在伺服器部署時前面沒有反向代理的情況下遭受潛在的阻斷服務 (DoS) 攻擊。

server.listen()#

開始讓 HTTP 伺服器監聽連線。此方法與 net.Server 中的 server.listen() 相同。

server.listening#

  • 類型: <boolean> 指示伺服器是否正在監聽連線。

server.maxHeadersCount#

限制最大傳入標頭數量。如果設定為 0,則不套用限制。

server.requestTimeout#

設定從用戶端接收完整請求的逾時值(以毫秒為單位)。

如果逾時,伺服器將以狀態碼 408 回應,且不將請求轉發給請求監聽器,然後關閉連線。

必須將其設定為非零值(例如 120 秒),以防止在伺服器部署時前面沒有反向代理的情況下遭受潛在的阻斷服務 (DoS) 攻擊。

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

設定 Socket 的逾時值,並在發生逾時時於 Server 物件上發出 'timeout' 事件,並將 Socket 作為參數傳遞。

如果 Server 物件上有 'timeout' 事件監聽器,則會呼叫該監聽器,並將逾時的 Socket 作為參數。

預設情況下,Server 不會對 Socket 進行逾時處理。但是,如果為 Server 的 'timeout' 事件分配了回呼,則必須明確處理逾時。

server.maxRequestsPerSocket#

  • 類型: <number> 每個 Socket 的請求數。預設值: 0(無限制)

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

值為 0 將停用此限制。

達到限制時,它會將 Connection 標頭值設定為 close,但不會實際關閉連線,達到限制後發送的後續請求將收到 503 Service Unavailable 回應。

server.timeout#

  • 類型:<number> 逾時毫秒數。 預設值: 0(無逾時)

Socket 在被認定為逾時之前,可保持無活動狀態的毫秒數。

值為 0 將停用連入連線的逾時行為。

Socket 逾時邏輯是在連線時建立的,因此變更此值僅會影響到伺服器的新連線,而不會影響任何現有的連線。

server.keepAliveTimeout#

  • 類型: <number> 逾時時間(以毫秒為單位)。預設值: 5000(5 秒)。

伺服器在完成寫入最後一個回應後,在銷毀 Socket 之前需要等待額外傳入資料的非活動毫秒數。

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

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

Socket 逾時邏輯是在連線時建立的,因此變更此值僅會影響到伺服器的新連線,而不會影響任何現有的連線。

server.keepAliveTimeoutBuffer#

  • 類型: <number> 逾時時間(以毫秒為單位)。預設值: 1000(1 秒)。

新增到 server.keepAliveTimeout 的額外緩衝時間,用於延長內部 Socket 逾時。

此緩衝區透過將 Socket 逾時時間延長至略長於宣稱的 keep-alive 逾時,有助於減少連線重置 (ECONNRESET) 錯誤。

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

server[Symbol.asyncDispose]()#

呼叫 server.close() 並傳回一個在伺服器關閉時實現(fulfill)的 Promise。

類別: http.ServerResponse#

此物件是由 HTTP 伺服器在內部建立的,而不是由使用者建立。它會作為第二個參數傳遞給 'request' 事件。

事件:'close'#

表示回應已完成,或其底層連線過早終止(在回應完成之前)。

事件:'finish'#

當回應發送完畢時發出。更具體地說,當回應標頭與主體的最後一部分已交給作業系統以便透過網路傳輸時,會發出此事件。這並不代表用戶端已經收到任何內容。

response.addTrailers(headers)#

此方法向回應中加入 HTTP 尾隨標頭(一種標頭,但位於訊息末尾)。

只有在回應使用分塊編碼時才會發出 Trailer;如果未使用(例如請求為 HTTP/1.0),它們將被悄悄捨棄。

HTTP 要求發送 Trailer 標頭才能發出 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 標頭(詳見 RFC 9110 第 6.6.1 節)。

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' 監聽器,則 Socket 在逾時時將被銷毀。如果為請求、回應或伺服器的 'timeout' 事件分配了處理程序,則必須明確處理逾時的 Socket。

response.socket#

底層 Socket 的引用。通常使用者不會想要訪問此屬性。特別是,由於協定解析器附加到 Socket 的方式,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> 以外的 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。此屬性不表示資料是否已排清,若要判斷是否排清,請改用 request.writableFinished

response.writableFinished#

如果在發出 'finish' 事件之前,所有資料都已排清至底層系統,則為 true

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

如果呼叫了此方法且未呼叫 response.writeHead(),它將切換到隱含標頭模式並排清隱含標頭。

發送回應主體的一個區塊。此方法可以呼叫多次,以提供主體的後續部分。

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

chunk 可以是字串或緩衝區。如果 chunk 是字串,第二個參數指定如何將其編碼為位元組流。當此資料區塊排清時,將呼叫 callback

這是原始的 HTTP 主體,與可能使用的更高層多部分 (multi-part) 主體編碼無關。

第一次呼叫 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,其中鍵(key)和值(value)位在同一個清單中。它不是一個元組(tuple)清單。因此,偶數索引位置是鍵,奇數索引位置是相關聯的值。該陣列的格式與 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 是以位元組(byte)而非字元(character)來讀取。使用 Buffer.byteLength() 來確定正文(body)的位元組長度。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>,它是為了在底層 socket 可能因 keep-alive 而多次重複使用的情況下,解析並發送傳入的 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 的 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> 的子類別)的執行個體,除非使用者指定了 <net.Socket> 以外的 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() 被呼叫後觸發。當事件觸發時,所有資料都已處理,但不一定已完全排清(flushed)。

outgoingMessage.addTrailers(headers)#

向訊息新增 HTTP 尾隨標頭(trailers,即位在訊息末尾的標頭)。

僅當訊息使用分塊編碼(chunked encoded)時,尾隨標頭才被發送。否則,尾隨標頭將被直接忽略。

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

回傳目前傳出標頭的淺拷貝(shallow copy)。由於使用的是淺拷貝,因此可以在不額外呼叫各種與標頭相關的 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 類別(http.OutgoingMessage 的父類別)的 stream.pipe() 方法。

呼叫此方法將拋出 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)時呼叫的可選函數。等同於綁定 timeout 事件。
  • 傳回:<this>

一旦 socket 與訊息相關聯且已連線,將以 msecs 作為第一個參數呼叫 socket.setTimeout()

outgoingMessage.socket#

對底層 socket 的引用。通常,使用者不會想要存取此屬性。

呼叫 outgoingMessage.end() 後,此屬性將被設為 null。

outgoingMessage.uncork()#

參閱 writable.uncork()

outgoingMessage.writableCorked#

outgoingMessage.cork() 被呼叫的次數。

outgoingMessage.writableEnded#

如果已呼叫 outgoingMessage.end() 則為 true。此屬性不表示資料是否已排清。若要判斷資料是否已排清,請改用 message.writableFinished

outgoingMessage.writableFinished#

如果所有資料都已排清到底層系統,則為 true

outgoingMessage.writableHighWaterMark#

底層 socket 的 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,它會在接收到新的傳入連線後立即在 socket 上啟用 keep-alive 功能,類似於 [socket.setKeepAlive([enable][, initialDelay])][socket.setKeepAlive(enable, initialDelay)] 所做的。預設值: false
    • keepAliveInitialDelay <number> 如果設為正數,它會設定在閒置 socket 上發送第一個 keepalive 探測之前的初始延遲。預設值: 0
    • keepAliveTimeout:伺服器在寫入最後一個回應後,在銷毀 socket 之前需要等待額外傳入資料的非活動毫秒數。詳見 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' 事件(如果未註冊監聽器,則其 socket 將被銷毀),而被拒絕的升級將像任何非升級請求一樣觸發 'request' 事件。此選項預設為 () => server.listenerCount('upgrade') > 0
    • uniqueHeaders <Array> 應僅發送一次的回應標頭清單。如果標頭的值是陣列,項目將使用 ; 合併。
    • rejectNonStandardBodyWrites <boolean> 如果設為 true,當寫入沒有正文的 HTTP 回應時會拋出錯誤。預設值: false
    • optimizeEmptyRequests <boolean> 如果設為 true,則不含 Content-LengthTransfer-Encoding 標頭(表示無正文)的請求將以已結束的正文串流初始化,因此它們永遠不會觸發任何串流事件(如 'data''end')。您可以使用 req.readableEnded 來偵測此情況。預設值: 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 設定的不同之處在於啟用了 keepAlivetimeout 為 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 選項時,產生用於請求之 socket/串流的函數。這可用於避免僅為了覆寫預設 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 域 socket。如果指定了 hostport 之一,則不能使用此選項,因為它們指定的是 TCP Socket。
    • timeout <number>:指定 socket 逾時時間(毫秒)的數字。這將在 socket 連線之前設定逾時。
    • 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'

如果在分配 socket 之前呼叫了 req.destroy(),將依序觸發以下事件

  • (在此處呼叫 req.destroy())
  • 觸發 'error',錯誤訊息為 'Error: socket hang up' 且代碼為 'ECONNRESET',或者呼叫 req.destroy() 時所帶的錯誤
  • 'close'

如果在連線成功之前呼叫了 req.destroy(),將依序觸發以下事件

  • 'socket'
  • (在此處呼叫 req.destroy())
  • 觸發 'error',錯誤訊息為 'Error: socket hang up' 且代碼為 'ECONNRESET',或者呼叫 req.destroy() 時所帶的錯誤
  • 'close'

如果在接收到回應之後呼叫了 req.destroy(),將依序觸發以下事件

  • 'socket'
  • 'response'
    • res 物件上多次觸發 'data'
  • (在此處呼叫 req.destroy())
  • res 物件上觸發 'aborted'
  • 'close'
  • res 物件上觸發 'error',錯誤訊息為 'Error: aborted' 且代碼為 'ECONNRESET',或者呼叫 req.destroy() 時所帶的錯誤
  • res 物件上觸發 'close'

如果在分配 socket 之前呼叫了 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 解析器的最大數量。

http.setGlobalProxyFromEnv([proxyEnv])#

  • proxyEnv <Object> 包含代理配置的物件。這接受與 Agent 接受的 proxyEnv 選項相同的選項。預設值: process.env
  • 回傳:<Function> 一個函數,可將原始 agent 和派發器(dispatcher)設定還原到呼叫此 http.setGlobalProxyFromEnv() 之前的狀態。

在執行時動態重設全域配置,以便為 fetch()http.request()/https.request() 啟用內建代理支援,作為使用 --use-env-proxy 標記或 NODE_USE_ENV_PROXY 環境變數的替代方案。它也可用於覆寫從環境變數配置的設定。

由於此函數會重設全域配置,呼叫此函數後,任何先前配置的 http.globalAgenthttps.globalAgent 或 undici 全域派發器都將被覆寫。建議在發出任何請求之前呼叫它,並避免在任何請求中間呼叫它。

有關代理 URL 格式和 NO_PROXY 語法的詳細資訊,請參閱內建代理支援

類別:WebSocket#

一個與瀏覽器相容的 <WebSocket> 實作。

內建代理支援#

穩定性:1.1 - 積極開發中

當 Node.js 建立全域 agent 時,如果 NODE_USE_ENV_PROXY 環境變數設定為 1 或啟用了 --use-env-proxy,全域 agent 將以 proxyEnv: process.env 建構,從而根據環境變數啟用代理支援。

若要動態且全域地啟用代理支援,請使用 http.setGlobalProxyFromEnv()

建立自定義 agent 時,也可以透過在建構 agent 時傳遞 proxyEnv 選項來支援代理。如果只想繼承環境變數的配置,值可以是 process.env,或者是一個包含覆寫環境特定設定的物件。

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

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

如果請求是發送到 Unix 域 socket,則代理設定將被忽略。

代理 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 程序,並為透過預設全域 agent 傳送的所有請求啟用代理支援,請使用 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

使用 process.envhttp.setGlobalProxyFromEnv() 的預設選項)動態且全域地啟用代理支援

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

// Reads proxy-related environment variables from process.env
const restore = http.setGlobalProxyFromEnv();

// Subsequent requests will use the configured proxies from environment variables
http.get('http://www.example.com', (res) => {
  // This request will be proxied if HTTP_PROXY or http_proxy is set
});

fetch('https://www.example.com', (res) => {
  // This request will be proxied if HTTPS_PROXY or https_proxy is set
});

// To restore the original global agent and dispatcher settings, call the returned function.
// restore();
import http from 'node:http';

// Reads proxy-related environment variables from process.env
http.setGlobalProxyFromEnv();

// Subsequent requests will use the configured proxies from environment variables
http.get('http://www.example.com', (res) => {
  // This request will be proxied if HTTP_PROXY or http_proxy is set
});

fetch('https://www.example.com', (res) => {
  // This request will be proxied if HTTPS_PROXY or https_proxy is set
});

// To restore the original global agent and dispatcher settings, call the returned function.
// restore();

使用自定義設定動態且全域地啟用代理支援

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

const restore = http.setGlobalProxyFromEnv({
  http_proxy: 'http://proxy.example.com:8080',
  https_proxy: 'https://proxy.example.com:8443',
  no_proxy: 'localhost,127.0.0.1,.internal.example.com',
});

// Subsequent requests will use the configured proxies
http.get('http://www.example.com', (res) => {
  // This request will be proxied through proxy.example.com:8080
});

fetch('https://www.example.com', (res) => {
  // This request will be proxied through proxy.example.com:8443
});
import http from 'node:http';

http.setGlobalProxyFromEnv({
  http_proxy: 'http://proxy.example.com:8080',
  https_proxy: 'https://proxy.example.com:8443',
  no_proxy: 'localhost,127.0.0.1,.internal.example.com',
});

// Subsequent requests will use the configured proxies
http.get('http://www.example.com', (res) => {
  // This request will be proxied through proxy.example.com:8080
});

fetch('https://www.example.com', (res) => {
  // This request will be proxied through proxy.example.com:8443
});

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

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 });