Merge pull request #3 from Klemek/dev

v1.0.2
This commit is contained in:
Klemek
2019-06-22 10:06:03 +02:00
committed by GitHub
9 changed files with 101 additions and 25 deletions
+2 -1
View File
@@ -4,4 +4,5 @@
/config.example.json /config.example.json
/data /data
/test_data /test_data
/git_secret /access.log
/error.log
+2
View File
@@ -203,6 +203,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 the Express view engine used to render pages from templates
* `access_log` (default: access.log) * `access_log` (default: access.log)
log file where to save access requests (empty to disable) 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` * `modules`
* `rss` (default: true) * `rss` (default: true)
activate the RSS endpoint and its features activate the RSS endpoint and its features
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"nodePort": 5000, "nodePort": 5000,
"name": "gitblog.md", "name": "gitblog.md",
"version": "1.0.1", "version": "1.0.2",
"description": "A static blog using Markdown pulled from your git repository.", "description": "A static blog using Markdown pulled from your git repository.",
"main": "src/server.js", "main": "src/server.js",
"dependencies": { "dependencies": {
+9 -3
View File
@@ -102,7 +102,7 @@ module.exports = (config) => {
const end = res.end; const end = res.end;
res.end = (chunk, encoding) => { res.end = (chunk, encoding) => {
fs.appendFile(config['access_log'], 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'}, () => { {encoding: 'UTF-8'}, () => {
res.end = end; res.end = end;
res.end(chunk, encoding); res.end(chunk, encoding);
@@ -235,10 +235,16 @@ module.exports = (config) => {
res.status(400).send('bad request'); res.status(400).send('bad request');
}); });
//log all server errors
app.use((err, req, res, next) => { app.use((err, req, res, next) => {
console.log(cons.error, `error when handling ${req.path} request : ${err}`); console.log(cons.error, `error when handling ${req.method} ${req.path} request : ${err}`);
console.error(err.stack); if (!config['error_log'])
next(err); 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 // must be use in a server.js to start the server
+2 -1
View File
@@ -3,6 +3,7 @@
"data_dir": "data", "data_dir": "data",
"view_engine": "ejs", "view_engine": "ejs",
"access_log": "access.log", "access_log": "access.log",
"error_log": "error.log",
"modules": { "modules": {
"rss": true, "rss": true,
"webhook": true, "webhook": true,
@@ -20,7 +21,7 @@
"template": "template.ejs", "template": "template.ejs",
"thumbnail_tag": "thumbnail", "thumbnail_tag": "thumbnail",
"default_title": "Untitled", "default_title": "Untitled",
"default_thumbnail": null "default_thumbnail": ""
}, },
"rss": { "rss": {
"title": "mygitblog RSS feed", "title": "mygitblog RSS feed",
+40 -1
View File
@@ -21,6 +21,7 @@ config['rss']['endpoint'] = '/rsstest';
config['rss']['length'] = 2; config['rss']['length'] = 2;
config['webhook']['endpoint'] = '/webhooktest'; config['webhook']['endpoint'] = '/webhooktest';
config['access_log'] = path.join(dataDir, 'access.log'); config['access_log'] = path.join(dataDir, 'access.log');
config['error_log'] = path.join(dataDir, 'error.log');
const app = require('../src/app')(config); 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) => { test('test get 200', (done) => {
request(app).get('/rsstest').then(() => { request(app).get('/rsstest').then(() => {
fs.readFile(path.join(dataDir, 'access.log'), {encoding: 'UTF-8'}, (err, data) => { 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', () => { describe('Test root path', () => {
test('404 no index no error', (done) => { test('404 no index no error', (done) => {
request(app).get('/').then((response) => { request(app).get('/').then((response) => {
+13
View File
@@ -1,5 +1,6 @@
/* jshint -W117 */ /* jshint -W117 */
const fs = require('fs'); const fs = require('fs');
const path = require('path');
const configFile = 'config.json'; const configFile = 'config.json';
const tmpConfigFile = 'config.temp.json'; const tmpConfigFile = 'config.temp.json';
@@ -29,6 +30,18 @@ test('no config', () => {
expect(config['data_dir']).toBe('data'); 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', () => { test('invalid config ignored', () => {
fs.writeFileSync(configFile, 'invalid JSON'); fs.writeFileSync(configFile, 'invalid JSON');
const config = require('../src/config')(); const config = require('../src/config')();
+20 -15
View File
@@ -117,9 +117,10 @@ describe('Test index article reading', () => {
`); `);
fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { fw.readIndexFile(file, 'custom_thumbnail', (err, info) => {
expect(err).toBeNull(); expect(err).toBeNull();
expect(info).toBeDefined(); expect(info).toEqual({
expect(info.title).toBe('This is an awesome title !?¤'); title: 'This is an awesome title !?¤',
expect(info.thumbnail).toBe('./thumbnail.jpg'); thumbnail: './thumbnail.jpg'
});
done(); done();
}); });
}); });
@@ -132,9 +133,10 @@ describe('Test index article reading', () => {
`); `);
fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { fw.readIndexFile(file, 'custom_thumbnail', (err, info) => {
expect(err).toBeNull(); expect(err).toBeNull();
expect(info).toBeDefined(); expect(info).toEqual({
expect(info.title).not.toBeDefined(); title: undefined,
expect(info.thumbnail).toBe('./thumbnail.jpg'); thumbnail: './thumbnail.jpg'
});
done(); done();
}); });
}); });
@@ -143,9 +145,10 @@ describe('Test index article reading', () => {
fs.writeFileSync(file, '#title'); fs.writeFileSync(file, '#title');
fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { fw.readIndexFile(file, 'custom_thumbnail', (err, info) => {
expect(err).toBeNull(); expect(err).toBeNull();
expect(info).toBeDefined(); expect(info).toEqual({
expect(info.title).toBe('title'); title: 'title',
expect(info.thumbnail).not.toBeDefined(); thumbnail: undefined
});
done(); done();
}); });
}); });
@@ -158,9 +161,10 @@ describe('Test index article reading', () => {
`); `);
fw.readIndexFile(file, 'thumbnail', (err, info) => { fw.readIndexFile(file, 'thumbnail', (err, info) => {
expect(err).toBeNull(); expect(err).toBeNull();
expect(info).toBeDefined(); expect(info).toEqual({
expect(info.title).toBe('This is an awesome title !?¤'); title: 'This is an awesome title !?¤',
expect(info.thumbnail).not.toBeDefined(); thumbnail: undefined
});
done(); done();
}); });
}); });
@@ -174,9 +178,10 @@ describe('Test index article reading', () => {
`); `);
fw.readIndexFile(file, 'custom_thumbnail', (err, info) => { fw.readIndexFile(file, 'custom_thumbnail', (err, info) => {
expect(err).toBeNull(); expect(err).toBeNull();
expect(info).toBeDefined(); expect(info).toEqual({
expect(info.title).toBe('This is an awesome title !?¤'); title: 'This is an awesome title !?¤',
expect(info.thumbnail).toBe('./thumbnail.jpg'); thumbnail: './thumbnail.jpg'
});
done(); done();
}); });
}); });
+11 -2
View File
@@ -4,12 +4,21 @@ const path = require('path');
const deleteFolderSync = (dir) => { const deleteFolderSync = (dir) => {
if (!fs.existsSync(dir)) if (!fs.existsSync(dir))
return; return;
fs.readdirSync(dir, {withFileTypes: true}).forEach((item) => { let items;
const deleteItem = (item) => {
if (item.isDirectory()) if (item.isDirectory())
deleteFolderSync(path.join(dir, item.name)); deleteFolderSync(path.join(dir, item.name));
else else
fs.unlinkSync(path.join(dir, item.name)); 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); fs.rmdirSync(dir);
}; };