Fix & refactor server routing + add tests (#799)

* Fix bad routing regex for sitemap & feed

* add tests for sitemap & feed

* use next middleware function if file nto found

* add pages routing & test

* refactor + add more test for page routing

* extension-less url routing + test

* refactor out requestFile

* add dot routing + test to handle special case like http://localhost:3000/blog/2018/05/27/1.13.0

* exit properly

* add more test for sitemap

* update nits from my phone
This commit is contained in:
Endilie Yacop Sucipto 2018-06-29 16:15:34 +08:00 committed by GitHub
parent e9f290f788
commit e9eef39760
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 231 additions and 37 deletions

View file

@ -20,7 +20,15 @@ function execute(port, options) {
const path = require('path');
const color = require('color');
const getTOC = require('../core/getTOC');
const {docsRouting, blogRouting} = require('../core/routing');
const {
blogRouting,
docsRouting,
dotRouting,
feedRouting,
pageRouting,
noExtRouting,
sitemapRouting,
} = require('../core/routing');
const mkdirp = require('mkdirp');
const glob = require('glob');
const chalk = require('chalk');
@ -123,6 +131,24 @@ function execute(port, options) {
return false;
}
function requestFile(url, res, notFoundCallback) {
request.get(url, (error, response, body) => {
if (!error) {
if (response) {
if (response.statusCode === 404 && notFoundCallback) {
notFoundCallback();
} else {
res.status(response.statusCode).send(body);
}
} else {
console.error('No response');
}
} else {
console.error('Request failed:', error);
}
});
}
/****************************************************************************/
reloadMetadata();
@ -257,7 +283,7 @@ function execute(port, options) {
res.send(renderToStaticMarkupWithDoctype(docComp));
});
app.get('/sitemap.xml', function(req, res) {
app.get(sitemapRouting(siteConfig.baseUrl), (req, res) => {
res.set('Content-Type', 'application/xml');
sitemap(xml => {
@ -265,18 +291,22 @@ function execute(port, options) {
});
});
app.get(/blog\/.*xml$/, (req, res) => {
app.get(feedRouting(siteConfig.baseUrl), (req, res, next) => {
res.set('Content-Type', 'application/rss+xml');
let parts = req.path.toString().split('blog/');
if (parts[1].toLowerCase() == 'atom.xml') {
let file = req.path
.toString()
.split('blog/')[1]
.toLowerCase();
if (file === 'atom.xml') {
res.send(feed('atom'));
return;
} else if (file === 'feed.xml') {
res.send(feed('rss'));
}
res.send(feed('rss'));
next();
});
// Handle all requests for blog pages and posts.
app.get(blogRouting(siteConfig.baseUrl), (req, res) => {
app.get(blogRouting(siteConfig.baseUrl), (req, res, next) => {
// Regenerate the blog metadata in case it has changed. Consider improving
// this to regenerate on file save rather than on page request.
reloadMetadataBlog();
@ -330,6 +360,11 @@ function execute(port, options) {
file = file.replace(new RegExp('/', 'g'), '-');
file = join(CWD, 'blog', file);
if (!fs.existsSync(file)) {
next();
return;
}
const result = metadataUtils.extractMetadata(
fs.readFileSync(file, {encoding: 'utf8'})
);
@ -361,7 +396,7 @@ function execute(port, options) {
});
// handle all other main pages
app.get('*.html', (req, res, next) => {
app.get(pageRouting(siteConfig.baseUrl), (req, res, next) => {
// look for user provided html file first
let htmlFile = req.path.toString().replace(siteConfig.baseUrl, '');
htmlFile = join(CWD, 'pages', htmlFile);
@ -394,6 +429,7 @@ function execute(port, options) {
} else {
res.send(fs.readFileSync(htmlFile, {encoding: 'utf8'}));
}
next();
return;
}
@ -535,36 +571,30 @@ function execute(port, options) {
// "redirect" requests to pages ending with "/" or no extension so that,
// for example, request to "blog" returns "blog/index.html" or "blog.html"
app.get(/\/[^\.]*\/?$/, (req, res) => {
const requestFile = (url, notFoundCallback) => {
request.get(url, (error, response, body) => {
if (!error) {
if (response) {
if (response.statusCode === 404 && notFoundCallback) {
notFoundCallback();
} else {
res.status(response.statusCode).send(body);
}
} else {
console.error('No response');
}
} else {
console.error('Request failed:', error);
}
});
};
app.get(noExtRouting(), (req, res, next) => {
let slash = req.path.toString().endsWith('/') ? '' : '/';
let requestUrl = 'http://localhost:' + port + req.path;
requestFile(requestUrl + slash + 'index.html', () => {
requestFile(requestUrl + slash + 'index.html', res, () => {
requestFile(
slash === '/'
? requestUrl + '.html'
: requestUrl.replace(/\/$/, '.html'),
null
res,
next
);
});
});
// handle special cleanUrl case like '/blog/1.2.3' & '/blog.robots.hai'
// where we should try to serve 'blog/1.2.3.html' & '/blog.robots.hai.html'
app.get(dotRouting(), (req, res, next) => {
if (!siteConfig.cleanUrl) {
next();
return;
}
requestFile('http://localhost:' + port + req.path + '.html', res, next);
});
if (options.watch) startLiveReload();
app.listen(port);