Swagger-ui: Swagger UI Dist Package has Broken Export for SwaggerUIBundle in 3.18.0

Created on 8 Aug 2018  路  5Comments  路  Source: swagger-api/swagger-ui

Q&A (please complete the following information)

  • OS: macOS running docker container containing a Linux distro an Express application)
  • Browser: Chrome (not a browser issue, but using Node v8.11.1)
  • Version: 67.0.3396.99
  • Method of installation: npm 5.6.0 (installed swagger-ui-dist)
  • Swagger-UI version: 3.18.0
  • Swagger/OpenAPI version: OpenAPI 3.0

Content & configuration

Example Swagger/OpenAPI definition:
Using a standard definition file, but due to security, I cannot paste the file or examples based on our file's structure. The issue is not related to the definition file.

Swagger-UI configuration options:

const ui = SwaggerUIBundle({
  url: '/openapi/submissions',
  dom_id: '#swagger-ui',
  deepLinking: true,
  presets: [
    SwaggerUIStandalonePreset
  ],
  layout: 'StandaloneLayout'
});

Describe the bug you're encountering

The SwaggerUIBundle export doesn't work, so if it's imported and an attempt to use it is made, an error is thrown essentially saying SwaggerUIBundle is undefined. When I console.log(require('swagger-ui-dist')), I only get the absolutePath and getAbsoluteFSPath exports.

To reproduce...

Steps to reproduce the behavior:

  1. npm install --save swagger-ui-dist
  2. Attempt to import SwaggerUIBundle from swagger-ui-dist
  3. Start Express server
  4. See error stating SwaggerUIBundle is undefined

Expected behavior

SwaggerUIBundle should be successfully imported (along with SwaggerUIStandalonePreset, but the problem isn't with that)

Screenshots

WITH MODIFIED index.js FORCING THROWING OF ERROR (see Additional context or thoughts):
error_with_modified_code

Additional context or thoughts

If you modify the index.js file like so:

try {
  module.exports.SwaggerUIBundle = require("./swagger-ui-bundle.js")
  // module.exports.SwaggerUIStandalonePreset = require("./swagger-ui-standalone-preset.js") // MODIFIED - NOT WHERE ISSUE IS OCCURING
} catch(e) {
  throw Error(e) // ADDED
  // swallow the error if there's a problem loading the assets.
  // allows this module to support providing the assets for browserish contexts,
  // without exploding in a Node context.
  //
  // see https://github.com/swagger-api/swagger-ui/issues/3291#issuecomment-311195388
  // for more information.
}

// `absolutePath` and `getAbsoluteFSPath` are both here because at one point,
// we documented having one and actually implemented the other.
// They were both retained so we don't break anyone's code.
module.exports.absolutePath = require("./absolute-path.js")
module.exports.getAbsoluteFSPath = require("./absolute-path.js")

you will see the following error:

/container/node_modules/swagger-ui-dist/index.js:5
  throw Error(e)
  ^
2018-08-08T14:39:35.787612500Z 
Error: TypeError: i.default.addHook is not a function
    at Object.<anonymous> (/container/node_modules/swagger-ui-dist/index.js:5:9)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/container/app/routes/swagger.js:6:25)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/container/app/routes/publicapi.js:5:23)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/container/app/app.js:21:26)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Module.require (module.js:579:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/container/app/bin/www:7:11)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Function.Module.runMain (module.js:676:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3
lock-bot support

Most helpful comment

Thanks for getting back to me @shockey!

For more context on what I'm trying to do, please refer to my other filing here. The Swagger UI documentation is a bit confusing on how to configure the app in a Node/Express app, so I tried to pull in SwaggerUIBundle and configure my application that way without directly editing the index.html in the node_modules/swagger-ui-dist folder. I assumed too much!

If the swagger-ui-dist package is supposed to be supported in Node/Express environments, it might make sense to explicitly document that some other way of configuring the application is needed rather than attempting to import SwaggerUIBundle. However, I'm not really sure what was intended in terms of configuration for Swagger UI served from a Node/Express app.

All 5 comments

@sietekk, thanks for the report!

From the 3.18.0 release notes:

You may experience issues with this version if you're importing Swagger UI in a non-browser environment (which we don't officially support). Consider loading JSDom beforehand, so that Swagger UI has the DOM APIs it needs access to.

Are you using SwaggerUIBundle in your Express application? I'm not aware of any useful reason to import Swagger UI _itself_ server-side (except server-side SPA rendering, which is covered in #4232)... can you share some context on how you're consuming the module?


Moving this to support for now, so I keep an eye on it.

Thanks for getting back to me @shockey!

For more context on what I'm trying to do, please refer to my other filing here. The Swagger UI documentation is a bit confusing on how to configure the app in a Node/Express app, so I tried to pull in SwaggerUIBundle and configure my application that way without directly editing the index.html in the node_modules/swagger-ui-dist folder. I assumed too much!

If the swagger-ui-dist package is supposed to be supported in Node/Express environments, it might make sense to explicitly document that some other way of configuring the application is needed rather than attempting to import SwaggerUIBundle. However, I'm not really sure what was intended in terms of configuration for Swagger UI served from a Node/Express app.

Hi @sietekk ,
any update on this issue?
I'm trying to do the same and getting the same error as you.

Thanks

docs/usage/installation.md implies that the main purpose of swagger-ui-dist is to serve it from Express bypassing asset bundlers. Yet the configuration is not exposed to the Express server.

It seems that one workaround to @sietekk's issue is to copy index.html from node_modules/swagger-ui-dist/ into your project and then edit the config directly in index.html. The docker deployment itself edits index.html directly for example:

if [[ -f $SWAGGER_JSON ]]; then
  cp -s $SWAGGER_JSON $NGINX_ROOT
  REL_PATH="./$(basename $SWAGGER_JSON)"
  sed -i "s|https://petstore.swagger.io/v2/swagger.json|$REL_PATH|g" $INDEX_FILE
  sed -i "s|http://example.com/api|$REL_PATH|g" $INDEX_FILE
else
  sed -i "s|https://petstore.swagger.io/v2/swagger.json|$API_URL|g" $INDEX_FILE
  sed -i "s|http://example.com/api|$API_URL|g" $INDEX_FILE
fi

This is a couple of extra steps to installation, but it works for me. I suggest that it would be helpful if installation.md mentioned this limitation (which doesn't exist on client side deployments) and the workaround.

footnote:
you can expose index.html as a static file, for example with app.use(express.static(path.join(__dirname, "../public")));

Following up here - if you need to configure Swagger UI in Express, the best solution I know of is https://github.com/scottie1984/swagger-ui-express, which is a clean way of doing the editing that @dcorking is referring to.

You should definitely _not_ be importing or calling SwaggerUIBundle directly in your server-side application - that code is meant for your user's browser. The only code relevant to server-side applications is the absolutePath helper.

Beyond that, I'm closing this due to inactivity. My apologies for not replying to this sooner. This is simply to keep our issue tracker clean - feel free to comment if there are any further thoughts or concerns, I'd be happy to reopen this issue.

Was this page helpful?
0 / 5 - 0 ratings