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 <[email protected]>
Gerrit-Reviewer: Ottomata <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits