From 3c4a558e02a722e5f29637ce956b5478197088cd Mon Sep 17 00:00:00 2001 From: "D. Berge" Date: Tue, 29 Dec 2020 16:20:57 +0100 Subject: [PATCH] Serve OpenAPI document on API root. When a client makes a request for `/` (the root of the API), the OpenAPI description is served in an appropriate format according to the `Accept` request header, as follows: Accept: text/html => HTML version Accept: application/json => JSON version Accept: * => YAML version --- lib/www/server/api/index.js | 3 ++ lib/www/server/api/middleware/index.js | 3 +- lib/www/server/api/middleware/openapi/get.js | 44 +++++++++++++++++++ .../server/api/middleware/openapi/index.js | 4 ++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 lib/www/server/api/middleware/openapi/get.js create mode 100644 lib/www/server/api/middleware/openapi/index.js diff --git a/lib/www/server/api/index.js b/lib/www/server/api/index.js index 5636571..7d4cd21 100644 --- a/lib/www/server/api/index.js +++ b/lib/www/server/api/index.js @@ -71,6 +71,9 @@ app.map({ '/logout': { get: [ mw.user.logout ], post: [ mw.user.logout ] + }, + '/': { + get: [ mw.openapi.get ] } }); diff --git a/lib/www/server/api/middleware/index.js b/lib/www/server/api/middleware/index.js index e096595..eaecf29 100644 --- a/lib/www/server/api/middleware/index.js +++ b/lib/www/server/api/middleware/index.js @@ -11,5 +11,6 @@ module.exports = { navdata: require('./navdata'), configuration: require('./configuration'), info: require('./info'), - meta: require('./meta') + meta: require('./meta'), + openapi: require('./openapi') }; diff --git a/lib/www/server/api/middleware/openapi/get.js b/lib/www/server/api/middleware/openapi/get.js new file mode 100644 index 0000000..e23f2a6 --- /dev/null +++ b/lib/www/server/api/middleware/openapi/get.js @@ -0,0 +1,44 @@ +const fs = require('fs'); +const path = require('path'); +const YAML = require('yaml'); + +const openapiYAML = path.join(__dirname, "../../../spec/openapi.yaml"); +const openapiHTML = path.join(__dirname, "../../../spec/openapi.html"); + +module.exports = async function (req, res, next) { + + function handleError (err) { + if (err instanceof TypeError || err.code == "ENOENT") { + res.status(404).send(); + next(); + } else { + next(err); + } + } + + try { + if (req.accepts("text/html")) { + const stream = fs.createReadStream(openapiHTML); + stream.on('open', () => { + res.set("Content-Type", "text/html"); + stream.pipe(res); + }); + stream.on('end', next); + stream.on('error', handleError); + } else if (req.accepts("application/json")) { + const text = await fs.promises.readFile(openapiYAML, 'utf8'); + res.json(YAML.parse(text)); + next(); + } else { + const stream = fs.createReadStream(openapiYAML); + stream.on('open', () => { + res.set("Content-Type", "application/yaml"); + stream.pipe(res); + }); + stream.on('end', next); + stream.on('error', handleError); + } + } catch (err) { + handleError(err); + } +}; diff --git a/lib/www/server/api/middleware/openapi/index.js b/lib/www/server/api/middleware/openapi/index.js new file mode 100644 index 0000000..fe5c66b --- /dev/null +++ b/lib/www/server/api/middleware/openapi/index.js @@ -0,0 +1,4 @@ + +module.exports = { + get: require('./get') +}