Skip to content
js
/*
{
  _connectionListener: [Function: connectionListener],
  METHODS: [
    'ACL',         'BIND',       'CHECKOUT',
    'CONNECT',     'COPY',       'DELETE',
    'GET',         'HEAD',       'LINK',
    'LOCK',        'M-SEARCH',   'MERGE',
    'MKACTIVITY',  'MKCALENDAR', 'MKCOL',
    'MOVE',        'NOTIFY',     'OPTIONS',
    'PATCH',       'POST',       'PROPFIND',
    'PROPPATCH',   'PURGE',      'PUT',
    'REBIND',      'REPORT',     'SEARCH',
    'SOURCE',      'SUBSCRIBE',  'TRACE',
    'UNBIND',      'UNLINK',     'UNLOCK',
    'UNSUBSCRIBE'
  ],
  STATUS_CODES: {
    '100': 'Continue',
    '101': 'Switching Protocols',
    '102': 'Processing',
    '103': 'Early Hints',
    '200': 'OK',
    '201': 'Created',
    '202': 'Accepted',
    '203': 'Non-Authoritative Information',
    '204': 'No Content',
    '205': 'Reset Content',
    '206': 'Partial Content',
    '207': 'Multi-Status',
    '208': 'Already Reported',
    '226': 'IM Used',
    '300': 'Multiple Choices',
    '301': 'Moved Permanently',
    '302': 'Found',
    '303': 'See Other',
    '304': 'Not Modified',
    '305': 'Use Proxy',
    '307': 'Temporary Redirect',
    '308': 'Permanent Redirect',
    '400': 'Bad Request',
    '401': 'Unauthorized',
    '402': 'Payment Required',
    '403': 'Forbidden',
    '404': 'Not Found',
    '405': 'Method Not Allowed',
    '406': 'Not Acceptable',
    '407': 'Proxy Authentication Required',
    '408': 'Request Timeout',
    '409': 'Conflict',
    '410': 'Gone',
    '411': 'Length Required',
    '412': 'Precondition Failed',
    '413': 'Payload Too Large',
    '414': 'URI Too Long',
    '415': 'Unsupported Media Type',
    '416': 'Range Not Satisfiable',
    '417': 'Expectation Failed',
    '418': "I'm a Teapot",
    '421': 'Misdirected Request',
    '422': 'Unprocessable Entity',
    '423': 'Locked',
    '424': 'Failed Dependency',
    '425': 'Too Early',
    '426': 'Upgrade Required',
    '428': 'Precondition Required',
    '429': 'Too Many Requests',
    '431': 'Request Header Fields Too Large',
    '451': 'Unavailable For Legal Reasons',
    '500': 'Internal Server Error',
    '501': 'Not Implemented',
    '502': 'Bad Gateway',
    '503': 'Service Unavailable',
    '504': 'Gateway Timeout',
    '505': 'HTTP Version Not Supported',
    '506': 'Variant Also Negotiates',
    '507': 'Insufficient Storage',
    '508': 'Loop Detected',
    '509': 'Bandwidth Limit Exceeded',
    '510': 'Not Extended',
    '511': 'Network Authentication Required'
  },
  Agent: [Function: Agent] { defaultMaxSockets: Infinity },
  ClientRequest: [Function: ClientRequest],
  IncomingMessage: [Function: IncomingMessage],
  OutgoingMessage: [Function: OutgoingMessage],
  Server: [Function: Server],
  ServerResponse: [Function: ServerResponse],
  createServer: [Function: createServer],
  validateHeaderName: [Function: __node_internal_],
  validateHeaderValue: [Function: __node_internal_],
  get: [Function: get],
  request: [Function: request],
  setMaxIdleHTTPParsers: [Function: setMaxIdleHTTPParsers],
  maxHeaderSize: [Getter],
  globalAgent: [Getter/Setter]
}
*/
const http = require('node:http')

console.log(http)

createServer

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

// req => IncomingMessage
// res => ServerResponse => OutgoingMessage
const server = http.createServer((req, res) => {
  console.log(req)
  console.log(res)
  res.statusCode = 404
  res.end(String(404))
})

server.listen(3300)

request

测试可知,OutgoingMessageClientRequest ServerResponse 的基类。

  1. IncomingMessage
  2. OutgoingMessage
  • ClientRequest
  • ServerResponse
js
const http = require('node:http')

const options = {
  hostname: 'www.example.com',
  port: 80,
  path: '/',
  method: 'GET'
}

// req => ClientRequest => OutgoingMessage
// res => IncomingMessage
const req = http.request(options, res => {
  // res.on('data', (chunk) => {
  //   console.log(`响应体: ${chunk}`)
  // })
  // res.on('end', () => {
  //   console.log('响应结束')
  // })
  console.log(res)
})

console.log(req)

req.end()

1.Agent

http.AgentNode.jsHTTP 客户端使用的一个类,用于管理和复用网络连接。

它主要用于控制 HTTP 请求的行为,比如连接的复用、最大并发连接数等。

默认情况下,Node.jsHTTP 请求会自动使用 http.Agent

不过,也可以通过自定义 http.Agent 实现更复杂的需求。

js
const http = require('http')

// 创建自定义 Agent
const agent = new http.Agent({
  keepAlive: true,         // 保持连接
  maxSockets: 10,          // 最大并发连接数
  maxFreeSockets: 5,       // 最大空闲连接数
  timeout: 60000           // 超时时间
})

// 使用自定义 Agent 发起请求
const options = {
  hostname: 'www.example.com',
  port: 80,
  path: '/',
  method: 'GET',
  agent: agent
}

const req = http.request(options, (res) => {
  // 处理响应
  console.log(`状态码: ${res.statusCode}`)
  
  // 监听数据事件
  res.on('data', (chunk) => {
    console.log(`响应体: ${chunk}`)
  })

  // 监听结束事件
  res.on('end', () => {
    console.log('响应结束')
  })
})

req.on('error', (e) => {
  console.error(`请求遇到问题: ${e.message}`)
})

// req.end() 标志着你已经发送完所有的请求数据。在调用 req.end() 后,请求会发送出去
req.end()

2.ClientRequest

http.clientRequestNode.jsHTTP 模块中的一个类,代表一个 HTTP 请求对象。

它是由 http.request()http.get() 方法创建的,并且用于向服务器发送 HTTP 请求。

http.clientRequest 对象具有许多方法和事件,用于控制和处理 HTTP 请求的生命周期。

常用的属性和方法:

  1. write(chunk, [encoding], [callback]): 向请求主体写入数据。chunk 是你要发送的数据块。

  2. end([data], [encoding], [callback]): 完成发送请求。当所有的请求数据都通过 write() 方法写入后,需要调用 end() 方法通知服务器请求已经完成。

  3. abort(): 中止请求。如果请求已经发送但尚未完成,你可以使用这个方法取消请求。

  4. setTimeout(timeout, [callback]): 设置请求的超时时间。timeout 是以毫秒为单位的时间,超过这个时间请求会自动终止。callback 是一个可选的回调函数,它将在超时时被调用。

  5. on(event, listener): 用于监听请求过程中的事件。常见的事件包括:

  • response: 当服务器响应时触发,返回一个 http.IncomingMessage 对象。
  • error: 当请求发生错误时触发。
  • timeout: 当请求超时时触发
js
const http = require('http')

const options = {
  hostname: 'example.com',
  port: 80,
  path: '/',
  method: 'GET'
}

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

req.end()

3.IncomingMessage

http.IncomingMessageNode.jsHTTP 模块的一个类,表示服务器接收到的 HTTP 请求或客户端收到的 HTTP 响应。

在服务器端,当使用 http.createServer() 创建一个 HTTP 服务器时,每次收到请求时,回调函数的第一个参数就是一个 http.IncomingMessage 对象。它包含了请求的详细信息,比如 HTTP 头、请求方法、URL 等。

在客户端,当你使用 http.request()http.get() 发送一个 HTTP 请求时,http.IncomingMessage 对象会作为回调函数的参数,表示服务器的响应。

主要属性和方法:

  1. httpVersion: 一个字符串,表示 HTTP 版本号,例如 1.1

  2. headers: 一个对象,包含了请求或响应的头部信息。键是头部名称,值是头部的值。

  3. rawHeaders: 一个数组,包含了头部的原始信息,以键值对的形式交替存储。

  4. method: 仅适用于服务器端,表示请求的方法,比如 GETPOST 等。

  5. url: 仅适用于服务器端,表示请求的 URL

  6. statusCode: 仅适用于客户端,表示服务器响应的 HTTP 状态码,比如 200404

  7. statusMessage: 仅适用于客户端,表示与 statusCode 关联的状态消息,例如 OK 对应状态码 200

  8. socket: 一个 net.Socket 对象,表示底层的网络套接字。

  9. setEncoding([encoding]): 设置接收到的数据的编码。如果你不设置编码,数据将作为 Buffer 对象传递。

  10. on(event, listener): 用于监听事件,常见的事件有:

  • data: 每当接收到一块数据时触发。数据将作为一个参数传递给回调函数。
  • end: 在接收到数据流结束时触发,表示所有的数据都已经被接收。
  • error: 当接收数据时发生错误时触发。
  • close: 当消息完全结束并且底层连接已被关闭时触发。
js
const http = require('http')

// 同时支持get和post请求
const server = http.createServer((req, res) => {
  console.log(`Request method: ${req.method}`)
  console.log(`Request URL: ${req.url}`)
  console.log(`Request headers: ${JSON.stringify(req.headers)}`)

  // 监听请求体
  req.on('data', (chunk) => {
    console.log(`Body chunk: ${chunk}`)
  })

  req.on('end', () => {
    res.writeHead(200, { 'Content-Type': 'text/plain' })
    res.end('Hello, world!\n')
  })
})

server.listen(3000, () => {
  console.log('Server is listening on port 3000')
})

4.OutgoingMessage

http.OutgoingMessageNode.jsHTTP 模块的一个类,它代表可以从 Node.js 应用程序发送到客户端或服务器的 HTTP 响应消息或请求消息。

应用场景

  1. 服务器端:当你创建一个 HTTP 服务器并使用 http.createServer() 处理客户端的请求时,响应对象 reshttp.ServerResponse 类的实例,而 http.ServerResponse 是继承自 http.OutgoingMessage 的。

  2. 客户端:当你使用 http.request()http.get() 发送 HTTP 请求时,返回的请求对象(即 http.ClientRequest 实例)也是继承自 http.OutgoingMessage 的。

主要属性和方法

  1. chunkedEncoding: 表示是否启用了分块传输编码。当你使用 res.write()req.write() 发送数据时,如果不知道内容的总长度,可以启用分块编码。

  2. finished: 表示消息是否已发送完成。

  3. headersSent: 表示是否已发送 HTTP 头部。通常在发送消息体数据之前发送头部。

  4. setHeader(name, value): 设置 HTTP 头部信息。name 是头部的名称,value 是头部的值。

  5. getHeader(name): 获取指定名称的 HTTP 头部值。

  6. removeHeader(name): 移除指定名称的 HTTP 头部信息。

  7. write(chunk, [encoding], [callback]): 向消息体写入数据块。chunk 是要写入的数据,encoding 是可选的编码方式,callback 是写入完成后的回调函数。

  8. end([data], [encoding], [callback]): 表示消息的结束。可以选择在调用 end() 时发送最后一块数据。data 是要发送的数据,encoding 是数据的编码,callback 是可选的回调函数。

  9. addTrailers(headers): 在消息末尾添加 HTTP 头部的尾部信息(通常用于分块传输编码)。

js
const http = require('http')

const server = http.createServer((req, res) => {
  // 设置响应头
  res.setHeader('Content-Type', 'text/plain')
  res.setHeader('X-Custom-Header', 'CustomHeaderValue')

  // 写入响应主体数据
  res.write('Hello, ')
  res.write('world!\n')

  // 结束响应并发送剩余数据
  res.end('Goodbye!\n')
})

server.listen(3000, () => {
  console.log('Server listening on port 3000')
})

5.Server

http.Server 主要方法和属性:

  1. server.listen(port[, hostname][, backlog][, callback]): 使服务器开始监听指定的端口和主机名。callback 是一个可选的回调函数,当服务器开始监听时触发。

  2. server.close([callback]): 关闭服务器,停止接收新的连接。callback 是一个可选的回调函数,当服务器完全关闭时触发。

  3. server.on(event, listener): 为服务器注册事件监听器。常见的事件包括:

  • request:每当有请求时触发。
  • connection:每当有新的 TCP 连接时触发。
  • close:服务器关闭时触发。
js
const http = require('http')

// 创建一个 HTTP 服务器
const server = http.createServer((req, res) => {
  // 设置响应头
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  
  // 设置响应内容
  res.end('Hello, World!\n')
})

// 监听端口 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Server running at http://127.0.0.1:3000/')
})

6.ServerResponse

http.ServerResponseNode.jsHTTP 模块的一部分,用于表示服务器向客户端发送的响应。

它提供了各种方法和属性,允许你构建和发送 HTTP 响应,包括设置状态码、响应头、以及发送响应数据。

主要方法

  1. res.writeHead(statusCode[, statusMessage][, headers]):
  • 设置响应的状态码、状态消息和响应头。
  • 例如:res.writeHead(200, {'Content-Type': 'text/html'});
  1. res.write(chunk[, encoding][, callback]):
  • 发送响应体的一部分数据。可以多次调用这个方法来发送响应体的不同部分。
  • 例如:res.write('<h1>Hello, World!</h1>');
  1. res.end([data][, encoding][, callback]):
  • 结束响应。data 是可选的,可以在结束响应时发送最后一块数据。
  • 例如:res.end('Goodbye!');
  1. res.setHeader(name, value):
  • 设置单个响应头。
  • 例如:res.setHeader('Content-Type', 'application/json');
  1. res.getHeader(name):
  • 获取指定的响应头值。
  • 例如:const contentType = res.getHeader('Content-Type');
  1. res.removeHeader(name):
  • 移除指定的响应头。
  • 例如:res.removeHeader('Content-Type');
  1. res.writeContinue():
  • 发送 100 ContinueHTTP 响应。
  1. res.addTrailers(headers):
  • 添加 HTTP trailers,这些是在消息体之后发送的额外头。

属性

  1. res.statusCode:
  • 获取或设置响应的状态码。
  • 例如:res.statusCode = 404;
  1. res.statusMessage:
  • 获取或设置响应的状态消息。
  • 例如:res.statusMessage = 'Not Found';
  1. res.headersSent:
  • 如果响应头已发送,则返回 true
  1. res.finished:
  • 如果响应已结束(res.end() 被调用),则返回 true

7.createServer

http.createServerNode.js 中的一个方法,用于创建一个 HTTP 服务器。

这个服务器能够监听客户端的 HTTP 请求,并发送响应。

js
const http = require('http')

const server = http.createServer((req, res) => {
  // req 是 http.IncomingMessage 的实例,表示客户端的请求
  // res 是 http.ServerResponse 的实例,用于向客户端发送响应
  console.log('createServer', req.url)
  res.statusCode = 200 // 设置响应状态码
  res.setHeader('Content-Type', 'text/plain') // 设置响应头
  res.end('Hello, World!\n') // 结束响应并发送内容
})

server.on('request', (req, res) => {
  console.log('request', req.url)
})

server.listen(3000, () => {
  console.log('服务器正在监听端口 3000')
})

8.validateHeaderName

http.validateHeaderNameNode.js 中的一个内部方法,用于验证 HTTP 头部字段的名称是否符合 HTTP/1.1 规范。

  • 如果 name 是合法的 HTTP 头部字段名称,这个函数不会返回任何内容。
  • 如果 name 不合法,它将抛出一个 TypeError,指出无效的头部名称。

合法的 HTTP 头部字段名称

根据 HTTP/1.1 规范,头部字段名称必须符合以下规则:

  • 仅包含 ASCII 字符。
  • 只能由字母(a-z,A-Z)、数字(0-9)、连字符(-)和下划线(_)组成。
  • 不允许空格或其他特殊字符。
js
const http = require('node:http')

console.log(http.validateHeaderName('Content-Type'))

console.log(http.validateHeaderName('Content.Type'))

console.log(http.validateHeaderName('Content&Type'))

console.log(http.validateHeaderName('Content Type'))

9.validateHeaderValue

http.validateHeaderValueNode.js 中的一个内部方法,用于验证 HTTP 头部字段的值是否符合 HTTP/1.1 规范。

http.validateHeaderName 类似,这个方法主要用于确保设置的 HTTP 头部字段值是合法的。

参数:

  1. name: 一个字符串,表示 HTTP 头部字段的名称。
  2. value: 一个字符串,表示 HTTP 头部字段的值。

行为:

  1. 如果 value 是合法的 HTTP 头部字段值,这个函数不会返回任何内容。
  2. 如果 value 不合法,它将抛出一个 TypeError,指出无效的头部值。
js
const http = require('http');

console.log(http.validateHeaderValue('Content-Type', 'text/html'))

// console.log(http.validateHeaderValue('Content-Type'))

console.log(http.validateHeaderValue('Content-Type', 'text/html\n'))

10.get

http.getNode.js 提供的一个简化方法,用于发起 HTTP GET 请求。

http.request 不同,http.get 专门用于 GET 请求,并且不需要手动调用 req.end()。它会自动完成请求的结束和发送。

js
const http = require('http')

// 使用 http.get 发起 GET 请求
http.get('http://www.example.com', (res) => {
  console.log(`状态码: ${res.statusCode}`)

  // 监听数据事件
  res.on('data', (chunk) => {
    console.log(`响应体: ${chunk}`)
  })

  // 监听结束事件
  res.on('end', () => {
    console.log('响应结束')
  })
}).on('error', (e) => {
  console.error(`请求遇到问题: ${e.message}`)
})

11.request

http.requestNode.js 中用于发起 HTTP 请求的一个方法。

适用于需要发送各种 HTTP 方法(如 POST、PUT、DELETE 等)以及需要自定义请求头和其他参数的场景。

之所以使用 res.on('data') 监听:

Node.js 中,HTTP 响应是以数据流(stream)的形式传输的。

数据流的传输方式意味着响应内容并不是一次性到达,而是以小块(chunk)的形式逐步传输。

当服务器向客户端发送数据时,这些数据会被拆分成一个个的块,data 事件在每个块到达时触发。

js
const http = require('http')

// 请求数据
const postData = JSON.stringify({
  'msg': 'Hello World'
})

// 请求选项
const options = {
  hostname: 'www.example.com',
  port: 80,
  path: '/post',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(postData)
  }
}

// 发起请求
const req = http.request(options, (res) => {
  console.log(`状态码: ${res.statusCode}`)
  
  // 监听数据事件
  res.on('data', (chunk) => {
    console.log(`响应体: ${chunk}`)
  })

  // 监听结束事件
  res.on('end', () => {
    console.log('响应结束')
  })
})

// 监听错误事件
req.on('error', (e) => {
  console.error(`请求遇到问题: ${e.message}`)
})

// 写入请求数据
req.write(postData)

// 结束请求
req.end()

12.setMaxIdleHTTPParsers

http.setMaxIdleHTTPParsersNode.js 中的一个内部方法,用于设置最大空闲 HTTP 解析器的数量。

这个方法在 Node.jsHTTP 模块中用于管理连接池中的 HTTP 解析器,以提高性能和资源管理。

在处理 HTTP 请求时,Node.js 使用 HTTP 解析器来解析传入的请求数据。

为了优化性能,Node.js 会维护一个解析器池(parser pool),以便可以重复使用这些解析器,而不是每次都创建新的解析器。

当连接关闭时,解析器可以被释放并返回池中,等待下一个请求。

http.setMaxIdleHTTPParsers 方法允许你设置池中可以保留的空闲解析器的最大数量。

超出这个数量的解析器将被销毁,而不是保留在池中等待下一次使用。

js
const http = require('http')

// 设置最大空闲 HTTP 解析器数量为 10
http.setMaxIdleHTTPParsers(10)

13.maxHeaderSize

http.maxHeaderSize 是用于获取 HTTP 头部的大小限制。

  • 安全性: 适当的头部大小限制有助于保护服务器免受头部攻击(例如,过大的头部数据)。

  • 性能: 设置合理的头部大小限制可以帮助平衡性能和资源使用,避免服务器因处理过大的头部数据而变得缓慢或不稳定。

  • 应用需求: 根据应用的需求和预期的请求头部大小,调整 maxHeaderSize 的值。对于大多数应用程序,默认值已经足够。

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

console.log(http.maxHeaderSize / 1024) // kb

14.globalAgent

http.globalAgentNode.js 中的一个全局代理对象,用于处理所有 HTTP 请求的代理设置。

它是 http.Agent 类的一个实例,主要用于管理连接池和连接复用。

作用:

  1. 连接池: http.globalAgent 管理一个全局的连接池,重用和管理与同一主机的连接,以提高性能。
  2. 代理设置: 通过设置代理配置,可以控制 HTTP 请求的行为,如代理服务器的使用等。

属性:

  1. maxSockets: 该属性指定了全局代理能够同时保持的最大连接数。默认为 10。你可以调整这个值来限制并发连接的数量。
  2. maxFreeSockets: 该属性指定了在连接池中保持的最大空闲连接数。默认值通常是 256
  3. keepAlive: 这是一个布尔值,指示是否启用 Keep-Alive 功能(持久连接)。默认为 true
  4. keepAliveMsecs: 指定连接在关闭之前应保持空闲的毫秒数。默认为 1000 毫秒(1 秒)。

方法:

  1. addRequest(req, socket): 用于将一个新的请求添加到代理中。
  2. destroy(): 销毁所有连接并关闭代理。
js
const http = require('http')

// 修改全局代理设置
http.globalAgent.maxSockets = 20 // 允许最多 20 个并发连接
http.globalAgent.keepAlive = true // 启用 Keep-Alive 功能