Repository: glennjones/hapi-swagger
Pull request #737 (2022-02-08 08:57:16)

fix: docs are rendered only with the options in last registered plugin
### The problem
When the plugin is registered multiple times, each `swagger.json` for each option is generated properly, but not for the documentation page rendered.

### Why this happened
The plugin pass settings data to the renderer via registering the `onPostHandler` ext function to the server. This behaviour caused only the last registered one to intercept others' requests, applying their settings on whole documentation pages.


Patch:
diff --git a/lib/index.js b/lib/index.js
index 5d180d3..49f3b22 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -310,8 +310,15 @@ exports.plugin = {
 const appendDataContext = function (plugin, settings) {
   plugin.ext('onPostHandler', (request, h) => {
     const response = request.response;
+    const routePrefix = plugin.realm.modifiers.route.prefix;
+
     // if the reply is a view add settings data into template system
     if (response.variety === 'view') {
+      // skip if the request is not for this handler
+      if (routePrefix && !request.path.startsWith(routePrefix)) {
+        return h.continue;
+      }
+
       // Added to fix bug that cannot yet be reproduced in test - REVIEW
       /* $lab:coverage:off$ */
       if (!response.source.context) {
@@ -327,9 +334,9 @@ const appendDataContext = function (plugin, settings) {
       }
 
       const prefixedSettings = Hoek.clone(settings);
-      if (plugin.realm.modifiers.route.prefix) {
-        ['jsonPath', 'swaggerUIPath'].forEach(setting => {
-          prefixedSettings[setting] = plugin.realm.modifiers.route.prefix + prefixedSettings[setting];
+      if (routePrefix) {
+        ['jsonPath', 'swaggerUIPath'].forEach((setting) => {
+          prefixedSettings[setting] = routePrefix + prefixedSettings[setting];
         });
       }
 


Test patch:
diff --git a/test/Integration/plugin-test.js b/test/Integration/plugin-test.js
index b6544bb..2df6a8a 100644
--- a/test/Integration/plugin-test.js
+++ b/test/Integration/plugin-test.js
@@ -556,7 +556,7 @@ lab.experiment('plugin', () => {
     ];
     const server = await Helper.createServer({}, testRoutes);
     const response = await server.inject({ method: 'GET', url: '/swagger.json' });
-    //console.log(JSON.stringify(response.result));
+
     expect(response.result.definitions).to.equal({
       Model1: {
         type: 'object',
@@ -637,5 +637,15 @@ lab.experiment('multiple plugins', () => {
     expect(isValid2).to.be.true();
     expect(response2.result.info.description).to.equal('This is the shop API docs');
     expect(response2.result.paths['/shop/'].post.operationId).to.equal('postShop');
+
+    const document1 = await server.inject({ method: 'GET', url: '/store-api/documentation' });
+    expect(document1.statusCode).to.equal(200);
+    expect(document1.result).to.include('/store-api/');
+    expect(document1.result).not.to.include('/shop-api/');
+
+    const document2 = await server.inject({ method: 'GET', url: '/shop-api/documentation' });
+    expect(document2.statusCode).to.equal(200);
+    expect(document2.result).to.include('/shop-api/');
+    expect(document2.result).not.to.include('/store-api/');
   });
 });