Node.js:HTTP

http 是 Node.js 处理 HTTP/1.1 的核心模块。接口按流设计,支持分块传输等特性,不会把整份请求或响应先缓冲完再交给你。

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  res.end('你好,李兆!');
});
server.listen(port, hostname, () => {
  console.log(`服务器运行在 http://${hostname}:${port}/`);
});

监听 0.0.0.0 会绑到所有网卡,本机浏览器应打开 http://127.0.0.1:3000/。HTTPS 用 https 模块;HTTP/2 用 http2,不要和本模块混成一套 API。一次性客户端也可用全局 fetch(Node 18+)。

http 类

HTTP 模块提供下列类。

Server 类

继承自 net.Serverhttp.createServer() 通常返回这个实例。

请求回调里解析查询串,用 WHATWG URL,不要再用已废弃的 url.parse()

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.statusMessage = 'OK';
  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  const urlObj = new URL(req.url, 'http://' + req.headers.host);
  res.write(urlObj.searchParams.get('name') || 'Lizhao01!');
  res.end();
});
server.listen(port, hostname, () => {
  console.log(`服务器运行在 http://${hostname}:${port}/`);
});

createServer 传入的函数等价于监听 request。不要再 server.on('request', ...) 绑一次,否则每个请求会进两个处理器。

checkContinue 事件

收到带 Expect: 100-continue 的请求时触发。未监听时服务器自动回 100 Continue

若客户端应继续发主体,调用 response.writeContinue();否则回适当状态(例如 400)。处理本事件后 不会 再触发 request

checkExpectation 事件

Expect 不是 100-continue 时触发。未监听则自动回 417 Expectation Failed。处理后不会再触发 request

clientError 事件

客户端连接出错。默认会立刻销毁 socket。

close 事件

服务器关闭时触发。

connect 事件

客户端发 HTTP CONNECT 时触发。未监听则关掉该连接。

connection 事件

新的 TCP 流建立时触发(与 net.Serverconnection 相同;较新文档也写作 connect)。

request 事件

每收到一个 HTTP 请求触发。keep-alive 下 一条 TCP 连接上可以有多次 request

upgrade 事件

客户端发 Upgrade 时触发。未监听则关掉该连接。WebSocket 握手走这条。

close([callback])

停止接收新连接。已有连接不会立刻掐断。

listen()

开始监听。可传端口、主机、回调,或 Unix socket 路径。

setTimeout()

设置超时毫秒。超时触发 timeout 事件。

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

listening

布尔值,是否正在监听。

maxHeadersCount

请求头个数上限,默认 2000。设为 0 表示不限制。

timeout

socket 无活动超时,毫秒。默认 120000(2 分钟)。0 关闭该超时。

只影响 之后新建 的连接。

keepAliveTimeout

发完最后一个响应后,还等多久入站数据才销毁 socket,默认 5000。keep-alive 期间收到新数据会重置计时。0 关闭该行为。同样只影响新建连接。

ClientRequest 类

http.request()http.get() 返回的对象,表示一个已排队请求头的客户端请求。头仍可用 setHeadergetHeaderremoveHeader 改,直到写出为止。

收到响应时触发 response,参数是 http.IncomingMessage。读主体:在 response 回调里听 dataend,或当可读流用。

Node 不会核对 Content-Length 是否等于实际发出的主体长度。

abort 事件

请求被客户端终止时触发(旧 abort() 路径)。现行应听 close,并用 destroy() 终止。

connect 事件

服务器响应 CONNECT 时触发。未监听则关闭连接。

continue 事件

服务器回了 100 Continue(通常因为请求带了 Expect: 100-continue),表示可以开始发主体。

response 事件

收到响应时触发,只一次。

socket 事件

socket 分配给该请求后触发。

timeout 事件

底层 socket 空闲超时。只是通知,请求要自己 destroy()

upgrade 事件

服务器响应 Upgrade 时触发。未监听则关闭连接。

abort()

已废弃。改用 request.destroy()

end()

结束发送。未发完的主体会刷新;分块传输会写结束块 0\r\n\r\n

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

data 时等于 writeendcallback 在请求流结束时调用。

flushHeaders()

立刻把请求头发出去。默认会等到 end() 或第一块 body,以便和数据打成一个 TCP 包。第一块数据要很久才有时,用 flushHeaders() 提前开请求。

getHeader(name)

读尚未发出的请求头。名称 不区分 大小写。

removeHeader(name)

从待发头里去掉一项。

setHeader(name, value)

设置单个头;已存在则覆盖。同名多个头用字符串数组。

setNoDelay([noDelay])

socket 连上后调用 socket.setNoDelay()

setSocketKeepAlive()

socket 连上后调用 socket.setKeepAlive()

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

setTimeout(timeout[, callback])

socket 连上后调用 socket.setTimeout()。返回 request

write()

写一块请求体。多次调用即可。这种情况下创建请求时建议用分块:Transfer-Encoding: chunked

request.write(chunk[, encoding][, callback]);
  • chunk:string 或 Buffer
  • encoding:默认 'utf8',仅字符串有效
  • callback:这块刷新后调用

aborted

已废弃。是否已终止请看 request.destroyed。旧值曾是终止时刻的毫秒时间戳。

connection

已废弃,等同 request.socketend 之后不要再依赖它。协议解析绑在 socket 上,socket 不会再触发普通的 readable

socket

底层 socket。

ServerResponse 类

HTTP 服务器内部创建,实现 stream.Writable(不是继承)。

close 事件

response.end() 或还能刷新之前,底层连接被掐掉时触发。

finish 事件

响应头和主体最后一块已交给操作系统发送时触发,不表示客户端已经收到。之后响应对象上不再有别的事件。

addTrailers(headers)

加尾部头。只有分块编码才会发出去;HTTP/1.0 等会丢弃。先在头里声明 Trailer

response.writeHead(200, {
  'Content-Type': 'text/plain',
  Trailer: 'Content-MD5'
});
response.write(fileData);
response.addTrailers({ 'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667' });
response.end();

end()

声明头和主体都发完。每个响应都必须调用。

response.end([data][, encoding][, callback]);

getHeader()

读已排队、尚未发给客户端的响应头。名称不区分大小写。

response.getHeader(name);

getHeaderNames()

当前响应头名称数组,均为小写。

getHeaders()

当前响应头的浅拷贝。改数组值会直接改到内部状态。键是小写头名。

返回对象 没有 Object.prototype,没有 toStringhasOwnProperty

hasHeader()

是否已设置名为 name 的头。不区分大小写。

response.hasHeader(name);

removeHeader()

从隐式发送队列里去掉一个头。

response.removeHeader(name);

setHeader()

设置隐式响应头,已存在则覆盖。非法字符抛 TypeError

response.setHeader(name, value);
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);

writeHead() 合并时,writeHead() 优先

setTimeout()

设置 socket 超时。有回调则作为 timeout 监听器。

response.setTimeout(msecs[, callback]);

write()

写一块响应体,可多次调用。若还没 writeHead(),会切到隐式响应头并刷新。

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

HEAD 请求、以及 204、304 响应不能带消息体。

第一次 write 会把缓冲的头和第一块主体发出去;之后才持续传。响应能否尽快结束,和第一块数据何时写出有关。

writeContinue()

向客户端发 HTTP/1.1 100 Continue

writeHead()

发送响应头。整条消息里只能调用一次,且必须在 end() 之前。

response.writeHead(statusCode[, statusMessage][, headers]);

若已经 write()end(),会先处理隐式头再走到这里。

connection、socket

底层 socket。connection 是旧名,用 socket

finished

已废弃。用 writableEnded(已调用 end)和 writableFinished(底层写完)。

headersSent

只读。头是否已发出。

sendDate

true 且没有 Date 头时自动补日期。默认 true。HTTP 响应需要日期头,只应在测试里关掉。

statusCode

隐式响应头时,刷新头用的状态码。头发出后表示实际发出的码。

statusMessage

隐式响应头时的原因短语;undefined 则用该状态码的标准短语。

IncomingMessage 类

http.Serverhttp.ClientRequest 创建,分别作为 requestresponse 事件的第一个参数。可读流,用来读状态、头和数据。

aborted 事件

已废弃。请求被终止且 socket 关闭时曾触发。改听 close

close 事件

底层连接关闭。每个消息一次。

destroy()

销毁收到该消息的 socket。

message.destroy([error]);

传入 error 会在 socket 上触发 error

setTimeout()

调用 message.socket.setTimeout(msecs, callback)

message.setTimeout(msecs, callback);

headers

请求头或响应头对象,键为小写。set-cookie 在较新 Node 里是数组;重复的其他头会合并成逗号分隔字符串。原始大小写和重复项见 rawHeaders

httpVersion

服务器上:客户端声明的 HTTP 版本;客户端上:对端服务器的版本。如 '1.1'

httpVersionMajor、httpVersionMinor

版本号的整数部分。

method(只读)

请求方法字符串。仅服务器收到的请求上有。

rawHeaders

原始头列表:偶数下标是键,奇数是值。名称保持原大小写,重复项不合并。

trailers

尾部头对象,只在 end 之后才有值。

rawTrailers

原始尾部头键值列表,同样只在 end 时赋值。

socket

关联的 net.Socket

statusCode

三位响应状态码。仅客户端收到的响应上有。

statusMessage

原因短语。仅客户端响应上有。

url

请求 URL 字符串,只含请求行里的路径和查询,没有协议和主机。仅服务器请求上有。拼完整 URL:new URL(req.url, 'http://' + req.headers.host)

Agent 类

管理客户端连接的复用。按主机和端口排队请求,队列空了才把 socket 销毁或放回池。是否入池看 keepAlive

池里的 TCP Keep-Alive 是开的,但服务器仍会关掉空闲连接;那时要从池里拿掉,下次再新建。有的服务器不允许一条连接上复用多个请求,这时每个请求都是新连接。

连接被任一方关闭就离开池。池里闲置的 socket 会释放,这样没有请求时进程不必空转。

Agent 不用了应 destroy(),否则 keep-alive 的 socket 会占操作系统资源。

new Agent([options])

  • keepAlive:布尔。为 true 时没有请求也留着 socket。自定义 Agent 默认仍是 falsehttp.globalAgent 从 Node 19 起默认 keepAlive: true
  • keepAliveMsecs:整数,默认 1000。TCP Keep-Alive 探测的初始延迟(keepAlive 为假时无效)。
  • maxSockets:每个来源最多多少并发 socket,默认 Infinity
  • maxFreeSockets:空闲最多留多少,默认 256,仅 keepAlive 为真时有效。
  • timeout:socket 超时毫秒。globalAgent 在 Node 19+ 默认 5000。

http.request() 默认用 http.globalAgent。要改行为就自己 new http.Agent(...)

const http = require('http');
const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 500,
  maxSockets: 88,
  maxFreeSockets: 126
});

createConnection(options[, callback])

为请求创建 socket 或流。默认类似 net.createConnection()。自定义 Agent 可覆盖。

  • host:默认 'localhost'
  • port:端口
  • path:Unix socket 路径
  • localAddresslocalPort:本地绑定
  • family46
  • hints:传给 dns.lookup() 的 hints
  • lookup:默认 dns.lookup()
  • callback(err, stream)

keepSocketAlive(socket)

请求用完 socket、代理还想留着时调用。

reuseSocket(socket, request)

keep-alive 的 socket 再次绑到请求时调用。

destroy()

毁掉代理正在用的 socket。启用了 keepAlive 、确定不再用时应该显式关掉。

getName(options)

给一组选项算唯一名,用来判断连接能否复用。HTTP 一般是 host:port:localAddress 或带 family;HTTPS 还会把 CA、证书等算进去。

sockets、freeSockets、requests

当前在用的 socket、空闲池、尚未分到 socket 的请求队列。不要改这些对象。

maxFreeSockets、maxSockets

可读写的上限,含义同构造选项。

http 属性

METHODS

支持的 HTTP 方法名数组。

STATUS_CODES

状态码到短描述的映射。

globalAgent

所有客户端请求的默认 Agent。

maxHeaderSize(只读)

单个 HTTP 头允许的最大字节数。现行默认 16KB(旧版文档写 8KB)。可用启动参数 --max-http-header-size 改。创建 server、request 时也可传 maxHeaderSize 覆盖。

http 方法

createServer([options][, requestListener])

返回 http.ServerrequestListener 自动听 request

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  res.end('你好,Lizhao!');
});
server.listen(port, hostname, () => {
  console.log(`服务器运行在 http://${hostname}:${port}/`);
});

node ./index.js 后浏览器打开 http://127.0.0.1:3000/

request()

发 HTTP 请求,返回 http.ClientRequest

http.request(options[, callback]);
http.request(url[, options][, callback]);

常用 options

  • protocol:默认 'http:'
  • hosthostname:默认 'localhost'。同时有时 hostname 优先
  • family46
  • port:默认 80
  • localAddresssocketPath
  • method:默认 'GET'
  • path:默认 '/',含查询串。含空字符会抛错
  • headersauthuser:pass 基本认证)
  • agentundefined 用 globalAgent;传入 Agent 则用它;false 则新建一个默认 Agent
  • createConnection:不用 agent 时自己造 socket
  • timeout:socket 超时毫秒

options 可以是对象、字符串或 URL。字符串按 URL 解析。出错(DNS、TCP、HTTP 解析)在返回的请求上触发 error;没有监听器就会变成未捕获异常。

const http = require('http');
const request = http.request('http://127.0.0.1:3000/', (res) => {
  res.on('data', (chunk) => {
    console.log(`响应主体: ${chunk}`);
  });
  res.on('end', () => {
    console.log('请求结束!');
  });
});
request.on('error', (err) => {
  console.error(err);
});
request.end();

必须调用 request.end(),即使没有 body。上面示例里不要对 GET 再 write('ok'),除非服务器真的在读 GET 主体。

get()

类似 request(),方法固定为 GET,并且 会自动 end()

参考资料

http(Node.js 文档)

搭建 HTTP 服务器

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-02 01:41:28

results matching ""

    No results matching ""