http-status vs http-status-code vs http-status-codes vs statuses
Node.js HTTP 状态码库选型与架构对比
http-statushttp-status-codehttp-status-codesstatuses

Node.js HTTP 状态码库选型与架构对比

http-status、http-status-code、http-status-codes 和 statuses 都是用于在 JavaScript 项目中处理 HTTP 状态码的工具库。它们的核心功能相似:提供状态码与文本描述之间的映射,以及判断状态码类别的辅助方法。然而,它们在 API 设计风格、维护状态和生态系统集成度上存在显著差异。http-status-codes 是目前社区最活跃、功能最全面的现代选择;statuses 是 Node.js 核心生态(如 Express、Koa)的首选轻量级依赖;而 http-status 和 http-status-code 则因维护停滞或 API 设计过时,已不再推荐用于新的生产环境项目。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
http-status0483338 kB52 年前BSD-3-Clause
http-status-code07-0-MIT
http-status-codes01,122223 kB323 年前MIT
statuses028312.5 kB71 年前MIT

HTTP 状态码库深度对比:从架构选型到实战陷阱

在 Node.js 生态中,处理 HTTP 状态码看似简单,实则关乎代码的可读性、类型安全以及长期维护成本。http-status、http-status-code、http-status-codes 和 statuses 这四个库虽然目标一致,但在设计哲学和实际表现上却大相径庭。作为架构师,我们需要透过表面的功能列表,深入理解它们的内部机制和适用场景。

🏛️ 核心架构与维护现状

选择第三方库的首要原则是生命力。一个停止维护的库不仅是技术债,更是安全隐患。

http-status-codes 是目前生态中的佼佼者。它由社区积极维护,定期更新以包含最新的 HTTP 标准状态码(如 103 Early Hints)。其架构设计清晰,将常量定义与工具函数分离,既保证了运行时的性能,又提供了良好的开发体验。

// http-status-codes: 活跃的维护与清晰的常量
import { StatusCodes } from 'http-status-codes';

console.log(StatusCodes.OK); // 200
console.log(StatusCodes.SERVICE_UNAVAILABLE); // 503

statuses 走的是极简主义路线。它被广泛集成在 Express、Koa 等核心框架内部。它的代码库非常小,几乎没有任何外部依赖,专注于“码转文本”这一单一职责。这种设计使其成为底层基础设施的理想选择。

// statuses: 极简主义,框架级集成
import statuses from 'statuses';

console.log(statuses[200]); // 'OK'
console.log(statuses.message[404]); // 'Not Found'

http-status 和 http-status-code 则显得步履蹒跚。http-status 虽然仍可使用,但更新缓慢,缺乏对现代 TypeScript 项目的友好支持。而 http-status-code 基本上已经处于废弃状态,其 API 设计存在歧义,且在处理边缘情况时表现不稳定。

// http-status: 较旧的常量定义方式
import httpStatus from 'http-status';

console.log(httpStatus.OK); // 200
// 注意:其命名空间和导出方式在现代打包工具中可能不够优化
// http-status-code: 不推荐,API 设计混乱
// 示例展示其过时的用法,实际项目中应避免
const code = require('http-status-code');
console.code(200); // 这种链式或全局污染的设计已过时

🔍 功能深度对比:反向查找与类别判断

在实际开发中,我们不仅需要将常量转换为数字,经常还需要根据数字反查描述,或者判断状态码的类别(如是否属于服务器错误)。

http-status-codes 提供了最全面的工具集。它不仅支持双向查找,还提供了语义化的谓词函数(如 isSuccess),这让业务逻辑代码读起来像自然语言。

// http-status-codes: 强大的工具函数
import { getReasonPhrase, isSuccess, isServerError } from 'http-status-codes';

// 反向查找:数字 -> 文本
console.log(getReasonPhrase(418)); // "I'm a teapot"

// 类别判断:语义化清晰
if (isServerError(responseCode)) {
  logError(responseCode);
}

statuses 在这方面的功能较为基础。它主要通过数组索引进行反向查找,没有内置复杂的类别判断函数。开发者通常需要自己编写简单的逻辑来判断范围,这在一定程度上增加了样板代码,但也换来了极致的轻量。

// statuses: 基础的反向查找
import statuses from 'statuses';

// 反向查找
console.log(statuses[500]); // "Internal Server Error"

// 类别判断需手动实现
if (code >= 500 && code < 600) {
  // 手动处理服务器错误
}

http-status 提供了一些辅助方法,但其命名风格不够统一,且缺乏像 http-status-codes 那样完善的类型推导支持。在 TypeScript 项目中,这往往导致需要额外的类型断言,降低了开发效率。

// http-status: 有限的辅助功能
import httpStatus from 'http-status';

// 反向查找
console.log(httpStatus.getStatusText(404)); // "Not Found"
// 缺乏内置的 isClientError 等语义化函数

http-status-code 的 API 设计最为令人困惑。它试图在一个对象上挂载所有功能,导致命名空间污染,且在反向查找时的行为在不同版本间不一致,极易引发运行时错误。

// http-status-code: 不稳定的 API
const httpCode = require('http-status-code');

// 这种调用方式缺乏类型安全,且容易出错
console.log(httpCode.getMessage(502)); 

🛡️ 类型安全与现代开发体验 (DX)

对于现代前端和全栈团队来说,TypeScript 支持是选型的决定性因素之一。

http-status-codes 原生提供了高质量的 .d.ts 类型定义文件。当你输入 StatusCodes. 时,IDE 会自动提示所有可用的状态码常量,并且在编译阶段就能捕获非法的状态码使用。这对于大型项目的重构至关重要。

// http-status-codes: 完美的 TS 支持
import { StatusCodes } from 'http-status-codes';

// TS 会提示所有可用的常量
const code: StatusCodes = StatusCodes.NOT_FOUND; 

// 如果尝试赋值不存在的属性,TS 会报错
// const invalid = StatusCodes.INVALID_CODE; // Error

statuses 的类型定义通常由社区维护(@types/statuses),虽然质量不错,但由于库本身设计简单,类型定义也相对基础,主要覆盖索引访问。

// statuses: 社区类型定义
import statuses from 'statuses';

// 类型推断基于数字索引
const message: string | null = statuses[404];

http-status 的类型支持参差不齐。在较新的 TypeScript 版本中,可能会遇到类型推断不准确的问题,尤其是在处理其导出的枚举或常量对象时。

http-status-code 基本没有有效的类型支持,强行在 TS 项目中使用会导致大量的 any 类型泛滥,完全丧失了类型安全的优势。

🚀 性能与打包体积考量

虽然这几个库都很小,但在微服务或 Serverless 环境中,每一字节的体积和毫秒级的启动时间都至关重要。

statuses 是绝对的王者。它的源代码极其精简,没有多余的逻辑分支。如果你的应用对冷启动时间极其敏感(如 AWS Lambda),或者你已经在用 Express/Koa(它们内部已依赖此库),直接使用 statuses 可以避免重复依赖,进一步减小体积。

http-status-codes 体积稍大,因为它包含了更多的工具函数和映射表。但在绝大多数 Web 应用中,这点体积差异可以忽略不计。它通过 Tree-shaking 支持,允许你只导入需要的部分,从而优化最终打包结果。

// http-status-codes: 支持 Tree-shaking
// 只导入需要的函数,减少打包体积
import { getReasonPhrase } from 'http-status-codes';

http-status 和 http-status-code 由于代码结构较老,往往难以进行有效的 Tree-shaking,可能导致打包工具引入不必要的代码。

💡 实战场景推荐

场景一:构建通用的 API 响应封装

你需要一个健壮的响应类,能够自动处理各种状态码的描述和分类。

✅ 推荐:http-status-codes 理由:语义化的 isSuccess、isRedirect 等函数能让逻辑判断一目了然,且类型安全能保证状态码的正确使用。

import { StatusCodes, getReasonPhrase, isSuccess } from 'http-status-codes';

class ApiResponse {
  constructor(code, data) {
    if (!isSuccess(code)) {
      console.warn(`Potential issue with status: ${getReasonPhrase(code)}`);
    }
    this.code = code;
    this.message = getReasonPhrase(code);
    this.data = data;
  }
}

场景二:底层框架中间件开发

你正在编写一个类似 Express 的底层中间件,需要快速获取状态码文本,且不能引入额外负担。

✅ 推荐:statuses 理由:极简、快速,且与 Node.js HTTP 模块的行为高度一致。

import statuses from 'statuses';

function sendRes(res, code) {
  const message = statuses[code] || 'Unknown';
  res.writeHead(code, message);
  // ...
}

场景三:遗留系统维护

你接手了一个三年前的老项目,里面大量使用了 http-status。

✅ 策略:逐步迁移 理由:不要立即重写,但在新模块中开始使用 http-status-codes。制定计划,逐步将旧的状态码常量替换为新库的常量,以利用更好的类型提示。

📊 总结对比表

特性http-status-codesstatuseshttp-statushttp-status-code
维护状态🟢 活跃🟢 活跃 (核心生态)🟡 缓慢🔴 废弃
API 设计现代、语义化极简、索引式传统、对象式混乱、过时
TypeScript⭐️ 原生完美支持⭐️ 社区支持良好⚠️ 支持一般❌ 几乎无支持
功能丰富度高 (含谓词函数)低 (仅映射)中低
打包体积小 (支持 Tree-shaking)极小中中
推荐指数⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️ (特定场景)⭐️⭐️❌

🎯 最终建议

在现代 Web 开发架构中,http-status-codes 应该是你的默认选择。它在功能、类型安全和维护性之间取得了最佳平衡,能够适应从简单脚本到复杂企业级应用的各种需求。

只有当你明确知道自己在做什么,比如正在开发底层网络库、极度关注体积,或者受限于现有的框架依赖(如 Express 内部机制)时,才考虑使用 statuses。

至于 http-status 和 http-status-code,请将它们视为历史遗留产物。在新的架构设计中,坚决避免引入这两个库,以免给未来的维护埋下隐患。技术选型不仅是选择功能,更是选择未来的维护成本和团队效率。

如何选择: http-status vs http-status-code vs http-status-codes vs statuses

  • http-status:

    不建议在新项目中选用 http-status。该库维护频率极低,API 设计较为陈旧,且功能集不如 http-status-codes 丰富。除非你是在维护一个强依赖此库的遗留系统,否则应迁移至更活跃的替代方案。

  • http-status-code:

    强烈避免使用 http-status-code。该库已长期停止维护,存在已知的设计缺陷,且 npm 社区普遍将其标记为过时。使用它可能会引入安全风险或兼容性問題,应立刻替换为 http-status-codes 或 statuses。

  • http-status-codes:

    如果你的项目需要最丰富的功能集(如获取所有状态码列表、自定义映射)且希望获得长期的社区维护,请选择 http-status-codes。它的 API 设计现代,支持 TypeScript 类型定义完善,且文档清晰,适合大多数现代前端和 Node.js 全栈项目。

  • statuses:

    如果你正在构建基于 Express、Koa 或 Connect 的服务端应用,或者极度关注包体积和依赖最小化,请选择 statuses。它是 Node.js 官方生态的事实标准,虽然功能单一(仅支持码转文本和类别判断),但性能极高且与其他核心中间件无缝集成。

http-status的README

HTTP Status codes for Node.js

Utility to interact with HTTP status codes.

Migration to v2.x

Version 2 is a migration of the library to ESM modules and TypeScript. The API remains the same. The build system generates both ESM and CommonJS exports.

For ESM users, the import remains the same.

import status from "http-status";
// Or
import { status } from "http-status";

For CommonJs users, update the require statement.

const { status } = require("http-status");
// Or
const { default: status } = require("http-status");

Usage

Once you import or require this module, you may call it with either an HTTP code or a status name. With an HTTP code, you will get the status name while with a status name you will get an HTTP code or some complementary information.

For example, status[418] return IM_A_TEAPOT while status.IM_A_TEAPOT return "I'm a teapot" and status.IM_A_TEAPOT_CODE returns 418.

The package is written in TypeScript and built for CommonJS and ESM.

HTTP Status codes

HTTP code names, information, and classes are respectively accessible with the property {code}_NAME, {code}_MESSAGE and {code}_CLASS. This includes all statuses in the IANA HTTP Status Code Registry, with the only addition being 418 I'm a teapot.

Extra codes

Extra status code are also made available that are not defined in the IANA registry, but used by popular softwares. They are grouped by category. Specific properties are exported by http-status under the property extra followed by the category name. Also, extra codes are merge with regular status codes and made available as modules available inside http-status/lib/{category}.

Available categories are:

unofficial
This represent a list of codes which are not specified by any standard.
iis
Microsoft's Internet Information Services (IIS) web server expands the 4xx error class to signal errors with the client's request.
nginx
The NGINX web server software expands the 4xx error class to signal issues with the client's request.
cloudflare
Cloudflare's reverse proxy service expands the 5xx error class to signal issues with the origin server.

They are accessible throught the status.extra[category] property. It is also possible to import one of the category with import status from "http-status/<category>" or const status = require("http-status/")`. In the later case, all the categories properties are merge with the common HTTP statuses.

HTTP Status code classes

In addition to HTTP status codes, this module also contains status code classes under the classes property. Similar to HTTP codes, you can access class names and messages with the property {class}_NAME and {class}_MESSAGE.

API organization

The API is structured as follows:

100
100_NAME
100_MESSAGE
100_CLASS
CONTINUE
101
101_NAME
101_MESSAGE
101_CLASS
SWITCHING_PROTOCOLS
…
classes.
├── 1xx
├── 1xx_NAME
├── 1xx_MESSAGE
├── INFORMATIONAL
├── 2xx
├── 2xx_NAME
├── 2xx_MESSAGE
├── SUCCESSFUL
├── …
extra.
├── unofficial.
│   ├── 103
│   ├── 103_NAME
│   ├── 103_MESSAGE
│   ├── 103_CLASS
│   ├── CHECKPOINT
│   ├── …
├── iis.
│   ├── 440
│   ├── 440_NAME
│   ├── 440_MESSAGE
│   ├── 440_CLASS
│   ├── LOGIN_TIME_OUT
│   ├── …
├── nginx.
│   ├── 444
│   ├── 444_NAME
│   ├── 444_MESSAGE
│   ├── 444_CLASS
│   ├── NO_RESPONSE
│   ├── …
├── cloudflare.
│   ├── 520
│   ├── 520_NAME
│   ├── 520_MESSAGE
│   ├── 520_CLASS
│   ├── UNKNOWN_ERROR
│   ├── …

For additional information, please refer to original code.

Example API usage

The api example illustrate how to access status names by code and number and how to extra various associated informations.

import status from "http-status";

console.info(status.INTERNAL_SERVER_ERROR);
// Output: 500

console.info(status[500]);
console.info(status[status.INTERNAL_SERVER_ERROR]);
// Both output: "Internal Server Error"

console.info(status["500_NAME"]);
console.info(status[`${status.INTERNAL_SERVER_ERROR}_NAME`]);
// Both output: "INTERNAL_SERVER_ERROR"

console.info(status["500_MESSAGE"]);
console.info(status[`${status.INTERNAL_SERVER_ERROR}_MESSAGE`]);
// Both output: "A generic error message, given when an unexpected condition was encountered and no more specific message is suitable."

console.info(status["500_CLASS"]);
console.info(status[`${status.INTERNAL_SERVER_ERROR}_CLASS`]);
// Both output: "5xx"

Example using classes

import status from "http-status";

const responseCode = status.INTERNAL_SERVER_ERROR;

switch (status[`${responseCode}_CLASS`]) {
  case status.classes.INFORMATIONAL:
    // The responseCode is 1xx
    break;
  case status.classes.SUCCESSFUL:
    // The responseCode is 2xx
    break;
  case status.classes.REDIRECTION:
    // The responseCode is 3xx
    break;
  case status.classes.CLIENT_ERROR:
    // The responseCode is 4xx
    break;
  case status.classes.SERVER_ERROR:
    // The responseCode is 5xx
    break;

  default:
    // Unknown
    break;
}

Example using the extra property

// Accessing property from the NGINX category
import status from "http-status";
console.info(status.extra.nginx.NO_RESPONSE);

// Accessing default HTTP status merged with NGINX status
import status from "http-status/lib/nginx";
console.info(status.IM_A_TEAPOT);
console.info(status.NO_RESPONSE);

Example integrating Express

The express example integrate the library with a real wold usage.

import express from "express";
import redis from "redis";
import status from "http-status";

// New Express HTTP server
const app = express.createServer();
// Regster a route
app.get("/", (req, res) => {
  const client = redis.createClient();
  client.ping((err, msg) => {
    if (err) {
      return res.send(status.INTERNAL_SERVER_ERROR);
    }
    res.send(msg, status.OK);
  });
});
// Start the HTTP server
app.listen(3000);

Contributors

The project is sponsored by Adaltas based in Paris, France. Adaltas offers support and consulting on distributed systems, big data and open source.

Developers

To automatically generate a new version:

npm run release

Package publication is handled by the CI/CD with GitHub action.