From 8cc3d40b96323b31772ba0596395c73d5a6e3b1d Mon Sep 17 00:00:00 2001 From: Klemek Date: Sat, 22 Jun 2019 09:30:34 +0200 Subject: [PATCH 1/4] Fixed default config file --- src/config.default.json | 2 +- test/config.test.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/config.default.json b/src/config.default.json index 49777fc..7c9c6b4 100644 --- a/src/config.default.json +++ b/src/config.default.json @@ -20,7 +20,7 @@ "template": "template.ejs", "thumbnail_tag": "thumbnail", "default_title": "Untitled", - "default_thumbnail": null + "default_thumbnail": "" }, "rss": { "title": "mygitblog RSS feed", diff --git a/test/config.test.js b/test/config.test.js index fa72475..74bf82b 100644 --- a/test/config.test.js +++ b/test/config.test.js @@ -1,5 +1,6 @@ /* jshint -W117 */ const fs = require('fs'); +const path = require('path'); const configFile = 'config.json'; const tmpConfigFile = 'config.temp.json'; @@ -29,6 +30,18 @@ test('no config', () => { expect(config['data_dir']).toBe('data'); }); +test('example config', () => { + if (fs.existsSync(configFile)) + fs.unlinkSync(configFile); + fs.copyFileSync(path.join('src', 'config.default.json'), configFile); + const data = fs.readFileSync(configFile, {encoding: 'UTF-8'}); + fs.writeFileSync(configFile, data.replace('3000', '3333'), {encoding: 'UTF-8'}); + const config = require('../src/config')(); + expect(config).toBeDefined(); + expect(config['node_port']).toBe(3333); + expect(config['data_dir']).toBe('data'); +}); + test('invalid config ignored', () => { fs.writeFileSync(configFile, 'invalid JSON'); const config = require('../src/config')(); From c90d573f1185f094e61103495e49c3cc3189dc48 Mon Sep 17 00:00:00 2001 From: Klemek Date: Sat, 22 Jun 2019 09:35:32 +0200 Subject: [PATCH 2/4] Reformated some file walker tests --- test/file_walker.test.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/test/file_walker.test.js b/test/file_walker.test.js index 4eb6c2c..bf30e49 100644 --- a/test/file_walker.test.js +++ b/test/file_walker.test.js @@ -117,9 +117,10 @@ describe('Test index article reading', () => { `); fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { expect(err).toBeNull(); - expect(info).toBeDefined(); - expect(info.title).toBe('This is an awesome title !?¤'); - expect(info.thumbnail).toBe('./thumbnail.jpg'); + expect(info).toEqual({ + title: 'This is an awesome title !?¤', + thumbnail: './thumbnail.jpg' + }); done(); }); }); @@ -132,9 +133,10 @@ describe('Test index article reading', () => { `); fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { expect(err).toBeNull(); - expect(info).toBeDefined(); - expect(info.title).not.toBeDefined(); - expect(info.thumbnail).toBe('./thumbnail.jpg'); + expect(info).toEqual({ + title: undefined, + thumbnail: './thumbnail.jpg' + }); done(); }); }); @@ -143,9 +145,10 @@ describe('Test index article reading', () => { fs.writeFileSync(file, '#title'); fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { expect(err).toBeNull(); - expect(info).toBeDefined(); - expect(info.title).toBe('title'); - expect(info.thumbnail).not.toBeDefined(); + expect(info).toEqual({ + title: 'title', + thumbnail: undefined + }); done(); }); }); @@ -158,9 +161,10 @@ describe('Test index article reading', () => { `); fw.readIndexFile(file, 'thumbnail', (err, info) => { expect(err).toBeNull(); - expect(info).toBeDefined(); - expect(info.title).toBe('This is an awesome title !?¤'); - expect(info.thumbnail).not.toBeDefined(); + expect(info).toEqual({ + title: 'This is an awesome title !?¤', + thumbnail: undefined + }); done(); }); }); @@ -174,9 +178,10 @@ describe('Test index article reading', () => { `); fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { expect(err).toBeNull(); - expect(info).toBeDefined(); - expect(info.title).toBe('This is an awesome title !?¤'); - expect(info.thumbnail).toBe('./thumbnail.jpg'); + expect(info).toEqual({ + title: 'This is an awesome title !?¤', + thumbnail: './thumbnail.jpg' + }); done(); }); }); From 705dafa4e482e718909f7ffee63e3666bcc5cf51 Mon Sep 17 00:00:00 2001 From: Klemek Date: Sat, 22 Jun 2019 10:02:25 +0200 Subject: [PATCH 3/4] Error log option --- .gitignore | 3 ++- README.md | 2 ++ src/app.js | 14 ++++++++++---- src/config.default.json | 1 + test/app.test.js | 41 ++++++++++++++++++++++++++++++++++++++++- test/test_utils.js | 13 +++++++++++-- 6 files changed, 66 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 606eb9f..54ecd89 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ /config.example.json /data /test_data -/git_secret \ No newline at end of file +/access.log +/error.log \ No newline at end of file diff --git a/README.md b/README.md index 73a3e88..f32b751 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,8 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link the Express view engine used to render pages from templates * `access_log` (default: access.log) log file where to save access requests (empty to disable) +* `error_log` (default: error.log) + log file where to save all server errors (empty to disable) * `modules` * `rss` (default: true) activate the RSS endpoint and its features diff --git a/src/app.js b/src/app.js index 1e9d38a..08b72a0 100644 --- a/src/app.js +++ b/src/app.js @@ -102,7 +102,7 @@ module.exports = (config) => { const end = res.end; res.end = (chunk, encoding) => { fs.appendFile(config['access_log'], - res.statusCode + ' ' + req.method + ' ' + req.url + ' ' + new Date().toUTCString() + ' ' + (req.ips.join(' ') || req.ip) + '\n', + `${res.statusCode} ${req.method} ${req.url} ${new Date().toUTCString()} ${req.ips.join(' ') || req.ip}\n`, {encoding: 'UTF-8'}, () => { res.end = end; res.end(chunk, encoding); @@ -235,10 +235,16 @@ module.exports = (config) => { res.status(400).send('bad request'); }); + //log all server errors app.use((err, req, res, next) => { - console.log(cons.error, `error when handling ${req.path} request : ${err}`); - console.error(err.stack); - next(err); + console.log(cons.error, `error when handling ${req.method} ${req.path} request : ${err}`); + if (!config['error_log']) + next(err); + fs.appendFile(config['error_log'], + `500 ${req.method} ${req.url} ${new Date().toUTCString()} ${req.ips.join(' ') || req.ip}\n${err.stack}\n`, + {encoding: 'UTF-8'}, () => { + next(err); + }); }); // must be use in a server.js to start the server diff --git a/src/config.default.json b/src/config.default.json index 7c9c6b4..5f39d6e 100644 --- a/src/config.default.json +++ b/src/config.default.json @@ -3,6 +3,7 @@ "data_dir": "data", "view_engine": "ejs", "access_log": "access.log", + "error_log": "error.log", "modules": { "rss": true, "webhook": true, diff --git a/test/app.test.js b/test/app.test.js index 7b5d6d1..bea34ec 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -21,6 +21,7 @@ config['rss']['endpoint'] = '/rsstest'; config['rss']['length'] = 2; config['webhook']['endpoint'] = '/webhooktest'; config['access_log'] = path.join(dataDir, 'access.log'); +config['error_log'] = path.join(dataDir, 'error.log'); const app = require('../src/app')(config); @@ -36,7 +37,16 @@ afterAll(() => { } }); -describe('Test logging', () => { +describe('Test request logging', () => { + test('test no log', (done) => { + const tmp = config['access_log']; + config['access_log'] = ''; + request(app).get('/rsstest').then(() => { + config['access_log'] = tmp; + expect(fs.existsSync(path.join(dataDir, 'access.log'))).toBe(false); + done(); + }); + }); test('test get 200', (done) => { request(app).get('/rsstest').then(() => { fs.readFile(path.join(dataDir, 'access.log'), {encoding: 'UTF-8'}, (err, data) => { @@ -69,6 +79,35 @@ describe('Test logging', () => { }); }); +describe('Test error logging', () => { + test('test no log', (done) => { + const tmp = config['home']['hidden']; + config['home']['hidden'] = null; + const tmp2 = config['errpr_log']; + config['error_log'] = ''; + request(app).get('/somefile.txt').then(() => { + config['home']['hidden'] = tmp; + config['error_log'] = tmp2; + expect(fs.existsSync(path.join(dataDir, 'error.log'))).toBe(false); + done(); + }); + }); + test('test null error ', (done) => { + const tmp = config['home']['hidden']; + config['home']['hidden'] = null; + request(app).get('/somefile.txt').then(() => { + config['home']['hidden'] = tmp; + fs.readFile(path.join(dataDir, 'error.log'), {encoding: 'UTF-8'}, (err, data) => { + expect(err).toBeNull(); + const start = data.split('\n').slice(0, 2).join('\n'); + const expected = '500 GET /somefile.txt ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\nTypeError: Cannot read property \'includes\' of null'; + expect(start).toBe(expected); + done(); + }); + }); + }); +}); + describe('Test root path', () => { test('404 no index no error', (done) => { request(app).get('/').then((response) => { diff --git a/test/test_utils.js b/test/test_utils.js index 6b509c5..8c250f5 100644 --- a/test/test_utils.js +++ b/test/test_utils.js @@ -4,12 +4,21 @@ const path = require('path'); const deleteFolderSync = (dir) => { if (!fs.existsSync(dir)) return; - fs.readdirSync(dir, {withFileTypes: true}).forEach((item) => { + let items; + const deleteItem = (item) => { if (item.isDirectory()) deleteFolderSync(path.join(dir, item.name)); else fs.unlinkSync(path.join(dir, item.name)); - }); + }; + do { + items = fs.readdirSync(dir, {withFileTypes: true}); + try { + items.forEach(deleteItem); + } catch (e) { + console.error(e); + } + } while (items.length > 0); fs.rmdirSync(dir); }; From f760c4e0d331351ca0d149ac61a2fdd0e2ba3173 Mon Sep 17 00:00:00 2001 From: Klemek Date: Sat, 22 Jun 2019 10:03:22 +0200 Subject: [PATCH 4/4] Changed version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc3d0be..75cba16 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "nodePort": 5000, "name": "gitblog.md", - "version": "1.0.1", + "version": "1.0.2", "description": "A static blog using Markdown pulled from your git repository.", "main": "src/server.js", "dependencies": {