Closed csakbalint closed 5 years ago
@csakbalint I just ran into this the other day. The problem is that given a swagger path of swagger
, swagger-ui-express serves its html file from /swagger/
and will redirect if the request path is /swagger
. Unfortunately API Gateway strips the trailing slash from the request path so you have to add it back with the block below.
if (event.path === '/swagger') {
event.path = '/swagger/';
}
This cannot be done as a middleware as req.path
from express is a getter and will throw an error if you try to overwrite it.
I have the similar problem. Swagger documentation doesn't work on AWS lambda using serverless framework. It works testing it locally (sls offline start
).
What is very strange, that only one file .js and doesn't have 404. Others does. I have no idea why.
Swagger API documentation: https://js6bdk1qg3.execute-api.eu-west-2.amazonaws.com/master/api
404: https://js6bdk1qg3.execute-api.eu-west-2.amazonaws.com/master/swagger-ui-bundle.js
200: https://js6bdk1qg3.execute-api.eu-west-2.amazonaws.com/master/swagger-ui-init.js
My part of configuration:
if (event.path === '/api') {
event.path = '/api/';
}
event.path = event.path.includes('swagger-ui') ? `/api${event.path}` : event.path;
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
export default (app, isServerless = false): void => {
const serverUrl = isServerless ? '/dev' : '/';
const options = new DocumentBuilder()
.setTitle(process.env.APP_NAME)
.setDescription(process.env.APP_DESC)
.setVersion('1.0')
.addServer(serverUrl)
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api', app, document);
};
@jtmthf @csakbalint would you have any idea?
Hi @plorencrstit , I am trying to use swagger with serverless and lambda functions. Can you explain how did you configure it ?
Hi @NastyZ98, what problem do you have?
Using TS and serverless-plugin-optimize
plugin I needed to add to my serverless.yml
configuration:
custom:
optimize:
external: ['swagger-ui-dist']
in lambda.ts
: [my handler]
export const handler: Handler = async (event: any, context: Context) => {
if (event.path === '/api') {
event.path = '/api/';
}
event.path = event.path.includes('swagger-ui') ? `/api${event.path}` : event.path;
cachedServer = await bootstrapServer();
return proxy(cachedServer, event, context, 'PROMISE').promise;
};
@plorencrstit hi, thank you for your reply,
I am trying to make swagger working on my aws lambda but it result of a 404 with sls offline
and of an error 500 when I deploy on aws.
I also added serverless-plugin-optimize
and edited my serverless.yml
but it looks like that serverless-plugin-optimize
broke something when I call: myawsurl/dev/api
Here is my lambda.ts
const binaryMimeTypes: string[] = [];
let cachedServer: Server;
process.on('unhandledRejection', reason => {
console.error(reason);
});
process.on('uncaughtException', reason => {
console.error(reason);
});
function setupSwagger(app: INestApplication) {
const options = new DocumentBuilder()
.setTitle('Tyffis API')
.setDescription('Tyffis REST API documentation')
.setVersion('1.0.0')
.addTag('tyffis')
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api', app, document);
}
async function bootstrapServer(): Promise<Server> {
if (!cachedServer) {
try {
const expressApp = express();
const adapter = new ExpressAdapter(expressApp);
const nestApp = await NestFactory.create(AppModule, adapter);
nestApp.use(eventContext());
await nestApp.init();
setupSwagger(nestApp);
cachedServer = createServer(expressApp, undefined, binaryMimeTypes);
} catch (error) {
return Promise.reject(error);
}
}
return Promise.resolve(cachedServer);
}
export const handler: Handler = async (event: any, context: Context) => {
if (event.path === '/api') {
event.path = '/api/';
}
event.path = event.path.includes('swagger-ui')
? `/api${event.path}`
: event.path;
cachedServer = await bootstrapServer();
return proxy(cachedServer, event, context, 'PROMISE').promise;
};
I had the same problem before with typeorm
. My solution was to manually listed entities in the configuration file. So I have two kind of settings.
entities: [`${__dirname}/../**/*.entity{.ts,.js}`],
...typeOrmConfigGeneral,
};
export const typeOrmConfigServerless: TypeOrmModuleOptions = {
entities: [
Category,
Comment,
Discussion,
],
...typeOrmConfigGeneral,
};
I choose the configuration based on some env
.
Do you use typeorm
?
Yes I use typeorm, your solution have fixed my problem concerning the entity :) ! But my swagger documentation still don't work..
Here is my serverless.yml
functions:
index:
handler: src/lambda.handler
events:
- http:
cors: true
path: '/{proxy+}'
method: any
Did I miss something in my lambda.ts
upper ?
Show the entire serverless.yml
, please.
Here it is:
service: tyffis-backend-test
provider:
name: aws
runtime: nodejs12.x
region: us-east-1
stage: dev
role: LambdaRole
memorySize: 512
vpc:
securityGroupIds:
- sg
subnetIds:
- ids
environment:
TYPEORM_HOST: ${self:custom.AURORA.HOST}
TYPEORM_PORT: ${self:custom.AURORA.PORT}
TYPEORM_USER: ${self:custom.USERNAME}
TYPEORM_PASSWORD: ${self:custom.PASSWORD}
TYPEORM_DB: ${self:custom.DB_NAME}
JWT_SECRET: secret
plugins:
- serverless-plugin-typescript
- serverless-plugin-optimize
- serverless-offline
package:
individually: true
custom:
DB_NAME: db_name
USERNAME: user
PASSWORD: pwd
AURORA:
HOST:
Fn::GetAtt: [AuroraRDSCluster, Endpoint.Address]
PORT:
Fn::GetAtt: [AuroraRDSCluster, Endpoint.Port]
optimize:
external: ['swagger-ui-dist']
resources:
Resources:
LambdaRole: ${file(./infra-serverless/LambdaRole.yml)}
AuroraRDSCluster: ${file(./infra-serverless/AuroraRDSCluster.yml)}
functions:
index:
handler: src/lambda.handler
events:
- http:
cors: true
path: '/{proxy+}'
method: any
All my other routes work, I have authentication flow with jwt, I have no problem with them
Try with:
functions:
main:
handler: src/lambda.handler
events:
- http:
method: any
path: /{any+}
It finally work !! 😄
The problem was here:
lambda.ts
await nestApp.init();
setupSwagger(nestApp);
I copied https://gist.github.com/csakbalint/7fe406bd1b15124180a988c87d57cf9b from the original author to make my test but nestApp init has to be call before the setupSwagger function..
setupSwagger(nestApp);
await nestApp.init();
Thank you very much for your time @plorencrstit ! I Appreciate it!
@csakbalint there is an error in your gist, look upper you switched your setupSwagger function with await nestApp.init(); one.
@plorencrstit Thank you very much, you saved my day!!
Hello guys! I have the same problem, but in serveless offline, the swagger works. When I access the aws endpoint, he didn't work. My lambda is similar of @nathanagez. Anyone can help me?
I'm submitting a...
Current behavior
Swagger endpoint is not found.
Expected behavior
Html response generated by swagger-ui.
Minimal reproduction of the problem with instructions
Here is an example I use in my project.
What is the motivation / use case for changing the behavior?
I'd like to generate swagger documents based on my modules and endpoints, but I cannot.
Environment