Hidden files path matching

This commit is contained in:
Klemek
2019-06-26 20:59:42 +02:00
parent 1b91002c03
commit 6af4012522
6 changed files with 73 additions and 44 deletions
+1 -3
View File
@@ -140,9 +140,7 @@ In your template, the following data is sent :
* `path` : the URL path for the folder of the article (without the title) * `path` : the URL path for the folder of the article (without the title)
* `realPath` : the system's path for the folder * `realPath` : the system's path for the folder
* `escapedTitle` : the code with alphanumeric and underscore characters only * `escapedTitle` : the code with alphanumeric and underscore characters only
* `error` (error pages only) * `error` (error pages only) : the error code
* `error` : the error code
* `path` : the resource that caused the error
#### 5. Create and init your git source #### 5. Create and init your git source
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "gitblog.md", "name": "gitblog.md",
"version": "1.2.2", "version": "1.2.3",
"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": {
+34 -29
View File
@@ -26,6 +26,28 @@ const cons = {
}; };
module.exports = (config) => { module.exports = (config) => {
/**
* Fetch articles from the data folder and send success as a response
* @param success
* @param error
*/
let reload;
/**
* Render the page with the view engine and catch errors
* @param req
* @param res
* @param vPath - path of the view
* @param data - data to pass to the view
* @param code - code to send along the page
*/
let render;
/**
* Show an error with the correct page
* @param req
* @param res
* @param code - error code
*/
let showError;
const fw = require('./file_walker')(config); const fw = require('./file_walker')(config);
const renderer = require('./renderer')(config); const renderer = require('./renderer')(config);
@@ -38,12 +60,7 @@ module.exports = (config) => {
let lastRSS = ''; let lastRSS = '';
let host = config['host']; let host = config['host'];
/** reload = (success, error) => {
* Fetch articles from the data folder and send success as a response
* @param success
* @param error
*/
const reload = (success, error) => {
fw.fetchArticles((err, dict) => { fw.fetchArticles((err, dict) => {
if (err) { if (err) {
console.error(cons.error, 'error loading articles : ' + err); console.error(cons.error, 'error loading articles : ' + err);
@@ -65,15 +82,7 @@ module.exports = (config) => {
if (config['test']) if (config['test'])
app.reload = reload; app.reload = reload;
/** render = (req, res, vPath, data, code = 200) => {
* Render the page with the view engine and catch errors
* @param req
* @param res
* @param vPath - path of the view
* @param data - data to pass to the view
* @param code - code to send along the page
*/
const render = (req, res, vPath, data, code = 200) => {
data.info = { data.info = {
title: config['home']['title'], title: config['home']['title'],
description: config['home']['description'], description: config['home']['description'],
@@ -83,27 +92,24 @@ module.exports = (config) => {
config: config config: config
}; };
res.render(vPath, data, (err, html) => { res.render(vPath, data, (err, html) => {
if (err) { if (err && vPath !== path.join(config['data_dir'], config['home']['error'])) {
console.log(cons.error, `failed to render page ${vPath} : ${err}`);
showError(req, res, 500);
} else if (err) {
res.sendStatus(500); res.sendStatus(500);
console.log(cons.error, `failed to render ${vPath} : ${err}`); console.log(cons.error, `failed to render error page : ${err}`);
} else } else
res.status(code).send(html); res.status(code).send(html);
}); });
}; };
/** showError = (req, res, code) => {
* Show an error with the correct page
* @param req
* @param res
* @param code - error code
*/
const showError = (req, res, code) => {
const errorPath = path.join(config['data_dir'], config['home']['error']); const errorPath = path.join(config['data_dir'], config['home']['error']);
fs.access(errorPath, fs.constants.R_OK, (err) => { fs.access(errorPath, fs.constants.R_OK, (err) => {
if (err) if (err)
res.sendStatus(code); res.sendStatus(code);
else else
render(req, res, errorPath, {error: code, path: req.path}, code); render(req, res, errorPath, {error: code}, code);
}); });
}; };
@@ -232,11 +238,10 @@ module.exports = (config) => {
}); });
// catch all hidden file type and return 404 // catch all hidden file type and return 404
app.get('*', (req, res, next) => { config['home']['hidden'].forEach(pathMatcher => {
if (config['home']['hidden'].includes(path.extname(req.path))) app.get(pathMatcher, (req, res) => {
showError(req, res, 404); showError(req, res, 404);
else });
next();
}); });
// serve all static files via get // serve all static files via get
+2 -1
View File
@@ -18,7 +18,8 @@
"index": "index.ejs", "index": "index.ejs",
"error": "error.ejs", "error": "error.ejs",
"hidden": [ "hidden": [
".ejs" "*.ejs",
"/.git*"
] ]
}, },
"article": { "article": {
+34 -9
View File
@@ -16,16 +16,15 @@ config['data_dir'] = dataDir;
config['webhook']['endpoint'] = '/webhooktest'; config['webhook']['endpoint'] = '/webhooktest';
config['rss']['endpoint'] = '/rsstest'; config['rss']['endpoint'] = '/rsstest';
config['rss']['length'] = 2; config['rss']['length'] = 2;
config['home']['index'] = testIndex;
config['home']['error'] = testError; config['home']['error'] = testError;
config['article']['template'] = testTemplate; config['article']['template'] = testTemplate;
const app = require('../src/app')(config); const app = require('../src/app')(config);
beforeEach((done, fail) => { beforeEach((done, fail) => {
config['home']['index'] = testIndex;
config['data_dir'] = dataDir; config['data_dir'] = dataDir;
config['article']['index'] = 'index.md'; config['article']['index'] = 'index.md';
config['home']['hidden'] = ['.ejs', '.test'];
config['access_log'] = ''; config['access_log'] = '';
config['error_log'] = ''; config['error_log'] = '';
config['modules']['rss'] = true; config['modules']['rss'] = true;
@@ -93,20 +92,20 @@ describe('Test request logging', () => {
describe('Test error logging', () => { describe('Test error logging', () => {
test('test no log', (done) => { test('test no log', (done) => {
config['home']['hidden'] = null; config['home']['index'] = null;
request(app).get('/somefile.txt').then(() => { request(app).get('/').then(() => {
expect(fs.existsSync(path.join(dataDir, 'error.log'))).toBe(false); expect(fs.existsSync(path.join(dataDir, 'error.log'))).toBe(false);
done(); done();
}); });
}); });
test('test null error ', (done) => { test('test null error ', (done) => {
config['home']['hidden'] = null; config['home']['index'] = null;
config['error_log'] = path.join(dataDir, 'error.log'); config['error_log'] = path.join(dataDir, 'error.log');
request(app).get('/somefile.txt').then(() => { request(app).get('/').then(() => {
fs.readFile(path.join(dataDir, 'error.log'), {encoding: 'UTF-8'}, (err, data) => { fs.readFile(path.join(dataDir, 'error.log'), {encoding: 'UTF-8'}, (err, data) => {
expect(err).toBeNull(); expect(err).toBeNull();
const start = data.split('\n').slice(0, 2).join('\n'); 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'; const expected = '500 GET / ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\nTypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type object';
expect(start).toBe(expected); expect(start).toBe(expected);
done(); done();
}); });
@@ -136,6 +135,23 @@ describe('Test root path', () => {
done(); done();
}); });
}); });
test('500 render error with page', (done) => {
fs.writeFileSync(path.join(dataDir, testIndex), 'articles <%= null.length %>');
fs.writeFileSync(path.join(dataDir, testError), 'error <%= error %>');
request(app).get('/').then((response) => {
expect(response.statusCode).toBe(500);
expect(response.text).toBe('error 500');
done();
});
});
test('500 render error with failing page', (done) => {
fs.writeFileSync(path.join(dataDir, testIndex), 'articles <%= null.length %>');
fs.writeFileSync(path.join(dataDir, testError), 'error <%= null.error %>');
request(app).get('/').then((response) => {
expect(response.statusCode).toBe(500);
done();
});
});
test('200 no articles', (done) => { test('200 no articles', (done) => {
fs.writeFileSync(path.join(dataDir, testIndex), 'articles <%= articles.length %>'); fs.writeFileSync(path.join(dataDir, testIndex), 'articles <%= articles.length %>');
request(app).get('/').then((response) => { request(app).get('/').then((response) => {
@@ -386,8 +402,17 @@ describe('Test static files', () => {
}); });
}); });
test('404 hidden file', (done) => { test('404 hidden file', (done) => {
fs.writeFileSync(path.join(dataDir, 'somefile.test'), ''); utils.createEmptyDirs([path.join(dataDir, 'tmp')]);
request(app).get('/somefile.test').then((response) => { fs.writeFileSync(path.join(dataDir, 'tmp', 'somefile.ejs'), '');
request(app).get('/tmp/somefile.ejs').then((response) => {
expect(response.statusCode).toBe(404);
done();
});
});
test('404 hidden folder', (done) => {
utils.createEmptyDirs([path.join(dataDir, '.git')]);
fs.writeFileSync(path.join(dataDir, '.git', 'file.txt'), '');
request(app).get('/.git/file.txt').then((response) => {
expect(response.statusCode).toBe(404); expect(response.statusCode).toBe(404);
done(); done();
}); });
+1 -1
View File
@@ -77,5 +77,5 @@ test('array fix', () => {
fs.writeFileSync(configFile, '{"home":{"hidden":{}}}'); fs.writeFileSync(configFile, '{"home":{"hidden":{}}}');
const config = require('../src/config')(); const config = require('../src/config')();
expect(config).toBeDefined(); expect(config).toBeDefined();
expect(config['home']['hidden']).toEqual(['.ejs']); expect(config['home']['hidden']).toEqual(['*.ejs', '/.git*']);
}); });