npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lark-apaas/nestjs-http-forwarder

v0.1.3

Published

FullStack Nestjs server-side HTTP request forwarder (node egress, mihomo-aware)

Readme

@lark-apaas/nestjs-http-forwarder

NestJS 模块:通用内网转发能力。自动注册 controller,把请求的出口从浏览器变成 node。

⚠️ SDK 不感知代理 / 鉴权 / 隧道。实际客户内网访问的代理 / JWT / 隧道路由由部署环境(如沙箱内的 mihomo 透明代理 + iptables 拦截)处理。

⚠️ SDK 不内置鉴权 guard。消费方在 AppModule 层面给路由加自己的 guard(如全局 NeedLoginGuard)。

自动注册的接口

ALL  /api/__platform__/http-forward?targetUrl=<内网 URL>
  • method:取自请求自身(GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS)
  • targetUrl:query 参数
  • headers:自动透传(剔除 host / content-length / hop-by-hop)
  • body:自动透传
  • 响应:上游 status / headers / body 直接投射到 HTTP response

路径硬编码 /api/__platform__/http-forward,不可配置(保证所有消费方调用方式一致)。

使用

1. 注册模块

import { Module } from '@nestjs/common';
import { HttpForwarderModule } from '@lark-apaas/nestjs-http-forwarder';

@Module({
  imports: [
    HttpForwarderModule.forRoot({
      // 全部可选
      requestTimeoutMs: 30_000,
      maxResponseBytes: 10 * 1024 * 1024,
      proxyAuth: { commandTimeoutMs: 5_000 }, // 调优代理鉴权刷新
    }),
  ],
})
export class AppModule {}

2. 前端调用(搭配 axiosForBackend

import { axiosForBackend } from '@lark-apaas/client-toolkit';

// GET 内网接口
const res = await axiosForBackend.get('/api/__platform__/http-forward', {
  params: { targetUrl: 'http://api.corp.com/v1/users' },
});

// POST 内网接口
await axiosForBackend.post('/api/__platform__/http-forward', { qty: 3 }, {
  params: { targetUrl: 'http://api.corp.com/v1/orders' },
});

// 其他 method 同理
await axiosForBackend.delete('/api/__platform__/http-forward', {
  params: { targetUrl: 'http://api.corp.com/v1/orders/42' },
});

前端拿到的就是真实上游响应:response.statusresponse.headersresponse.data 跟直连内网一样。

3. 自定义编排(高级用法)

如果默认 controller 行为不够灵活,可以直接注入 service 写自己的 controller:

import { Body, Controller, Post } from '@nestjs/common';
import {
  HttpForwarderService,
  type ForwardRequestDto,
} from '@lark-apaas/nestjs-http-forwarder';

@Controller('my/custom')
export class MyController {
  constructor(private readonly forwarder: HttpForwarderService) {}

  @Post()
  async forward(@Body() body: ForwardRequestDto) {
    return this.forwarder.forward(body);
  }
}

ForwardRequestDto / ForwardResponseDto

import type { Readable } from 'node:stream';
import type { IncomingHttpHeaders } from 'undici/types/header';

interface ForwardRequestDto {
  method: string;             // 由 undici 自身校验
  targetUrl: string;          // 必须 http:// 或 https://
  headers?: Record<string, string>;
  body?: string | null;
}

interface ForwardResponseDto {
  status: number;
  headers: IncomingHttpHeaders; // Record<string, string | string[] | undefined>
                                // 多值字段(set-cookie / link / via)保留数组
  body: Readable;               // 未消费的可读流;调用方 pipe / for-await 消费
}

0.2.0 BREAKINGheaders 形态从 Record<string, string> 改为 IncomingHttpHeadersbodystring 改为 Readable。详情见 docs/plans/2026-05-09-http-forwarder.md Phase 3

配置参考

| 字段 | 必填 | 默认 | 说明 | |------|------|------|------| | requestTimeoutMs | — | 30000 | 单次请求超时(AbortController) | | maxResponseBytes | — | 10485760 (10 MB) | 上游响应体最大字节数;超阈值返回 502 RESPONSE_TOO_LARGE | | proxyAuth | — | undefined | v0.3.0 起,出网代理鉴权机制始终启用(按 appId 拉 jwtToken + updateProxyCmd,exec 后定时刷新)。SDK 不感知具体代理实现。本字段仅用于覆盖调优默认值,不传则全用默认。详见 docs/api/nestjs-http-forwarder.md |

service 做的 6 件核心事

| # | 能力 | 说明 | |---|------|------| | 1 | 协议白名单 | targetUrl 仅允许 http:// / https://(防 SSRF) | | 2 | host / content-length 接管 | host 重写为 targetUrl.host;content-length 让 undici 自算 | | 3 | 超时控制 | AbortController + setTimeout 默认 30s;undici 自带 Headers/Body/Connect Timeout 也兜底 | | 4 | 响应体大小上限 | 第一层 content-length 预检超阈值直接 502;第二层 Transform 流中累计字节,超阈值 destroy 流 | | 5 | 错误码映射 | undici 抛错按 signal.aborted / 错误类(HeadersTimeout / InvalidArgument)/ err.code 等结构化信号映射 | | 6 | 出网代理 | EnvHttpProxyAgentHTTP_PROXY / HTTPS_PROXY / NO_PROXY env 注入 dispatcher |

method 白名单 / body 类型校验 / payload 非空校验等都没做——交给 undici 自身(undici 对配置错抛 InvalidArgumentError,由 SDK 映射为 400 INVALID_REQUEST)。

错误码

| HTTP | code | 含义 | |------|------|------| | 400 | INVALID_REQUEST | targetUrl 缺失/非法 URL / undici 抛 InvalidArgumentError(method/headers 配置错) | | 400 | INVALID_TARGET_PROTOCOL | targetUrl 协议非 http/https | | 502 | UPSTREAM_UNREACHABLE | 上游不可达 / 网络错(err.code ∈ ENOTFOUND / ECONNREFUSED / ETIMEDOUT / UND_ERR_*) | | 502 | RESPONSE_TOO_LARGE | 上游响应体超 maxResponseBytes。预检命中时整次请求 502;流中累计兜底时 status 已发出,连接被切断(client 看到截断) | | 504 | UPSTREAM_TIMEOUT | 单次请求超时(controller.signal.aborted 或 undici HeadersTimeoutError / BodyTimeoutError / ConnectTimeoutError) |

上游 4xx / 5xx 不抛错,原样投射到 HTTP response。

限制(v0.3.0)

  • 请求体(ForwardRequestDto.body)仍仅支持 string / null(binary / FormData / 流上传待后续版本)
  • 响应体流式 pipe 到下游 response,不做 buffer,不支持改写 / 重试
  • 默认 controller 路径固定 /api/__platform__/http-forward,路径自定义请走自定义 controller
  • proxyAuth 始终启用,每个进程严格只服务一个 appId(沙箱-per-app);不同 appId 的请求会被拒绝。消费方必须提供 @lark-apaas/nestjs-commonRequestContextService + PLATFORM_HTTP_CLIENT