Swagger UI & Vercel: Unexpected token < in JSON at position 1
Asked Answered
R

5

7

Code

Full codebase & folder structure can be seen in GitHub

Here is the Swagger related route (had to make it a standalone server)

// api/v1.ts

import express = require("express");
import swaggerJSDoc = require("swagger-jsdoc");
import swaggerUi = require("swagger-ui-express");
import packageJSON = require("../package.json");
import path = require("path");

const app = express();
app.use(express.json());
app.use(express.static(path.resolve(__dirname, "../", "public")));

const swaggerSpec = swaggerJSDoc({
  swaggerDefinition: some_spec,
  apis: ["api/*"]
});

const cssOpts = some_css_override;

app.use("/api/v1", swaggerUi.serve, swaggerUi.setup(swaggerSpec, cssOpts));

module.exports = app;

Problem

When I run vercel dev (locally- localhost:3000/api/v1), I see documentation as expected: Local (vercel dev)

However when I push my code to a branch which triggers a vercel build, I see the following: Vercel Build

Checking the console, I see:

DevTools failed to load source map: Could not parse content for https://colormaster-1unjfn63b-lbragile.vercel.app/api/v1/swagger-ui-bundle.js.map: Unexpected token < in JSON at position 1

DevTools failed to load source map: Could not parse content for https://colormaster-1unjfn63b-lbragile.vercel.app/api/v1/swagger-ui-standalone-preset.js.map: Unexpected token < in JSON at position 1

Even though they respond with 200 Network Responses

I understand that this has something to do with JSON.parse() of HTML content, but not sure how to fix this. Any ideas?

Raze answered 11/9, 2021 at 20:33 Comment(1)
Same error here. Have you fixed it?Freighter
F
4

I am facing the exact same problem of you, trying without success to deploy Swagger to Vercel with Express.

I did one step more, and now I'm seen an error in my console:

Refused to apply style from 'https://myurlishere.vercel.app/api-docs/swagger-ui.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

What I did was, adding a file routes.ts

import { Router } from 'express';
import LanguageController from './controller/LanguageController';
import WordController from './controller/WordController';

const routes = Router();

routes.get("/word", WordController.find);
routes.get("/word/:wordName/language/:languageId", WordController.findByWordAndLanguage);
routes.post("/word", WordController.create);
routes.get("/language", LanguageController.find);

export default routes;

And my server.ts looks like that:

import mongoose from 'mongoose';
import routes from './routes';

const express = require("express");

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
}

const app = express();
const cors = require('cors');


mongoose.connect(process.env.MONGODB_URI || "", {
    dbName: "WordsThatIKnowMongoDB"
})
    .then(() => console.debug("Database connected!"))
    .catch(err => { console.debug(err) });

app.use(express.json());
app.use(express.static("/api-docs"));

app.use(cors());
app.use(routes);

const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');

routes.use('/api-docs', swaggerUi.serve);
routes.get('/api-docs', swaggerUi.setup(swaggerDocument));


app.listen(5000, () => {
    console.debug("Running on port 5000.");
});

// Export the Express API
module.exports = app;

You will see in the file above that I changed app. to routes. like this:

routes.use('/api-docs', swaggerUi.serve);
routes.get('/api-docs', swaggerUi.setup(swaggerDocument));

I still can't solve this problem, but maybe this new error can help you find the solution. I'm also looking for that.

  • EDIT: It's solved.

This is the code that solved my problem:

server.ts

import path from 'path';
import cors from 'cors';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import routes from './routes';

const express = require("express");
const app = express();

const ROOT_FOLDER = path.join(__dirname, '..');
const SRC_FOLDER = path.join(ROOT_FOLDER, 'src');

// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// parse requests of content-type - application/json
app.use(bodyParser.json());

app.use(cors());
app.use(routes);

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
}

mongoose.connect(process.env.MONGODB_URI || "", {
    dbName: "WordsThatIKnowMongoDB"
})
    .then(() => console.debug("Database connected!"))
    .catch(err => { console.debug(err) });

const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
const options = { customCssUrl: '/public/swagger-ui.css', customSiteTitle: "The Words That I Know API - Swagger" };

app.use('/public', express.static(path.join(SRC_FOLDER, 'public')));
app.use('/', swaggerUi.serve);
app.get('/', swaggerUi.setup(swaggerDocument, options));

app.listen(5000, () => {
    console.debug("Running on port 5000.");
});

export default app;

Don't forget to put the styles from Swagger at '/public/swagger-ui.css'. Create a public folder inside src and include a swagger-ui.css file. Inside of this, past swagger styles. You can find swagger styles using inspect on browser, and going to source tab. There you'll find the swagger-ui.css file; remove the commented line after pasting the styles code. If you prefer an easy way to get the styles code, get this file. https://github.com/deywersonp/ghibli-50-api/blob/main/src/public/css/swagger-ui.css

Freighter answered 26/8, 2022 at 15:8 Comment(0)
C
0

hey I got the same problem ! the solution I use isn't optimal but it worked

knowing the css file is been wel process localy,all i did is to add custom css to my swagger-ui documentation. so as the css is working localy I copied all the css ( inspected web browser saw the file swagger-ui.css file source code ) , created a css file , paste the css to it , then i added my css file to my static folder.

here is how to add costum css

const options = { customCssUrl: '/public/css/swagger-ui.css',};

router.use('/api-docs-ui', function(req, res, next){
  swaggerDocument.host = req.get('host');
  req.swaggerDoc = swaggerDocument;
  next();
}, swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));

here is how you define your statics files

app.use('/public/css', express.static('public/css'));

so now localy I have 2 css file working but on vercel just one is working!

hope it could help

Charlatanism answered 6/10, 2022 at 17:9 Comment(0)
A
0

Also you can use a CDN for you Swagger styles if you don't wont to put the css files into your public folder.

Archery answered 2/2, 2023 at 1:53 Comment(1)
How to do that?Orin
T
0

this is how i solve it

const file = fs.readFileSync(path.resolve(__dirname, './swagger.yaml'), 'utf8');
const css = fs.readFileSync(
  path.resolve(__dirname, '../node_modules/swagger-ui-dist/swagger-ui.css'),
  'utf8'
);


const swaggerDocument = YAML.parse(file);
const options: swaggerUi.SwaggerUiOptions = {
  customCss: css,
};

app.use(
  '/api-docs',
  express.static('node_modules/swagger-ui-dist'),
  swaggerUi.serve,
  swaggerUi.setup(swaggerDocument, options)
);

i read the css file content then use it as customCss

Tare answered 17/3 at 10:39 Comment(1)
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?Marybelle
I
0

I had a similar problem with using swagger in vercel. Although, the same swagger doc is working fine on render. After many trials and errors, I had to solve it in a hacky way. I have answered that in details here >> https://mcmap.net/q/1625658/-after-vercel-production-i-cant-view-swagger-ui

Please see the full answer. The main point of my solution is that forcing vercel to load swagger ui dist files directly from the node_modules/swagger-ui-dist.

Interdigitate answered 3/7 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.