Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration from @fastify/swagger 7 to 8 #957

Open
dargolith opened this issue Nov 4, 2023 · 10 comments
Open

Migration from @fastify/swagger 7 to 8 #957

dargolith opened this issue Nov 4, 2023 · 10 comments
Labels
help wanted Extra attention is needed

Comments

@dargolith
Copy link

💬 Question here

How do I migrate my current fastify-swagger from 7.x to 8.x (I have read the migration guide, but it is still not working)?

Directory structure:

...
src
|   index.js
swagger
│   index.yaml
│
├───definitions
│   ├───entities
│   │       Asset.yaml
│   │       ...
│   │
│   └───responses
│           500.yaml
│
└───paths
    ├───asset
    │       create.yaml
    │       delete.yaml
    │       read.yaml
    │       update.yaml
    ├─── ...
    ...
...

index.js (before, working fine with @fastify/swagger 7.4.1)

import { fastify } from 'fastify';
import fastifySwagger from '@fastify/swagger';
import fastifyCors from '@fastify/cors';
...

const start = async () => {
...
  console.info('Loading API...');
  const app = fastify({});
  app.get('/', (_, response) => response.redirect('/docs')); // default to swagger docs
  app.register(createApi(storage));
  app.register(fastifyCors, { origin: '*' });
  app.register(fastifySwagger, {
    mode: 'static',
    specification: { path: './swagger/index.yaml' },
    routePrefix: '/docs',
    exposeRoute: true,
  });
  console.info('API Loaded.');

  app.listen({ host: '0.0.0.0', port: SERVICE_PORT }, (error, address) => {
    if (error) {
      console.error(error);
      process.exit(1);
    }
    console.info(`Server started. Listening on ${address}`);
  });
};

index.js (now, not working)

import { fastify } from 'fastify';
import fastifySwagger from '@fastify/swagger';
import fastifySwaggerUi from '@fastify/swagger-ui';
import fastifyCors from '@fastify/cors';
...

const start = async () => {
...
  console.info('Loading API...');
  const app = fastify({});
  app.get('/', (_, response) => response.redirect('/docs')); // default to swagger docs
  app.register(createApi(storage));
  app.register(fastifyCors, { origin: '*' });
  app.register(fastifySwagger, {
    mode: 'static',
    specification: { path: './swagger/index.yaml' },
  });
  app.register(fastifySwaggerUi, {
    routePrefix: '/docs',
  });

  console.info('API Loaded.');

  app.listen({ host: '0.0.0.0', port: SERVICE_PORT }, (error, address) => {
    if (error) {
      console.error(error);
      process.exit(1);
    }
    console.info(`Server started. Listening on ${address}`);
  });
};
...

swagger/index.yaml

swagger: "2.0"
info:
  title: "My Service"
  description: >
    Service providing an API.
  version: "1.0.0"
schemes:
  - https
  - http
paths:
  # Asset
  /asset/create:
    $ref: ./paths/asset/create.yaml
  /asset/read:
    $ref: ./paths/asset/read.yaml
  /asset/update:
    $ref: ./paths/asset/update.yaml
  /asset/delete:
    $ref: ./paths/asset/delete.yaml

...

Errors in the UI:

Errors
 
Resolver error at paths./asset/create.$ref
Could not resolve reference: undefined Route GET:/docs/paths/asset/create.yaml not found
Resolver error at paths./asset/read.$ref
Could not resolve reference: undefined Route GET:/docs/paths/asset/read.yaml not found
Resolver error at paths./asset/update.$ref
Could not resolve reference: undefined Route GET:/docs/paths/asset/update.yaml not found
Resolver error at paths./asset/delete.$ref
Could not resolve reference: undefined Route GET:/docs/paths/asset/delete.yaml not found

I've tried with all the options in the migration instructions as well, but no difference.

It does work if I use the baseDir option, but I don't want to specify an absolute path, and the docs says that it should use the directory where the main spec is located, which I assume would be my "swagger" directory, since my index.yaml main spec file is located there.

What am I doing wrong?

Your Environment

  • node version: 18
  • fastify version: 4.3.0
  • @fastify/swagger version: 8.12.0
  • @fastify/swagger-ui version: 1.10.1
  • os: Windows
@dargolith dargolith added the help wanted Extra attention is needed label Nov 4, 2023
@dargolith dargolith changed the title Help Migration from @fastify/swagger 7 to 8 Nov 4, 2023
@dargolith
Copy link
Author

dargolith commented Jan 24, 2024

After waiting for a few months for an answer I decided to try again and do some more research. After meddling with it and testing some things I finally found something that made it work.

For anyone else having this problem when serving a static specification... In order to get it to work I used @fastify/static to serve the folder with the swagger specification. Not sure if this is the way to go, but it worked at least.

import { fastify } from 'fastify';
import { fastifyStatic } from '@fastify/static';
import { fastifySwagger } from '@fastify/swagger';
import { fastifySwaggerUi } from '@fastify/swagger-ui';
import { fastifyCors } from '@fastify/cors';
import path from 'path';
...

const start = async () => {
...
  console.info('Loading API...');
  const app = fastify({});
  app.get('/', (_, response) => response.redirect('/docs')); // default to swagger docs
  app.register(createApi(storage));
  app.register(fastifyCors, { origin: '*' });
  app.register(fastifyStatic, {
    root: path.join(__dirname, '..', 'swagger'),
    prefix: '/docs/',
  });
  app.register(fastifySwagger, {
    mode: 'static',
    specification: { path: './swagger/index.yaml' },
  });
  app.register(fastifySwaggerUi, {
    routePrefix: '/docs',
  });

  console.info('API Loaded.');

  app.listen({ host: '0.0.0.0', port: SERVICE_PORT }, (error, address) => {
    if (error) {
      console.error(error);
      process.exit(1);
    }
    console.info(`Server started. Listening on ${address}`);
  });
};
...

@Uzlopak
Copy link

Uzlopak commented Jan 24, 2024

Actually @fastify/swagger-ui uses @fastify/static. So why are you using static?

@dargolith
Copy link
Author

Actually @fastify/swagger-ui uses @fastify/static. So why are you using static?

That was the only way I got it working, please enlighten me how to do it otherwise. If I remove the static plugin swagger-ui won't find the paths to my swagger specification files. It will find the swagger/index.yaml, but no other files of the spec.

@climba03003
Copy link
Member

Have you tried the baseDir option in @fastify/swagger-ui?

@dargolith
Copy link
Author

Have you tried the baseDir option in @fastify/swagger-ui?

Yeah, I tried that. Didn't get it working. Let me try some more with it.

@dargolith
Copy link
Author

dargolith commented Jan 25, 2024

I've tried with baseDir now and I can't get it to work. This is what I'm at right now without the static plugin. Uncommenting / commenting the specification.baseDir for @fastify/swagger does no difference.

NOTE: I've renamed my "swagger" folder to "openapi". I switched to a newer spec.

Uncommenting the static-plugin section makes it work.

  // app.register(fastifyStatic, {
  //   root: path.join(__dirname, '..', 'openapi'),
  //   prefix: '/docs/',
  // });
  await app.register(fastifySwagger, {
    mode: 'static',
    specification: {
      path: './openapi/index.yaml',
      // baseDir: path.join(__dirname, '..', 'openapi'),
    },
    routePrefix: '/docs',
    exposeRoute: true,
  });
  await app.register(fastifySwaggerUi, {
    mode: 'static',
    // baseDir: path.join(__dirname, '..', 'openapi'),
    routePrefix: '/docs',
    exposeRoute: true,
  });

Regardless of using the specification.baseDir in @fastify/swagger I get the same error in swagger-ui. The main spec can be opened, but the refs do not resolve:

Resolver error at paths./asset/create.$ref
Could not resolve reference: undefined Route GET:/docs/paths/asset/create.yaml not found

I really don't think I should have to use the baseDir since my main spec file is located in the root of the folder with my other spec files. And as expected the baseDir option does no difference.

When using baseDir in @fastify/swagger-ui the swagger UI page doesn't load at all.

I've also tried without custom /docs prefixes, using the default /documentation instead. Same deal.

It seems really strange to me that it doesn't work with just the code above. The example here:
https://github.com/fastify/fastify-swagger/blob/master/examples/static-yaml-file.js

should really include how to setup a static specification with referenced files, because I doubt it would work using $refs. Though to me no more configuration should be needed if the references are in the same folder. Is this a bug?

@Uzlopak
Copy link

Uzlopak commented Jan 25, 2024

Its really strange. Can you provide a repository to clone and test?

@dargolith
Copy link
Author

dargolith commented Jan 25, 2024

Its really strange. Can you provide a repository to clone and test?

Sure! Try this:
https://github.com/dargolith/fastify-swagger-static-example

(If you uncomment the static section it works)

@climba03003
Copy link
Member

We should really split baseDir to websiteDir and specificationDir.
It is currently mixed togather which causing problem.

https://github.com/fastify/fastify-swagger-ui/blob/master/lib/routes.js#L203-L227

@dargolith
Copy link
Author

We should really split baseDir to websiteDir and specificationDir. It is currently mixed togather which causing problem.

https://github.com/fastify/fastify-swagger-ui/blob/master/lib/routes.js#L203-L227

Yes, that sounds like a good plan. However, it should work without setting baseDir as well if it is correctly located relative to the main spec file, right? So in this case if I point the plugin to my main spec the $refs should be reachable as long as they are in the same folder structure, or?

If not for some reason, then the docs must be really clear that the static default configuration does not work for split specs (using $refs) and also give an example on how to configure it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants