[英]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
// 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);
};
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.