基于Fastify的NestJS应用配置HTTP/HTTPS端口遇问题求助
问题描述
我本地运行一个基于Fastify的容器化NestJS应用,需要配置外部第三方服务向应用的部分端点推送数据。目前应用通过HTTP监听3000端口,但第三方服务采用客户端认证,他们提供了PFX文件和密码,我想用这些配置一个监听3333端口的HTTPS端口。本地测试时,Thunderclient和Postman均报错:
- Postman: 客户端网络套接字在安全TLS连接建立前断开
- Thunderclient: 连接被对等方强制关闭
我请求的地址是https://localhost:3333/endpoint/。
以下是实现HTTPS之前的main.ts代码:
import { NestFactory } from '@nestjs/core'; import { NestFastifyApplication } from '@nestjs/platform-fastify'; import { AppModule } from './app.module'; import { utilities as nestWinstonModuleUtilities, WinstonModule, } from 'nest-winston'; import * as winston from 'winston'; import * as winstonDailyRotateFile from 'winston-daily-rotate-file'; async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>(AppModule, { logger: globalLogger }); await app.startAllMicroservices(); await app.listen(3000); process.on('uncaughtException', function (err) { globalLogger.error(JSON.stringify(err, null, 2)) globalLogger.log("UNCAUGHT EXCEPTION: Node NOT Exiting..."); }); } const globalLogger = WinstonModule.createLogger({ // ... 日志配置 }) bootstrap();
已尝试方案
我参考了NestJS官方文档、相关GitHub问题和Stack Overflow讨论,尝试了多种配置,当前的main.ts代码如下:
import { NestFactory } from '@nestjs/core'; import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; import { AppModule } from './app.module'; import { httpsModule } from './httpsmodule/httpsmodule.module'; import { utilities as nestWinstonModuleUtilities, WinstonModule, } from 'nest-winston'; import * as winston from 'winston'; import * as winstonDailyRotateFile from 'winston-daily-rotate-file'; import { readFileSync, accessSync, constants } from 'fs'; async function bootstrap() { try { const userAuthCertificateFilePath = "/src/ssl/UserCloudAuth.p12"; accessSync(userAuthCertificateFilePath, constants.F_OK | constants.R_OK) const certificatePassword = "somePassword" const userAuthCertificateFilePath = process.env.CERTIFICATE_FILE_PATH; const certificatePassword = process.env.CERTIFICATE_PASSWORD; const httpsOptions = { pfx: readFileSync(userAuthCertificateFilePath), passphrase: certificatePassword } const httpApp = await NestFactory.create<NestFastifyApplication>( AppModule, { logger: globalLogger } ); await httpApp.startAllMicroservices(); const httpsApp = await NestFactory.create<NestFastifyApplication>( httpsModule, new FastifyAdapter({ https: httpsOptions }) ); await httpsApp.startAllMicroservices(); await httpApp.listen(3000); await httpsApp.listen(3333); process.on('uncaughtException', function (err) { globalLogger.error(JSON.stringify(err, null, 2)) globalLogger.log("UNCAUGHT EXCEPTION: Node NOT Exiting..."); }); } catch (error) { globalLogger.error(`Main: ${error}`) } } const globalLogger = WinstonModule.createLogger({ // ... 日志配置 }) bootstrap();
解决方案
1. 修复变量重复定义问题
当前代码重复定义了userAuthCertificateFilePath和certificatePassword,直接覆盖了硬编码值,若环境变量未设置会读取undefined路径引发错误。调整为:
// 优先使用环境变量,无值时 fallback 到默认配置 const userAuthCertificateFilePath = process.env.CERTIFICATE_FILE_PATH || "/src/ssl/UserCloudAuth.p12"; const certificatePassword = process.env.CERTIFICATE_PASSWORD || "somePassword";
2. 验证证书文件路径与权限
容器内路径可能和本地不一致,确保/src/ssl/UserCloudAuth.p12在容器中存在,且应用进程拥有读取权限。可在启动容器时挂载本地证书目录到对应路径,或在代码中增加路径存在性校验的错误提示。
3. 用单Nest实例监听多端口(推荐)
无需创建两个独立Nest应用实例,Fastify支持单实例同时监听HTTP和HTTPS端口,可共享模块、中间件和配置:
async function bootstrap() { const globalLogger = WinstonModule.createLogger({ // ... 日志配置 }); // 创建HTTP适配器与Nest应用 const httpAdapter = new FastifyAdapter(); const app = await NestFactory.create<NestFastifyApplication>( AppModule, httpAdapter, { logger: globalLogger } ); await app.startAllMicroservices(); // 配置HTTPS服务器选项 const httpsOptions = { pfx: readFileSync(userAuthCertificateFilePath), passphrase: certificatePassword }; const httpsServer = httpAdapter.getInstance().createServer(httpsOptions); // 监听HTTP和HTTPS端口,指定0.0.0.0允许外部访问 await app.listen(3000, '0.0.0.0'); await new Promise((resolve) => httpsServer.listen(3333, '0.0.0.0', resolve)); process.on('uncaughtException', function (err) { globalLogger.error(JSON.stringify(err, null, 2)) globalLogger.log("UNCAUGHT EXCEPTION: Node NOT Exiting..."); }); }
4. 检查HTTPS模块配置
若坚持使用独立的httpsModule,需确保该模块正确注册了需要暴露的端点,且无错误的中间件、守卫配置导致连接中断。
5. 本地测试排查
- 用
lsof -i :3333确认端口未被其他进程占用 - 若PFX证书为自签名或私有CA颁发,需在Postman/Thunderclient中导入证书信任,避免TLS验证失败
- 执行
curl -v https://localhost:3333/endpoint/查看详细连接日志,定位具体错误点
内容的提问来源于stack exchange,提问作者Abeer
相关产品推荐
相关产品推荐

