Hidden files path matching
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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*']);
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user