簡體   English   中英

NestJS Swagger 為 API 網關生成 UI

[英]NestJS Swagger UI generation for API Gateway

我在創建端點來服務 swagger 文檔時遇到問題。 我可以在本地執行的唯一方法是路徑末尾有雙斜杠localhost:3003/dev/swagger// 如果我省略其中一個正斜杠,它會為沒有/dev路徑localhost:3003/swagger返回 404。 部署后,API 網關將為 swagger 端點(帶或不帶// )返回{"message": "Forbidden"} 如何讓 API 網關/swagger端點返回 swagger UI?,我不確定我是否錯過了一些步驟。

下面是我的 NestJS 應用程序的 main.ts 以及 serverless.yml,這里是一個示例 repo,使用最少的設置來復制我的問題。 https://github.com/MRdgz/serverless-nestj-swagger

主.ts

// main.ts
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { configure as serverlessExpress } from '@vendia/serverless-express';
import { Callback, Context, Handler } from 'aws-lambda';
import { AppModule } from './app.module';

let server: Handler;

function setupSwagger(nestApp: INestApplication): void {
  const config = new DocumentBuilder()
    .setTitle('Sample API')
    .setDescription('Sample API Documentation')
    .setVersion('0.0.1')
    .addServer('/dev')
    .build();

  const document = SwaggerModule.createDocument(nestApp, config);

  SwaggerModule.setup('/swagger', nestApp, document, {
    customSiteTitle: 'Sample',
    swaggerOptions: {
      docExpansion: 'none',
      operationSorter: 'alpha',
      tagSorter: 'alpha',
    },
  });
}

async function bootstrap(): Promise<Handler> {
  const app = await NestFactory.create(AppModule);

  setupSwagger(app);
  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress({ app: expressApp });
}

export const handler: Handler = async (
  event: any,
  context: Context,
  callback: Callback,
) => {
  event.path = `${event.path}/`;
  event.path = event.path.includes('swagger-ui')
    ? `swagger${event.path}`
    : event.path;

  server = server ?? (await bootstrap());

  return server(event, context, callback);
};

無服務器.yml

service: sample-api

variablesResolutionMode: 20210326
useDotenv: true

plugins:
  - serverless-offline
  - serverless-plugin-optimize

# functions will inherit settings from provider properties if available,
provider:
  name: aws
  runtime: nodejs14.x
  lambdaHashingVersion: 20201221
  # memorySize: 1024 # default 1024 MB
  timeout: 30 # default 6 seconds
  # sls deploy --stage {stage} otherwise defaults to dev
  stage: ${opt:stage, 'dev'}

functions:
  main:
    handler: dist/main.handler
    name: ${opt:stage, 'dev'}-${self:service}
    events:
      - http:
          method: ANY
          path: /{proxy+}
          cors: true

custom:
  serverless-offline:
    httpPort: 3003
  optimize:
    external: ['swagger-ui-dist']

你可以在這里查看,這可能會給你一些想法,這就是我最終的結果:

const document = SwaggerModule.createDocument(app, config);
const forwardedPrefixSwagger = async (
    req: any,
    _: Response,
    next: NextFunction,
) => {
   req.originalUrl = (req.headers['x-forwarded-prefix'] || '') + req.url;
   next();
};
app.use(
   '/api/',
   forwardedPrefixSwagger,
   swaggerUi.serve,
   swaggerUi.setup(document),
);

我認為這里描述了這個問題serverless-http/issues/86

對我的情況有什么幫助(請注意:它仍然是一種解決方法;我只在本地檢查過npm run sls:offline ;這是一個簡化的示例)

  • serverless.yaml

我的自定義部分:

   plugins:
     - serverless-plugin-typescript
     - serverless-plugin-optimize
     - serverless-offline

   [...]

    custom:
      serverless-offline:
        noPrependStageInUrl: true    <----- this guy!
      optimize:
        external: ['swagger-ui-dist']

    [...]

    functions:
      main:
        handler: src/lambda.handler
     events:
        - http:
           method: ANY
           path: /
        - http:
           method: ANY
           path: '/{proxy+}'
  • lambda.ts

     import { AppModule } from './app.module'; import { Callback, Context, Handler } from 'aws-lambda'; import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import serverlessExpress from '@vendia/serverless-express'; import { INestApplication } from '@nestjs/common'; let cachedServer: Handler; async function bootstrap(): Promise<Handler> { const app = await NestFactory.create(AppModule); setupSwagger(app); await app.init(); const expressApp = app.getHttpAdapter().getInstance(); return serverlessExpress({ app: expressApp }); } export const handler: Handler = async ( event: any, context: Context, callback: Callback, ) => { cachedServer = cachedServer?? (await bootstrap()); return cachedServer(event, context, callback); }; function setupSwagger(app: INestApplication) { const options = new DocumentBuilder().setTitle('My API').setDescription('My application API').setVersion('1.0.0').addTag('#tag').build(); const document = SwaggerModule.createDocument(app, options); SwaggerModule.setup('api/swagger', app, document); }

結果是http://localhost:3000/api/swagger返回api頁面, http://localhost:3000/api默認處理

@Controller('api')
   @Get()

嘗試

functions:
  main:
    handler: dist/main.handler
    name: ${opt:stage, 'dev'}-${self:service}
    events:
      - httpApi: "*"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM