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

如何正确整合NestJS应用与Azure Function HTTP触发器?

NestJS 整合 Azure Functions 控制器无法执行的问题解决

问题背景

NestJS应用在Azure Functions中能启动,但控制器无法执行,相关配置、版本及报错信息如下:

配置代码

import { app, HttpRequest, HttpResponseInit } from '@azure/functions';
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from '../app.module';

let appNest: INestApplication;

async function createAppNest() {
  if (!appNest) {
    appNest = await NestFactory.create(AppModule);
    await appNest.init();
  }
}

export async function httpTrigger(
  request: HttpRequest,
  context: any
): Promise<HttpResponseInit> {
  context.log('EJECUCIÓN FUNCIÓN');
  await createAppNest();

  const expressApp = appNest.getHttpAdapter().getInstance();
  const response = expressApp(request, context.res);

  return {
    status: 200,
    body: response,
  };
}

app.http('afiliacion', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: httpTrigger,
  route: '{*segments}',
});

版本信息

@azure/functions: 4.6.0
nestjs: 10.4.8
nodejs: 22.11.0

报错信息

[Nest] 20948  - 29/11/2024, 9:26:48 a. m.   ERROR [AllExceptionsFilter] Unexpected Error
[2024-11-29T14:26:48.953Z] [error] Worker uncaught exception (learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ): TypeError: Cannot read properties of undefined (reading 'status')     at AllExceptionsFilter.catch (C:\Users\amartinez\Downloads\Proyectos\servicio\dist\filters\http-exception.filter.js:54:29)     at ExceptionsHandler.invokeCustomFilters (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules@nestjs\core\exceptions\exceptions-handler.js:30:26)     at ExceptionsHandler.next (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules@nestjs\core\exceptions\exceptions-handler.js:14:18)     at C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules@nestjs\core\router\router-proxy.js:25:35     at Layer.handle_error (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\layer.js:71:5)     at trim_prefix (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\index.js:326:13)     at C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\index.js:286:9     at Function.process_params (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\index.js:346:12)     at next (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\index.js:280:10)     at Layer.handle_error (C:\Users\amartinez\Downloads\Proyectos\servicio\node_modules\express\lib\router\layer.js:67:12)
[2024-11-29T14:26:49.025Z] Language Worker Process exited. Pid=20948.

问题根源

报错核心是Azure Functions的context.res响应对象与Express期望的结构不匹配,直接传入会导致NestJS异常过滤器无法读取响应对象的status属性。同时,Express处理请求是异步回调模式,直接返回expressApp(request, context.res)无法正确获取响应结果。

正确整合方案

1. 确认依赖完整性

确保项目已安装@nestjs/platform-express(NestJS 10.x默认包含,若缺失可执行:npm install @nestjs/platform-express)。

2. 修改触发器代码,适配请求/响应

通过模拟Express兼容的请求、响应对象,将NestJS的输出转换为Azure Functions要求的HttpResponseInit格式:

import { app, HttpRequest, HttpResponseInit, Context } from '@azure/functions';
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import * as express from 'express';
import { AppModule } from '../app.module';

let appNest: INestApplication;
const expressInstance = express();

// 初始化NestJS应用,绑定到Express实例
async function createAppNest() {
  if (!appNest) {
    const adapter = new ExpressAdapter(expressInstance);
    appNest = await NestFactory.create(AppModule, adapter);
    await appNest.init();
  }
}

export async function httpTrigger(
  request: HttpRequest,
  context: Context
): Promise<HttpResponseInit> {
  context.log('EJECUCIÓN FUNCIÓN');
  await createAppNest();

  // 转换Azure请求为Express兼容格式
  const expressReq = Object.assign(request, {
    path: context.req.params.segments,
    originalUrl: `/${context.req.params.segments}`,
    headers: request.headers,
    method: request.method,
  });

  // 模拟Express响应对象,捕获NestJS输出
  let responseBody: any;
  let statusCode = 200;
  const expressRes = {
    status: (code: number) => ({
      json: (body: any) => {
        statusCode = code;
        responseBody = body;
      },
      send: (body: any) => {
        statusCode = code;
        responseBody = body;
      },
    }),
    json: (body: any) => {
      responseBody = body;
    },
    send: (body: any) => {
      responseBody = body;
    },
  };

  // 异步处理请求,等待Express回调完成
  await new Promise<void>((resolve) => {
    expressInstance(expressReq, expressRes, resolve);
  });

  // 返回符合Azure要求的响应格式
  return {
    status: statusCode,
    body: responseBody,
    headers: {
      'Content-Type': 'application/json',
    },
  };
}

app.http('afiliacion', {
  methods: ['GET', 'POST'],
  authLevel: 'anonymous',
  handler: httpTrigger,
  route: '{*segments}',
});

3. 调整自定义异常过滤器(若有)

如果项目中自定义了AllExceptionsFilter,需确保它能兼容模拟的响应对象结构,或者暂时改用NestJS默认的异常过滤器,避免因响应属性缺失报错。

4. 验证路由匹配

Azure Functions的route: '{*segments}'会将所有子路径传递到触发器,需确保NestJS控制器的路由与请求路径匹配。例如:

  • 若请求路径为/afiliacion/user,NestJS控制器需配置@Controller('')或@Controller('user')。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:53:10