diff --git a/README.md b/README.md index a6a6dce..73a3e88 100644 --- a/README.md +++ b/README.md @@ -190,75 +190,55 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link ## Configuration [back to top](#gitblog-md) -* `node_port` (default: 3000) - - the port the server is listening to -* `data_dir` (default: data) - - the directory where will be located the git repo with templates and articles -* `view_engine` (default: ejs) - - the Express view engine used to render pages from templates +* `node_port` (default: 3000) + the port the server is listening to +* `data_dir` (default: data) + the directory where will be located the git repo with templates and articles +* `view_engine` (default: ejs) + 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) * `modules` - * `rss` (default: true) - - activate the RSS endpoint and its features - * `webhook` (default: true) - - activate the webhook endpoint and its features - * `prism` (default: true) - - activate Prism code highlighting + * `rss` (default: true) + activate the RSS endpoint and its features + * `webhook` (default: true) + activate the webhook endpoint and its features + * `prism` (default: true) + activate Prism code highlighting * `home` - * `index` (default: index.ejs) - - the name of the home page template on the data directory - - it will receive `articles`, a list of articles for rendering - * `error` (default: error.ejs) - - the name of the error page template on the data directory - - it will receive `error`, the error code - * `hidden` (default: `[.ejs]`) - - file extensions to be returned 404 when reached + * `index` (default: index.ejs) + the name of the home page template on the data directory + it will receive `articles`, a list of articles for rendering + * `error` (default: error.ejs) + the name of the error page template on the data directory + it will receive `error`, the error code + * `hidden` (default: `[.ejs]`) + file extensions to be returned 404 when reached * `article` - * `index` (default: index.md) - - the name of the Markdown page of the article on the `/year/month/day/` directory - * `template` (default: template.ejs) - - the name of the article page template on the data directory - * `thumbnail_tag`: (default: thumbnail) - - the alt text searched to get the thumbnail image on the article - - as in `![]()` - * `default_title`: (default: Untitled) - - the title of the article in case a level 1 title was not found - * `default_thumbnail`: (default: none) - - the path of the default thumbnail to get from the data directory + * `index` (default: index.md) + the name of the Markdown page of the article on the `/year/month/day/` directory + * `template` (default: template.ejs) + the name of the article page template on the data directory + * `thumbnail_tag`: (default: thumbnail) + the alt text searched to get the thumbnail image on the article + as in `![]()` + * `default_title`: (default: Untitled) + the title of the article in case a level 1 title was not found + * `default_thumbnail`: (default: none) + the path of the default thumbnail to get from the data directory * `rss` * `title`: (default: mygitblog RSS feed) * `description`: (default: a generated RSS feed from my articles) * `endpoint`: (default: /rss) - * `length`: (default: 10) - - how many last articles will be present in the feed + * `length`: (default: 10) + how many last articles will be present in the feed * `webhook` * `endpoint`: (default: /webhook) - * `secret`: (default: none) - - see [above](#7-securize-your-webhook-optional-) - * `signature_header`: (default: none) - - see [above](#7-securize-your-webhook-optional-) - * `pull_command`: (default: git pull) - - the command used by the server on webhook trigger -* `showdown` - - Options to be applied to Showdown renderer (see [showdown options](https://github.com/showdownjs/showdown#valid-options) for more info) + * `secret`: (default: none) + see [above](#7-securize-your-webhook-optional-) + * `signature_header`: (default: none) + see [above](#7-securize-your-webhook-optional-) + * `pull_command`: (default: git pull) + the command used by the server on webhook trigger +* `showdown` + Options to be applied to Showdown renderer (see [showdown options](https://github.com/showdownjs/showdown#valid-options) for more info) diff --git a/src/app.js b/src/app.js index f6802d2..1e9d38a 100644 --- a/src/app.js +++ b/src/app.js @@ -3,6 +3,8 @@ const app = express(); const fs = require('fs'); const path = require('path'); +app.enable('trust proxy'); + //rss const Rss = require('rss'); @@ -94,6 +96,22 @@ module.exports = (config) => { }); }; + //log request at result end + app.use((req, res, next) => { + if (config['access_log']) { + 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', + {encoding: 'UTF-8'}, () => { + res.end = end; + res.end(chunk, encoding); + }); + }; + } + next(); + }); + // home endpoint : send the correct index page or error if not existing app.get('/', (req, res) => { const homePath = path.join(config['data_dir'], config['home']['index']); diff --git a/src/config.default.json b/src/config.default.json index 0ab7f55..49777fc 100644 --- a/src/config.default.json +++ b/src/config.default.json @@ -2,6 +2,7 @@ "node_port": 3000, "data_dir": "data", "view_engine": "ejs", + "access_log": "access.log", "modules": { "rss": true, "webhook": true, diff --git a/test/app.test.js b/test/app.test.js index c694be9..7b5d6d1 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -20,6 +20,7 @@ config['home']['hidden'].push('.test'); config['rss']['endpoint'] = '/rsstest'; config['rss']['length'] = 2; config['webhook']['endpoint'] = '/webhooktest'; +config['access_log'] = path.join(dataDir, 'access.log'); const app = require('../src/app')(config); @@ -35,6 +36,39 @@ afterAll(() => { } }); +describe('Test logging', () => { + test('test get 200', (done) => { + request(app).get('/rsstest').then(() => { + fs.readFile(path.join(dataDir, 'access.log'), {encoding: 'UTF-8'}, (err, data) => { + expect(err).toBeNull(); + expect(data).toBe('200 GET /rsstest ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\n'); + done(); + }); + }); + }); + test('test post 400', (done) => { + request(app).post('/rsstest').then(() => { + fs.readFile(path.join(dataDir, 'access.log'), {encoding: 'UTF-8'}, (err, data) => { + expect(err).toBeNull(); + expect(data).toBe('400 POST /rsstest ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\n'); + done(); + }); + }); + }); + test('test 2 requests', (done) => { + request(app).get('/rss').then(() => { + request(app).post('/rsstest').then(() => { + fs.readFile(path.join(dataDir, 'access.log'), {encoding: 'UTF-8'}, (err, data) => { + expect(err).toBeNull(); + expect(data).toBe('404 GET /rss ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\n' + + '400 POST /rsstest ' + new Date().toUTCString() + ' ::ffff:127.0.0.1\n'); + done(); + }); + }); + }); + }); +}); + describe('Test root path', () => { test('404 no index no error', (done) => { request(app).get('/').then((response) => {