Swagger: Swagger module ignores setGlobalPrefix()

Created on 26 Jun 2018  路  19Comments  路  Source: nestjs/swagger

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior


When setting setGlobalPrefix('v2') and using the Swagger module as described in the doc with SwaggerModule.setup('api', app, document), the API is actually available under /api and /v2/api throws a 404 Cannot GET /v2/api.

It works when setting SwaggerModule.setup('v2/api', app, document), but this introduces duplication.

Expected behavior


I expected the global prefix to be applied to the Swagger module's path, too.

Minimal reproduction of the problem with instructions


Repro repo. Created with the CLI, only added swagger module as described in the doc and setGlobalPrefix().

Environment

Nest version: 5.0.1
question

Most helpful comment

@renatogbp try to change operations order.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api');

  const options = new DocumentBuilder()
    .setTitle('Example')
    .setDescription('The API description')
    .setVersion('1.0.0')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('swagger', app, document);

  await app.listen(3000);
}

All 19 comments

the DocumentBuilder has a method .setBasePath so you can set that to match your GlobalPrefix

@nartc, I just tried it and for me setBasePath() only sets the URL displayed as the "Base URL" in the swagger GUI. It does not seem to influence the routing, i. e. where the swagger is accessible.

Even if it were changing the base path, I would expect the SwaggerModule to respect the setGlobalPrefix() anyway, because otherwise it's not a global prefix. ;) I hope this clarifies what I meant.

That鈥檚 what I did for my app to work with a prefix (api). About swaggerModule not being aware of the globalPrefix, we鈥檙e gonna have to hear from Kamil

@nartc, on the repro branch using setBasePath(), can you access localhost:3000/v2/api? I can't. That is my problem. ;)

Just tried to reproduce this issue and for me, everything is working correctly. My code:

app.setGlobalPrefix('v1');
const options = new DocumentBuilder()
  .setBasePath('v1')
  .build();

It works when setting SwaggerModule.setup('v2/api', app, document), but this introduces duplication.

My understanding of this issue is that it shouldn't be necessary to use documentBuilder.setBasePath('v1') when app.setGlobalPrefix('v1') is given.

I agree you should not have to set:

app.setGlobalPrefix('/my/deep/path');
const options = new DocumentBuilder()
  .setBasePath('/my/deep/path')
  .build();
SwaggerModule.setup("/my/deep/path/api", app, document);

You should be able to do it this way:

app.setGlobalPrefix('/my/deep/path');
const options = new DocumentBuilder().build();
SwaggerModule.setup("api", app, document);

But that's just my $.02

I agree that SwaggerModule should detect setGlobalPrefix()s automatically. Manually adding it with setBasePath() fails when there are multiple modules with different global prefixes contained in a parent module. Here is a case

NestApplication1.setGlobalPrefix('module1');
NestApplication2.setGlobalPrefix('module2');

@Module({
  imports: [NestApplication1, NestApplication2],
})
export class ContainerModule {}

const app = await NestFactory.create(ContainerModule);
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api', app, document);

Here setBasePath() won't work because we have to do it multiple times which is not possible

I'm not sure if my issue is the same as this one, but my nestjs api runs in a subdirectory of a site

(e.q. www.domain.ext/some/path/nestjs )

Without setting the GlobalPrefix, the requests to that route are relatively mapped to be from the 'root'

(e.q. www.domain.ext/some/path/nestjs/todo => GET '/todo' )

So all the controller paths work just normally, but only the SwaggerModule which is setup like :

const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('docs', app, document);

redirects to www.domain.ext/docs, instead of my expected www.domain.ext/some/path/nestjs/docs

Fixed in 4.0.0. If you don't want to automatically include global prefix, you can use ignoreGlobalPrefix option (createDocument method, 3rd argument)

Can someone give an example, please? I have this setup and isn't working.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const options = new DocumentBuilder()
    .setTitle('Example')
    .setDescription('The API description')
    .setVersion('1.0.0')
    .build();
  const document = SwaggerModule.createDocument(app, options, {
    ignoreGlobalPrefix: false,
  });
  SwaggerModule.setup('swagger', app, document);

  app.setGlobalPrefix('api');
  await app.listen(3000);
}

Swagger is making the request without the /api prefix.
These are my dependencies:

"dependencies": {
    "@nestjs/common": "^6.7.2",
    "@nestjs/core": "^6.7.2",
    "@nestjs/platform-express": "^6.7.2",
    "@nestjs/swagger": "^4.0.9",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.0",
    "rxjs": "^6.5.3",
    "swagger-ui-express": "^4.1.2"
  },

@renatogbp try to change operations order.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api');

  const options = new DocumentBuilder()
    .setTitle('Example')
    .setDescription('The API description')
    .setVersion('1.0.0')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('swagger', app, document);

  await app.listen(3000);
}

@Arthesian did you find a solution ? I have the same problem.
Thx

@njournaud Unfortunately, no. We were not able to fix it. We were however, lucky enough that we were not restricted for our hosting, so we just changed the server/routing config in the end...

I would still like to know if it is possible in the way we had it set up before though

Thanks for the answer. It's seems to be a complicated problem. I don't know if in the SwaggerModule.setup we can get the url from the clientside :/

I'm also seeing this using @nestjs/[email protected] & [email protected].

Can we reopen the issue? From what I can see, and based on others' responses (and related issues), it's not or no-longer resolved.

Edit: addServer mentioned in #435 has worked for my needs.

I'm seconding @Arthesian issue. We deploy on google cloud where the app routes are always prefixed with something, e.g. app-1/, and we can't use Swagger at all thanks to that. If we set the Swagger path to /api then app-1/api redirects to /api and throws error.

If anyone ran into the issue @Arthesian pointed out - https://github.com/scottie1984/swagger-ui-express/issues/183 it actually fixed for me by using "/" at the end of the URL.

@renatogbp try to change operations order.

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api');

  const options = new DocumentBuilder()
    .setTitle('Example')
    .setDescription('The API description')
    .setVersion('1.0.0')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('swagger', app, document);

  await app.listen(3000);
}

app.setGlobalPrefix('api'); before swagger!!! It's help to me...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

patilrevansidh picture patilrevansidh  路  4Comments

KatSick picture KatSick  路  3Comments

alisherks picture alisherks  路  4Comments

kalaivanan-muthusamy picture kalaivanan-muthusamy  路  4Comments

cdiaz picture cdiaz  路  4Comments