You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js v18 HTTPS模块报unsupported错误,v16运行正常

Node.js v18.4.0 下自定义HTTP客户端「Error: unsupported」兼容问题排查

问题背景

公司内部开发的HTTP客户端库单元测试在Node.js v16.16.0环境可正常运行,但切换到v18.4.0后,调用HttpClient.request请求https://www.google.com时抛出Error: unsupported错误,报错栈指向Client.ts第72行的requestMethod调用。

测试代码

// ~/http/tests/Client.spec.ts

import { HttpClient } from '../src';

describe('Standard HTTP Client', () => {
  const { request: http } = HttpClient;
  
  it('should save the response when a state is given', async () => {
    const response = await http({ method: 'GET', url: 'https://www.google.com' });
    
    expect(response).toBeDefined();
  });
});

v18报错信息

Error: unsupported

    at configSecureContext (node:internal/tls/secure-context:282:15)
    at Object.createSecureContext (node:_tls_common:117:3)
    at Object.connect (node:_tls_wrap:1624:48)
    at Agent.createConnection (node:https:150:22)
    at Agent.createSocket (node:_http_agent:346:26)
    at Agent.addRequest (node:_http_agent:297:10)
    at new ClientRequest (node:_http_client:322:16)
    at Client.request (node:https:360:10)
    at Client.promiseHandler (/home/user/projects/node/http/src/Client.ts:72:25)
    at new Promise (<anonymous>)

自定义Client类核心实现

// ~/http/src/Client.ts

import { request as http, ClientRequest, IncomingMessage } from 'http';
import { request as https } from 'https';

// 省略其他导入和类型定义

export class Client {
  // 省略其他属性和方法

  private promiseHandler(resolve: PromiseExecutor, reject: PromiseExecutor): void {
    const { requestOptions: { body, hasPayload = false, ...rest } } = Object.assign(this, { resolve, reject }) as this;
    // 报错指向该行的requestMethod调用
    this.request = this.requestMethod(rest, this.boundRequestHandler).on('error', this.boundRequestErrorHandler);
    
    if(hasPayload) {
      this.request.write(body);
    }

    this.request.end();
  }

  get requestMethod(): RequestMethod {
    if(this.isSecure) {
      return https;
    }

    return http;
  }

  // 省略其他方法
}

排查分析

从报错栈可知,错误源于Node.js内部TLS安全上下文配置逻辑。结合版本差异,核心原因是:

  • Node.js v18开始严格校验HTTPS请求选项的字段合法性,非标准字段会直接触发「unsupported」错误
  • v16及更早版本会自动忽略请求选项中的非标准字段,不会报错
  • 当前代码中,promiseHandler方法将HttpRequest类中的自定义字段(如hasPayload、url等)通过rest对象直接传递给https.request,违反了v18的校验规则

解决方案

需要过滤掉请求选项中的自定义非标准字段,仅保留Node.js官方定义的http.RequestOptions/https.RequestOptions字段:

修改Client.ts的promiseHandler方法

private promiseHandler(resolve: PromiseExecutor, reject: PromiseExecutor): void {
  // 解构时分离出自定义字段与标准请求选项
  const { requestOptions: { body, hasPayload = false, url, protocol, ...standardOptions } } = Object.assign(this, { resolve, reject }) as this;
  // 仅传递标准选项给requestMethod
  this.request = this.requestMethod(standardOptions, this.boundRequestHandler).on('error', this.boundRequestErrorHandler);
  
  if(hasPayload) {
    this.request.write(body);
  }

  this.request.end();
}

额外注意

如果HttpRequest类中还有其他自定义扩展字段,需全部从standardOptions中排除,确保传递给http/https.request的参数完全符合Node.js官方文档定义的格式。

内容的提问来源于stack exchange,提问作者Solonotix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:06:25