From: Justin Wind Date: Fri, 10 Sep 2021 18:46:29 +0000 (-0700) Subject: Merge branch 'v1.2-dev' as v1.2.1 X-Git-Tag: v1.2.1 X-Git-Url: http://git.squeep.com/?p=websub-hub;a=commitdiff_plain;h=f92c90e92ded661ddd957580e7fbde8aaa24224d;hp=085b55f507dedc16016bb491d520c556acd60643 Merge branch 'v1.2-dev' as v1.2.1 --- diff --git a/.gitignore b/.gitignore index 622f9a7..88f74fe 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ node_modules coverage .vscode *.sqlite* +static/*.gz +static/*.br diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b458a4..0f153a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ Releases and notable changes to this project are documented here. ## [Unreleased] +## [v1.2.1] + +### Fixed + +- Minor issues and dependency updates. + ## [v1.2.0] - 2021-08-28 ### Added diff --git a/config/default.js b/config/default.js index 70837b1..64f45ec 100644 --- a/config/default.js +++ b/config/default.js @@ -46,7 +46,7 @@ const defaultOptions = { pageTitle: packageName, // title on html pages footerEntries: [ // common footers on all html pages 'Development Repository / GitHub mirror', - '©', + '©', ], strictSecrets: false, // If true, reject requests with secrets but not over https publicHub: true, // Accept publish requests as new topics. diff --git a/package-lock.json b/package-lock.json index 002506d..cca2037 100644 --- a/package-lock.json +++ b/package-lock.json @@ -572,8 +572,8 @@ "dev": true }, "@squeep/api-dingus": { - "version": "git+https://git.squeep.com/squeep-api-dingus/#ca35f167826c0732571da5f35e3c25881d138b79", - "from": "git+https://git.squeep.com/squeep-api-dingus/#v1.1.0", + "version": "git+https://git.squeep.com/squeep-api-dingus/#842a9b1e5b62aa642a53269a8466fd1e021e4ff2", + "from": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.0", "requires": { "mime-db": "^1.49.0", "uuid": "^8.3.2" @@ -745,11 +745,11 @@ "dev": true }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "balanced-match": { @@ -1161,17 +1161,17 @@ "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" }, "domhandler": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", - "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", + "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", "requires": { "domelementtype": "^2.2.0" } }, "domutils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", - "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "requires": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -1549,9 +1549,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", + "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==" }, "foreground-child": { "version": "2.0.0", @@ -1771,13 +1771,13 @@ "dev": true }, "htmlparser2": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.0.0.tgz", - "integrity": "sha512-IhdltX9BWhYQft4UPA92jFasNajskja0om6vU0DaIEL4OseCg5zE+mHAMr51AT89TbzzECrQWJ4CZ5NVYTPlKw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.1.1.tgz", + "integrity": "sha512-hZb0lfG0hbhR/hB879zbBr8Opv0Be9Zp+JYHgqTw5epF++aotu/zmMTPLy/60iJyR1MaD/3pYRp7xYteXsZMEA==", "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.0.0", - "domutils": "^2.5.2", + "domutils": "^2.8.0", "entities": "^3.0.1" } }, @@ -2236,9 +2236,9 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mocha": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.0.tgz", - "integrity": "sha512-Kjg/XxYOFFUi0h/FwMOeb6RoroiZ+P1yOfya6NK7h3dNhahrJx1r2XIT3ge4ZQvJM86mdjNA+W5phqRQh7DwCg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -3450,9 +3450,9 @@ } }, "tar": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz", - "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", diff --git a/package.json b/package.json index a16ad0e..94a4957 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "websub-hub", - "version": "1.2.0", + "version": "1.2.1", "description": "A WebSub Hub server implementation.", "main": "server.js", "scripts": { @@ -32,13 +32,13 @@ "coverage-check" ], "dependencies": { - "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.1.0", + "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.0", "@squeep/web-linking": "git+https://git.squeep.com/squeep-web-linking/#v1.0.0", "argon2": "^0.28.2", - "axios": "^0.21.1", + "axios": "^0.21.4", "better-sqlite3": "^7.4.3", "feedparser": "^2.2.10", - "htmlparser2": "^7.0.0", + "htmlparser2": "^7.1.1", "iconv": "^3.0.0", "pg-promise": "^10.11.0" }, @@ -47,7 +47,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-security": "^1.4.0", "eslint-plugin-sonarjs": "^0.10.0", - "mocha": "^9.1.0", + "mocha": "^9.1.1", "mocha-steps": "^1.3.0", "nyc": "^15.1.0", "pre-commit": "^1.2.2", diff --git a/src/communication.js b/src/communication.js index 097da63..b112377 100644 --- a/src/communication.js +++ b/src/communication.js @@ -443,7 +443,7 @@ class Communication { // Cull any expired subscriptions await this.db.subscriptionDeleteExpired(dbCtx, topicId); - logInfoData.url = topicId.url; + logInfoData.url = topic.url; if (topic.isDeleted) { this.logger.debug(_scope, 'topic deleted, skipping update request', logInfoData); diff --git a/src/link-helper.js b/src/link-helper.js index 2b6a833..93a947b 100644 --- a/src/link-helper.js +++ b/src/link-helper.js @@ -60,7 +60,7 @@ class LinkHelper { if (nonUTF8Charset) { const iconv = new Iconv(nonUTF8Charset, 'utf-8//translit//ignore'); try { - body = iconv.convert(body); + body = iconv.convert(body).toString('utf8'); } catch (e) { /* istanbul ignore next */ this.logger.error(_scope, 'iconv conversion error', { error: e, contentType, url }); diff --git a/src/service.js b/src/service.js index c69f6fb..df56ba0 100644 --- a/src/service.js +++ b/src/service.js @@ -40,14 +40,14 @@ class Service extends Dingus { // These routes are intended for accessing static content during development. // In production, a proxy server would likely handle these first. - this.on(['GET', 'HEAD'], '/static', (req, res, ctx) => this.handlerRedirect(req, res, ctx, `${options.dingus.proxyPrefix}/static/`)); - this.on(['GET', 'HEAD'], '/static/', (req, res, ctx) => this.handlerGetStaticFile(req, res, ctx, 'index.html')); + this.on(['GET', 'HEAD'], '/static', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/static/`); + this.on(['GET', 'HEAD'], '/static/', this.handlerGetStaticFile.bind(this), 'index.html'); this.on(['GET', 'HEAD'], '/static/:file', this.handlerGetStaticFile.bind(this)); - this.on(['GET', 'HEAD'], '/favicon.ico', (req, res, ctx) => this.handlerGetStaticFile(req, res, ctx, 'favicon.ico')); - this.on(['GET', 'HEAD'], '/robots.txt', (req, res, ctx) => this.handlerGetStaticFile(req, res, ctx, 'robots.txt')); + this.on(['GET', 'HEAD'], '/favicon.ico', this.handlerGetStaticFile.bind(this), 'favicon.ico'); + this.on(['GET', 'HEAD'], '/robots.txt', this.handlerGetStaticFile.bind(this), 'robots.txt'); // Private informational endpoints - this.on(['GET', 'HEAD'], '/admin', (req, res, ctx) => this.handlerRedirect(req, res, ctx, `${options.dingus.proxyPrefix}/admin/`)); + this.on(['GET', 'HEAD'], '/admin', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/admin/`); this.on(['GET', 'HEAD'], '/admin/', this.handlerGetAdminOverview.bind(this)); this.on(['GET', 'HEAD'], '/admin/topic/:topicId', this.handlerGetAdminTopicDetails.bind(this)); @@ -60,22 +60,6 @@ class Service extends Dingus { } - /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx - * @param {String} newPath - */ - async handlerRedirect(req, res, ctx, newPath) { - const _scope = _fileScope('handlerRedirect'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx }); - - res.setHeader(Enum.Header.Location, newPath); - res.statusCode = 307; // Temporary Redirect - res.end(); - } - - /** * @param {http.ClientRequest} req * @param {http.ServerResponse} res @@ -240,25 +224,6 @@ class Service extends Dingus { } - /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {object} ctx - */ - async handlerGetStaticFile(req, res, ctx, file) { - const _scope = _fileScope('handlerGetStaticFile'); - this.logger.debug(_scope, 'called', { req: common.requestLogData(req), ctx, file }); - - Dingus.setHeadHandler(req, res, ctx); - - // Set a default response type to handle any errors; will be re-set to serve actual static content type. - this.setResponseType(this.responseTypes, req, res, ctx); - - await this.serveFile(req, res, ctx, this.staticPath, file || ctx.params.file); - this.logger.info(_scope, 'finished', { ctx: { ...ctx, responseBody: common.logTruncate((ctx.responseBody || '').toString(), 100) } }); - } - - /** * @param {http.ClientRequest} req * @param {http.ServerResponse} res diff --git a/src/template/root-html.js b/src/template/root-html.js index c68d52a..8797564 100644 --- a/src/template/root-html.js +++ b/src/template/root-html.js @@ -46,6 +46,15 @@ function usageSection(isPublicHub, hubURL) { +
  • + Ideally, these should be combined in one header. +
    +
    Example:
    + + Link: <${hubURL}>; rel="hub", <https://example.com/feed/>; rel="self" + +
    +
  • @@ -73,15 +82,21 @@ function usageSection(isPublicHub, hubURL) {

    Publishing Updates

    - Send a POST request to this hub with Form Data: + To notify the Hub that a topic's content has been updated and should be distributed to subscribers, send a POST request with Form Data (application/x-www-form-urlencoded): +
    +
    Example:
    + + curl ${hubURL} -d'hub.mode=publish' -d'hub.url=https://example.com/blog_one/feed' -d'hub.url=https://example.com/blog_two/feed' + +
    ` : `

    Private Hub

    diff --git a/test/src/service.js b/test/src/service.js index a00b2ce..7a97cf5 100644 --- a/test/src/service.js +++ b/test/src/service.js @@ -60,14 +60,6 @@ describe('Service', function () { }); }); // maybeIngestBody - describe('handlerRedirect', function () { - it('covers', async function () { - await service.handlerRedirect(req, res, ctx, '/'); - assert(res.end.called); - assert.strictEqual(res.statusCode, 307); - }); - }); // handlerRedirect - describe('handlerPostRoot', function () { it('covers public mode', async function () { await service.handlerPostRoot(req, res, ctx); @@ -123,14 +115,6 @@ describe('Service', function () { }) }); // handlerGetAdminTopicDetails - describe('handlerGetStaticFile', function () { - it('covers', async function () { - service.serveFile.resolves(); - await service.handlerGetStaticFile(req, res, ctx); - assert(service.serveFile.called); - }); - }); // handlerGetStaticFile - describe('handlerPostAdminProcess', function () { it('covers', async function () { service.serveFile.resolves();