使用swagger-ui-express动态加载YAML渲染SwaggerUI时空白页问题
问题:Express中使用swagger-ui-express动态加载OpenAPI文档出现空白页
我用ExpressJS搭配swagger-ui-express渲染SwaggerUI时,访问/api-docs/prd路由一直显示空白页。需求是每次访问这个路由时,先从云端下载YAML文件、解析成JSON格式后再传递给SwaggerUI。
可正常运行的提前加载代码
提前下载好文档再挂载路由的写法是没问题的:
const downloadAsYAML = async () => { const bucket ='buc'; const path = 'openapi_prd.yaml'; const file = await new Storage() .bucket(bucket) .file(path) .download(); var x = yaml.parse(file[0].toString('utf8')) return x; } downloadAsYAML().then((res)=>{ app.use('/api-docs/prd', swaggerUi.serveFiles(res, options), swaggerUi.setup(null,options)); });
动态加载时的问题
改成在GET路由里动态下载文件的写法后,页面直接空白,控制台报这些错:
Refused to apply style from 'http://localhost:3001/api-docs/prd/swagger-ui.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled. swagger-ui-bundle.js:1 Failed to load resource: the server responded with a status of 404 (Not Found) localhost/:1 Refused to execute script from
对应的问题代码:
app.get('/api-docs/prd', function(req, res, next){ downloadAsYAML('openapi_prd.yaml').then((result)=>{ swaggerDocument=result; //swaggerDocument初始值为null }); next(); }, swaggerUi.serveFiles(swaggerDocument, options), swaggerUi.setup());
问题原因
- 异步代码顺序错误:
downloadAsYAML是异步函数,调用后立刻执行next(),此时swaggerDocument还是初始的null值,swaggerUi.serveFiles拿到空参数后,无法正确加载SwaggerUI所需的静态资源(css、js),导致404和MIME类型错误。 - 中间件初始化是一次性的:
app.get中的swaggerUi.serveFiles和swaggerUi.setup在服务启动时就已初始化,不会随每次请求重新执行,后续swaggerDocument赋值也无法更新中间件配置。
解决方法
要在请求处理流程中完成文件下载与解析,再动态调用SwaggerUI的渲染逻辑,确保每次请求都使用最新文档:
调整后的代码
首先修改downloadAsYAML让它支持接收文件名参数:
const downloadAsYAML = async (fileName) => { const bucket = 'buc'; const path = fileName; const file = await new Storage() .bucket(bucket) .file(path) .download(); return yaml.parse(file[0].toString('utf8')); };
然后修改路由处理逻辑:
app.get('/api-docs/prd', async (req, res, next) => { try { // 先完成文档的下载和解析 const swaggerDocument = await downloadAsYAML('openapi_prd.yaml'); // 用最新文档调用setup并处理请求 swaggerUi.setup(swaggerDocument, options)(req, res, next); } catch (err) { next(err); // 处理下载或解析时的错误 } }, swaggerUi.serveFiles(null, options));
代码说明
- 使用
async/await确保文档下载完成后再渲染SwaggerUI,彻底解决异步顺序问题。 swaggerUi.serveFiles传入null,因为我们会在请求时动态传入文档,无需提前指定。- 将
swaggerUi.setup放在请求回调内,每次请求都基于最新下载的文档初始化SwaggerUI。
内容的提问来源于stack exchange,提问作者user2570135
相关产品推荐
相关产品推荐

