Repository: glennjones/hapi-swagger
Pull request #605 (2019-08-16 09:45:07)

add option plugins for documentation route
i want to add the plugins option to the documentation route because my project have using `blankie` when i access to the document page it cant download the script because of following this rules
```js
{
   fontSrc: ['self', 'fonts.gstatic.com', 'data:'],
   scriptSrc: ['self', 'unsafe-inline'],
   styleSrc: ['self', 'fonts.googleapis.com', 'unsafe-inline'],
   imgSrc: ['self', 'data:'],
   generateNonces: false
}
```
so i have to add those config to globally at `blankie` plugin and i don't want to do it becuase my other route is gonna be restricts .

if this can fix my issue or any other who use `blankie` or any other plugin that want to specify for that only route .


Patch:
diff --git a/examples/custom.js b/examples/custom.js
index bc003fa..2952d3d 100644
--- a/examples/custom.js
+++ b/examples/custom.js
@@ -39,6 +39,15 @@ const goodOptions = {
 let swaggerOptions = {
   documentationPage: false,
   documentationRouteTags: 'no-logging',
+  documentationRoutePlugins: {
+    blankie: {
+      fontSrc: ['self', 'fonts.gstatic.com', 'data:'],
+      scriptSrc: ['self', 'unsafe-inline'],
+      styleSrc: ['self', 'fonts.googleapis.com', 'unsafe-inline'],
+      imgSrc: ['self', 'data:'],
+      generateNonces: false
+    }
+  },
   swaggerUIPath: '/ui/',
   basePath: '/v1/',
   pathPrefixSize: 2,
diff --git a/index.d.ts b/index.d.ts
index 65c6823..a73f67f 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -233,6 +233,12 @@ declare namespace hapiswagger {
      */
     documentationRouteTags?: string | string[];
 
+    /**
+     * Add hapi plugins option to internal hapi-swagger routes
+     * @default []
+     */
+    documentationRoutePlugins?: object;
+
     /**
      * The mime types consumed
      *
diff --git a/lib/builder.js b/lib/builder.js
index a171ba1..acb80e7 100644
--- a/lib/builder.js
+++ b/lib/builder.js
@@ -216,6 +216,7 @@ internals.removeNoneSchemaOptions = function(options) {
   [
     'debug',
     'documentationPath',
+    'documentationRoutePlugins',
     'documentationRouteTags',
     'documentationPage',
     'jsonPath',
diff --git a/lib/defaults.js b/lib/defaults.js
index 58686ef..ee7e67b 100644
--- a/lib/defaults.js
+++ b/lib/defaults.js
@@ -5,6 +5,7 @@ module.exports = {
   jsonPath: '/swagger.json',
   documentationPath: '/documentation',
   documentationRouteTags: [],
+  documentationRoutePlugins: {},
   templates: resolve(__dirname, '..', 'templates'),
   swaggerUIPath: '/swaggerui/',
   auth: false,
diff --git a/lib/index.js b/lib/index.js
index f4722ea..a6832c1 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -17,6 +17,7 @@ const schema = Joi.object({
   jsonPath: Joi.string(),
   documentationPath: Joi.string(),
   documentationRouteTags: Joi.alternatives().try(Joi.string(), Joi.array().items(Joi.string())),
+  documentationRoutePlugins: Joi.object().default({}),
   templates: Joi.string(),
   swaggerUIPath: Joi.string(),
   auth: Joi.alternatives().try(Joi.boolean(), Joi.string(), Joi.object()),
@@ -143,7 +144,8 @@ exports.plugin = {
                 tags: settings.documentationRouteTags,
                 handler: (request, h) => {
                   return h.view('index', {});
-                }
+                },
+                plugins: settings.documentationRoutePlugins
               }
             }
           ]);
@@ -210,7 +212,8 @@ exports.plugin = {
                 tags: settings.documentationRouteTags,
                 handler: (request, h) => {
                   return h.view('debug.html', {}).type('application/json');
-                }
+                },
+                plugins: settings.documentationRoutePlugins
               }
             }
           ]);
diff --git a/optionsreference.md b/optionsreference.md
index 5cbb9ed..25c5b50 100644
--- a/optionsreference.md
+++ b/optionsreference.md
@@ -34,6 +34,7 @@
 -   `securityDefinitions:`: (object) Containing [Security Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#securityDefinitionsObject). No defaults are provided.
 -   `payloadType`: (string) How payload parameters are displayed `json` or `form` - default: `json`
 -   `documentationRouteTags`: (string or array) Add hapi tags to internal `hapi-swagger` routes - default: `[]`
+-   `documentationRoutePlugins`: (object) Add hapi plugins to internal `hapi-swagger` routes - default: `{}`
 -   `consumes`: (array) The mime types consumed - default: `['application/json']`
 -   `produces`: (array) The mime types produced - default: `['application/json']`
 -   `xProperties`: Adds JOI data that cannot be use directly by swagger as metadata - default: `true`


Test patch:
diff --git a/test/Integration/documentation-route-plugins-test.js b/test/Integration/documentation-route-plugins-test.js
new file mode 100644
index 0000000..e53b3cf
--- /dev/null
+++ b/test/Integration/documentation-route-plugins-test.js
@@ -0,0 +1,75 @@
+const Code = require('@hapi/code');
+const Lab = require('@hapi/lab');
+const Helper = require('../helper.js');
+const Validate = require('../../lib/validate.js');
+
+const expect = Code.expect;
+const lab = (exports.lab = Lab.script());
+
+lab.experiment('documentation-route-plugins', () => {
+  const routes = [
+    {
+      method: 'GET',
+      path: '/test',
+      handler: Helper.defaultHandler
+    }
+  ];
+
+  const testServer = async (swaggerOptions, plugins) => {
+    const server = await Helper.createServer(swaggerOptions, routes);
+    const response = await server.inject({ method: 'GET', url: '/swagger.json' });
+
+    const table = server.table();
+    table.forEach(route => {
+      switch (route.path) {
+        case '/test':
+          break;
+        case '/documentation':
+          expect(route.settings.plugins).to.equal(plugins);
+          break;
+        case '/swagger.json':
+          expect(route.settings.plugins).to.equal({ 'hapi-swagger': false });
+          break;
+        case '/swaggerui/extend.js':
+        case '/swaggerui/{path*}':
+          expect(route.settings.plugins).to.equal({});
+          break;
+        default:
+          break;
+      }
+    });
+
+    expect(response.statusCode).to.equal(200);
+    const isValid = await Validate.test(response.result);
+    expect(isValid).to.be.true();
+  };
+
+  lab.test('should have no documentationRoutePlugins property', async () => {
+    await testServer({}, {});
+  });
+
+  lab.test('should have documentationRoutePlugins property passed', async () => {
+    const swaggerOptions = {
+      documentationRoutePlugins: {
+        blankie: {
+          fontSrc: ['self', 'fonts.gstatic.com', 'data:']
+        }
+      }
+    };
+    await testServer(swaggerOptions, swaggerOptions.documentationRoutePlugins);
+  });
+
+  lab.test('should have multiple documentationRoutePlugins options', async () => {
+    const swaggerOptions = {
+      documentationRoutePlugins: {
+        blankie: {
+          fontSrc: ['self', 'fonts.gstatic.com', 'data:']
+        },
+        'simple-plugin': {
+          isEnable: true
+        }
+      }
+    };
+    await testServer(swaggerOptions, swaggerOptions.documentationRoutePlugins);
+  });
+});