Yuki Takei 7 лет назад
Родитель
Сommit
720ff19b43

+ 1 - 0
config/env.dev.js

@@ -10,6 +10,7 @@ module.exports = {
     // 'growi-plugin-lsx',
     // 'growi-plugin-pukiwiki-like-linker',
   ],
+  // PUBLISH_OPEN_API: true,
   // USER_UPPER_LIMIT: 0,
   // DEV_HTTPS: true,
   // PUBLIC_WIKI_ONLY: true,

+ 1 - 1
config/swagger-definition.js

@@ -1,7 +1,7 @@
 module.exports = {
   openapi: '3.0.1',
   info: {
-    title: 'GROWI API Docs',
+    title: 'GROWI API v3',
     version: '3.0.0',
   },
   externalDocs: {

+ 7 - 0
resource/cdn-manifests.js

@@ -70,6 +70,13 @@ module.exports = {
         integrity: '',
       },
     },
+    {
+      name: 'redoc-standalone',
+      url: 'https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js',
+      args: {
+        integrity: '',
+      },
+    },
   ],
   style: [
     {

+ 0 - 20
src/server/crowi/dev.js

@@ -5,10 +5,6 @@ const path = require('path');
 const swig = require('swig-templates');
 const onHeaders = require('on-headers');
 
-const swaggerJSDoc = require('swagger-jsdoc');
-const swaggerDefinition = require('@root/config/swagger-definition');
-
-
 class CrowiDev {
 
   /**
@@ -88,25 +84,9 @@ class CrowiDev {
     eazyLogger.unprefixed('info', `         APP: {magenta:${serverUrl}}`);
     eazyLogger.unprefixed('info', '{grey:=======================================}');
 
-    this.setupSwaggerJSdoc(app);
-
     return server;
   }
 
-  setupSwaggerJSdoc(app) {
-    const options = {
-      swaggerDefinition,
-      apis: swaggerDefinition.apis,
-    };
-    const swaggerSpec = swaggerJSDoc(options);
-
-    app.get('/api-docs.json', (req, res) => {
-      res.setHeader('Content-Type', 'application/json');
-      res.send(swaggerSpec);
-    });
-  }
-
-
   /**
    *
    * @param {any} app express

+ 1 - 0
src/server/crowi/index.js

@@ -6,6 +6,7 @@ const pkg = require('@root/package.json');
 const InterceptorManager = require('@commons/service/interceptor-manager');
 const CdnResourcesService = require('@commons/service/cdn-resources-service');
 const Xss = require('@commons/service/xss');
+
 const path = require('path');
 
 const sep = path.sep;

+ 38 - 0
src/server/routes/apiv3/docs.js

@@ -0,0 +1,38 @@
+const loggerFactory = require('@alias/logger');
+
+const logger = loggerFactory('growi:routes:apiv3:docs'); // eslint-disable-line no-unused-vars
+
+const express = require('express');
+
+const router = express.Router();
+
+module.exports = (crowi) => {
+
+  // skip if disabled
+  if (!crowi.configManager.getConfig('crowi', 'app:publishOpenAPI')) {
+    return router;
+  }
+
+  const swaggerJSDoc = require('swagger-jsdoc');
+  const swaggerDefinition = require('@root/config/swagger-definition');
+
+  // generate swagger spec
+  const options = {
+    swaggerDefinition,
+    apis: swaggerDefinition.apis,
+  };
+  const swaggerSpec = swaggerJSDoc(options);
+
+  // publish swagger spec
+  router.get('/swagger-spec.json', (req, res) => {
+    res.setHeader('Content-Type', 'application/json');
+    res.send(swaggerSpec);
+  });
+
+  // publish redoc
+  router.get('/', (req, res) => {
+    res.render('redoc');
+  });
+
+  return router;
+};

+ 7 - 0
src/server/routes/apiv3/healthcheck.js

@@ -8,12 +8,19 @@ const router = express.Router();
 
 const helmet = require('helmet');
 
+/**
+ * @swagger
+ *  tags:
+ *    name: Healthcheck
+ */
+
 module.exports = (crowi) => {
   /**
    * @swagger
    *
    *  /healthcheck:
    *    get:
+   *      tags: [Healthcheck]
    *      description: Check whether the server is healthy or not
    *      produces:
    *        - application/json

+ 1 - 0
src/server/routes/index.js

@@ -231,6 +231,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/hackmd.saveOnHackmd' , accessTokenParser , loginRequired(crowi, app) , csrf, hackmd.validateForApi, hackmd.saveOnHackmd);
 
   // API v3
+  app.use('/api-docs', require('./apiv3/docs')(crowi));
   app.use('/_api/v3', require('./apiv3')(crowi));
 
   app.get('/*/$'                   , loginRequired(crowi, app, false) , page.showPageWithEndOfSlash, page.notFound);

+ 6 - 0
src/server/service/config-loader.js

@@ -116,6 +116,12 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type:    TYPES.STRING,
     default: null,
   },
+  PUBLISH_OPEN_API: {
+    ns:      'crowi',
+    key:     'app:publishOpenAPI',
+    type:    TYPES.BOOLEAN,
+    default: false,
+  },
   MAX_FILE_SIZE: {
     ns:      'crowi',
     key:     'app:maxFileSize',

+ 24 - 0
src/server/views/redoc.html

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>GROWI API v3</title>
+    <!-- needed for adaptive design -->
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
+
+    <!--
+    ReDoc doesn't change outer page styles
+    -->
+    <style>
+      body {
+        margin: 0;
+        padding: 0;
+      }
+    </style>
+  </head>
+  <body>
+    <redoc spec-url='/api-docs/swagger-spec.json'></redoc>
+    {{ cdnScriptTag('redoc-standalone') }}
+  </body>
+</html>