Ottomata has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/339706 )

Change subject: Merge from upstream template/master at 
a354b0e8bbf88123a6c2fe17693435fb1107b794
......................................................................


Merge from upstream template/master at a354b0e8bbf88123a6c2fe17693435fb1107b794

Conflicts:
        lib/api-util.js
        package.json
        routes/ex.js
        routes/root.js
        routes/v1.js

Change-Id: Ia0cc779e5292bde0ffe287b8bc9c901462c5852a
---
A lib/swagger-ui.js
M package.json
M routes/root.js
M spec.template.yaml
4 files changed, 95 insertions(+), 5 deletions(-)

Approvals:
  Ottomata: Verified; Looks good to me, approved



diff --git a/lib/swagger-ui.js b/lib/swagger-ui.js
new file mode 100644
index 0000000..a4e41c2
--- /dev/null
+++ b/lib/swagger-ui.js
@@ -0,0 +1,79 @@
+'use strict';
+
+
+const BBPromise = require('bluebird');
+const fs = BBPromise.promisifyAll(require('fs'));
+const path = require('path');
+const HTTPError = require('../lib/util.js').HTTPError;
+
+
+// Swagger-ui helpfully exporting the absolute path of its dist directory
+const docRoot = `${require('swagger-ui').dist}/`;
+
+function processRequest(app, req, res) {
+
+    const reqPath = req.query.path || '/index.html';
+    const filePath = path.join(docRoot, reqPath);
+
+    // Disallow relative paths.
+    // Test relies on docRoot ending on a slash.
+    if (filePath.substring(0, docRoot.length) !== docRoot) {
+        throw new HTTPError({
+            status: 404,
+            type: 'not_found',
+            title: 'File not found',
+            detail: `${reqPath} could not be found.`
+        });
+    }
+
+    return fs.readFileAsync(filePath)
+    .then((body) => {
+        if (reqPath === '/index.html') {
+            body = body.toString()
+                .replace(/((?:src|href)=['"])/g, '$1?doc&path=')
+                // Some self-promotion
+                .replace(/<a id="logo".*?<\/a>/,
+                        `<a id="logo" 
href="${app.info.homepage}">${app.info.name}</a>`)
+                .replace(/<title>[^<]*<\/title>/, 
`<title>${app.info.name}</title>`)
+                // Replace the default url with ours, switch off validation &
+                // limit the size of documents to apply syntax highlighting to
+                .replace(/Sorter: "alpha"/, 'Sorter: "alpha", validatorUrl: 
null, ' +
+                    'highlightSizeThreshold: 10000')
+                .replace(/docExpansion: "none"/, 'docExpansion: "list"')
+                .replace(/ url: url,/, 'url: "/?spec",');
+        }
+
+        let contentType = 'text/html';
+        if (/\.js$/.test(reqPath)) {
+            contentType = 'text/javascript';
+            body = body.toString()
+                .replace(/underscore-min\.map/, 
'?doc&path=lib/underscore-min.map');
+        } else if (/\.png$/.test(reqPath)) {
+            contentType = 'image/png';
+        } else if (/\.map$/.test(reqPath)) {
+            contentType = 'application/json';
+        } else if (/\.ttf$/.test(reqPath)) {
+            contentType = 'application/x-font-ttf';
+        } else if (/\.css$/.test(reqPath)) {
+            contentType = 'text/css';
+            body = body.toString().replace(/\.\.\/(images|fonts)\//g, 
'?doc&path=$1/');
+        }
+
+        res.setHeader('Content-Type', contentType);
+        res.setHeader('content-security-policy', "default-src 'none'; " +
+                        "script-src 'self' 'unsafe-inline'; connect-src *; " +
+                        "style-src 'self' 'unsafe-inline'; img-src 'self'; 
font-src 'self';");
+        res.send(body.toString());
+    })
+    .catch({ code: 'ENOENT' }, () => {
+        res.status(404)
+            .type('not_found')
+            .send('not found');
+    });
+
+}
+
+module.exports = {
+    processRequest
+};
+
diff --git a/package.json b/package.json
index 4e1bd94..ff9e48f 100644
--- a/package.json
+++ b/package.json
@@ -5,9 +5,10 @@
   "main": "./app.js",
   "scripts": {
     "start": "service-runner",
-    "test": "mocha && nsp check",
+    "test": "PREQ_CONNECT_TIMEOUT=15 mocha && nsp check",
     "docker-start": "service-runner docker-start",
     "docker-test": "service-runner docker-test",
+    "test-build": "service-runner docker-test && service-runner build 
--deploy-repo --force",
     "coverage": "istanbul cover _mocha -- -R spec"
   },
   "repository": {
@@ -42,6 +43,7 @@
     "js-yaml": "^3.7.0",
     "service-runner": "^2.1.11",
     "swagger-router": "^0.5.5",
+    "swagger-ui": "git+https://github.com/wikimedia/swagger-ui#master";,
     "node-rdkafka-statsd": "^0.1.0",
     "kafka-sse": 
"git+https://phabricator.wikimedia.org/diffusion/WKSE/kafkasse.git#v0.0.6";
   },
diff --git a/routes/root.js b/routes/root.js
index 28930cb..42686eb 100644
--- a/routes/root.js
+++ b/routes/root.js
@@ -2,6 +2,7 @@
 
 
 const sUtil = require('../lib/util');
+const swaggerUi = require('../lib/swagger-ui');
 
 
 /**
@@ -31,15 +32,17 @@
 
 /**
  * GET /
- * Main entry point. Currently it only responds if the spec query
+ * Main entry point. Currently it only responds if the spec or doc query
  * parameter is given, otherwise lets the next middleware handle it
  */
 router.get('/', (req, res, next) => {
 
-    if (!{}.hasOwnProperty.call(req.query || {}, 'spec')) {
-        next();
-    } else {
+    if ({}.hasOwnProperty.call(req.query || {}, 'spec')) {
         res.json(app.conf.spec);
+    } else if ({}.hasOwnProperty.call(req.query || {}, 'doc')) {
+        return swaggerUi.processRequest(app, req, res);
+    } else {
+        next();
     }
 
 });
diff --git a/spec.template.yaml b/spec.template.yaml
index 75b0db1..608f92f 100644
--- a/spec.template.yaml
+++ b/spec.template.yaml
@@ -46,6 +46,12 @@
               spec: true
           response:
             status: 200
+        - title: doc from root
+          request:
+            query:
+              doc: true
+          response:
+            status: 200
         - title: root with wrong query param
           request:
             query:

-- 
To view, visit https://gerrit.wikimedia.org/r/339706
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia0cc779e5292bde0ffe287b8bc9c901462c5852a
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/services/eventstreams
Gerrit-Branch: master
Gerrit-Owner: Ottomata <ao...@wikimedia.org>
Gerrit-Reviewer: Ottomata <ao...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to