Mholloway has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/390878 )

Change subject: Update to service-template-node v0.5.2
......................................................................

Update to service-template-node v0.5.2

Change-Id: Id6a2fe9c8656ce9947e2b9936275a40db704e402
---
M .eslintrc.yml
M .travis.yml
M lib/api-util.js
A lib/swagger-ui.js
M package.json
M routes/root.js
M test/features/app/spec.js
M test/index.js
8 files changed, 116 insertions(+), 26 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/mobileapps 
refs/changes/78/390878/1

diff --git a/.eslintrc.yml b/.eslintrc.yml
index bf9f475..312fdfd 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -1 +1 @@
-extends: node-services
\ No newline at end of file
+extends: 'eslint-config-node-services'
diff --git a/.travis.yml b/.travis.yml
index c417c7f..df202fa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,4 +5,3 @@
 node_js:
   - "4"
   - "6"
-  - "node"
diff --git a/lib/api-util.js b/lib/api-util.js
index 9fd9959..d6059d7 100644
--- a/lib/api-util.js
+++ b/lib/api-util.js
@@ -4,7 +4,6 @@
 const preq = require('preq');
 const sUtil = require('./util');
 const Template = require('swagger-router').Template;
-
 const HTTPError = sUtil.HTTPError;
 
 
diff --git a/lib/swagger-ui.js b/lib/swagger-ui.js
new file mode 100644
index 0000000..9e39ff5
--- /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(/docExpansion: "none"/, 'docExpansion: "list", '
+                    + 'validatorUrl: null, '
+                    + 'highlightSizeThreshold: 10000')
+                .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 f1a64ef..05712d1 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
     "lint": "eslint --cache --max-warnings 0 --ext .js --ext .json .",
     "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": {
@@ -40,45 +41,47 @@
   },
   "homepage": "https://www.mediawiki.org/wiki/RESTBase_services_for_apps";,
   "dependencies": {
-    "bluebird": "^3.4.6",
-    "body-parser": "^1.15.2",
-    "bunyan": "^1.8.5",
+    "bluebird": "^3.5.0",
+    "body-parser": "^1.17.1",
+    "bunyan": "^1.8.9",
     "cassandra-uuid": "^0.0.2",
     "compression": "^1.6.2",
     "core-js": "^2.4.1",
-    "domino": "^1.0.27",
+    "domino": "^1.0.28",
     "escape-string-regexp": "^1.0.5",
     "express": "^4.16.0",
-    "js-yaml": "^3.7.0",
+    "js-yaml": "^3.8.2",
     "mediawiki-title": "^0.6.3",
     "parsoid-dom-utils": "^0.1.3",
-    "preq": "^0.5.1",
+    "preq": "^0.5.2",
     "service-runner": "^2.2.5",
-    "swagger-router": "^0.5.5",
+    "swagger-router": "^0.5.6",
+    "swagger-ui": "git+https://github.com/wikimedia/swagger-ui#master";,
     "underscore": "^1.8.3"
   },
   "devDependencies": {
     "ajv": "^4.7.7",
     "csv-parse": "^1.1.7",
-    "eslint": "^3.11.1",
-    "eslint-config-node-services": "^2.2.2",
-    "eslint-config-wikimedia": "^0.4.0",
-    "eslint-plugin-jsdoc": "^3.0.0",
-    "eslint-plugin-json": "^1.2.0",
     "extend": "^3.0.0",
     "istanbul": "^0.4.5",
     "js-beautify": "^1.6.8",
     "mkdirp": "^0.5.1",
-    "mocha": "^3.1.2",
+    "mocha": "^3.2.0",
     "mocha-jshint": "^2.3.1",
-    "mocha-lcov-reporter": "^1.2.0",
-    "nsp": "^2.6.2",
+    "mocha-lcov-reporter": "^1.3.0",
+    "nsp": "^2.6.3",
+    "mocha-eslint": "^3.0.1",
+    "eslint": "^3.12.0",
+    "eslint-config-node-services": "^2.0.2",
+    "eslint-config-wikimedia": "^0.4.0",
+    "eslint-plugin-json": "^1.2.0",
+    "eslint-plugin-jsdoc": "^3.0.0",
     "rss-parser": "^2.5.2",
     "sepia": "^2.0.1"
   },
   "deploy": {
     "target": "debian",
-    "node": "6.11.1",
+    "node": "6.9.1",
     "dependencies": {
       "_all": []
     }
diff --git a/routes/root.js b/routes/root.js
index cf0ffda..83ee521 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,21 +32,23 @@
 
 /**
  * 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();
     }
 
 });
 
 
-module.exports = function(appObj) {
+module.exports = (appObj) => {
 
     app = appObj;
 
diff --git a/test/features/app/spec.js b/test/features/app/spec.js
index c5abfb0..1645149 100644
--- a/test/features/app/spec.js
+++ b/test/features/app/spec.js
@@ -62,8 +62,9 @@
         try {
             uri.expand(Object.assign({}, defParams, ex.request.params || {}));
         } catch (e) {
-            const msg = `Route ${pathStr}, example ${ex.title}: missing 
parameter: ${e.message}`;
-            throw new Error(msg);
+            throw new Error(
+                `Route ${pathStr}, example ${idx} (${ex.title}): missing 
parameter: ${e.message}`
+            );
         }
     });
 
diff --git a/test/index.js b/test/index.js
index a8c4173..8c26dad 100644
--- a/test/index.js
+++ b/test/index.js
@@ -2,3 +2,9 @@
 
 // Run jshint as part of normal testing
 require('mocha-jshint')();
+require('mocha-eslint')([
+    'lib',
+    'routes'
+], {
+    timeout: 10000
+});

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id6a2fe9c8656ce9947e2b9936275a40db704e402
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/services/mobileapps
Gerrit-Branch: master
Gerrit-Owner: Mholloway <mhollo...@wikimedia.org>

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

Reply via email to