mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 11:35:55 +01:00
fix: #9580, proper 404 when ajaxifying
This commit is contained in:
@@ -7,6 +7,7 @@ const validator = require('validator');
|
||||
const meta = require('../meta');
|
||||
const plugins = require('../plugins');
|
||||
const middleware = require('../middleware');
|
||||
const helpers = require('../middleware/helpers');
|
||||
|
||||
exports.handle404 = function handle404(req, res) {
|
||||
const relativePath = nconf.get('relative_path');
|
||||
@@ -22,7 +23,13 @@ exports.handle404 = function handle404(req, res) {
|
||||
|
||||
if (isClientScript.test(req.url)) {
|
||||
res.type('text/javascript').status(404).send('Not Found');
|
||||
} else if (req.path.startsWith(`${relativePath}/assets/uploads`) || (req.get('accept') && !req.get('accept').includes('text/html')) || req.path === '/favicon.ico') {
|
||||
} else if (
|
||||
!res.locals.isAPI && (
|
||||
req.path.startsWith(`${relativePath}/assets/uploads`) ||
|
||||
(req.get('accept') && !req.get('accept').includes('text/html')) ||
|
||||
req.path === '/favicon.ico'
|
||||
)
|
||||
) {
|
||||
meta.errors.log404(req.path || '');
|
||||
res.sendStatus(404);
|
||||
} else if (req.accepts('html')) {
|
||||
@@ -41,7 +48,11 @@ exports.send404 = async function (req, res) {
|
||||
res.status(404);
|
||||
const path = String(req.path || '');
|
||||
if (res.locals.isAPI) {
|
||||
return res.json({ path: validator.escape(path.replace(/^\/api/, '')), title: '[[global:404.title]]' });
|
||||
return res.json({
|
||||
path: validator.escape(path.replace(/^\/api/, '')),
|
||||
title: '[[global:404.title]]',
|
||||
bodyClass: helpers.buildBodyClass(req, res),
|
||||
});
|
||||
}
|
||||
|
||||
if (req.method === 'GET') {
|
||||
@@ -49,5 +60,9 @@ exports.send404 = async function (req, res) {
|
||||
}
|
||||
|
||||
await middleware.buildHeaderAsync(req, res);
|
||||
await res.render('404', { path: validator.escape(path), title: '[[global:404.title]]' });
|
||||
await res.render('404', {
|
||||
path: validator.escape(path),
|
||||
title: '[[global:404.title]]',
|
||||
bodyClass: helpers.buildBodyClass(req, res),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const winston = require('winston');
|
||||
const validator = require('validator');
|
||||
const slugify = require('../slugify');
|
||||
|
||||
const helpers = module.exports;
|
||||
|
||||
helpers.try = function (middleware) {
|
||||
@@ -20,3 +24,34 @@ helpers.try = function (middleware) {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
helpers.buildBodyClass = function (req, res, templateData = {}) {
|
||||
const clean = req.path.replace(/^\/api/, '').replace(/^\/|\/$/g, '');
|
||||
const parts = clean.split('/').slice(0, 3);
|
||||
parts.forEach((p, index) => {
|
||||
try {
|
||||
p = slugify(decodeURIComponent(p));
|
||||
} catch (err) {
|
||||
winston.error(err.stack);
|
||||
p = '';
|
||||
}
|
||||
p = validator.escape(String(p));
|
||||
parts[index] = index ? `${parts[0]}-${p}` : `page-${p || 'home'}`;
|
||||
});
|
||||
|
||||
if (templateData.template && templateData.template.topic) {
|
||||
parts.push(`page-topic-category-${templateData.category.cid}`);
|
||||
parts.push(`page-topic-category-${slugify(templateData.category.name)}`);
|
||||
}
|
||||
|
||||
if (Array.isArray(templateData.breadcrumbs)) {
|
||||
templateData.breadcrumbs.forEach((crumb) => {
|
||||
if (crumb && crumb.hasOwnProperty('cid')) {
|
||||
parts.push(`parent-category-${crumb.cid}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
parts.push(`page-status-${res.statusCode}`);
|
||||
return parts.join(' ');
|
||||
};
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
const nconf = require('nconf');
|
||||
const validator = require('validator');
|
||||
const winston = require('winston');
|
||||
|
||||
|
||||
const plugins = require('../plugins');
|
||||
const meta = require('../meta');
|
||||
const translator = require('../translator');
|
||||
const widgets = require('../widgets');
|
||||
const utils = require('../utils');
|
||||
const slugify = require('../slugify');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
const relative_path = nconf.get('relative_path');
|
||||
|
||||
@@ -31,7 +31,7 @@ module.exports = function (middleware) {
|
||||
options.relative_path = relative_path;
|
||||
options.template = { name: template, [template]: true };
|
||||
options.url = (req.baseUrl + req.path.replace(/^\/api/, ''));
|
||||
options.bodyClass = buildBodyClass(req, res, options);
|
||||
options.bodyClass = helpers.buildBodyClass(req, res, options);
|
||||
|
||||
const buildResult = await plugins.hooks.fire(`filter:${template}.build`, { req: req, res: res, templateData: options });
|
||||
if (res.headersSent) {
|
||||
@@ -123,34 +123,4 @@ module.exports = function (middleware) {
|
||||
const translated = await translator.translate(str, language);
|
||||
return translator.unescape(translated);
|
||||
}
|
||||
|
||||
function buildBodyClass(req, res, templateData) {
|
||||
const clean = req.path.replace(/^\/api/, '').replace(/^\/|\/$/g, '');
|
||||
const parts = clean.split('/').slice(0, 3);
|
||||
parts.forEach((p, index) => {
|
||||
try {
|
||||
p = slugify(decodeURIComponent(p));
|
||||
} catch (err) {
|
||||
winston.error(err.stack);
|
||||
p = '';
|
||||
}
|
||||
p = validator.escape(String(p));
|
||||
parts[index] = index ? `${parts[0]}-${p}` : `page-${p || 'home'}`;
|
||||
});
|
||||
|
||||
if (templateData.template.topic) {
|
||||
parts.push(`page-topic-category-${templateData.category.cid}`);
|
||||
parts.push(`page-topic-category-${slugify(templateData.category.name)}`);
|
||||
}
|
||||
if (templateData.breadcrumbs) {
|
||||
templateData.breadcrumbs.forEach((crumb) => {
|
||||
if (crumb.hasOwnProperty('cid')) {
|
||||
parts.push(`parent-category-${crumb.cid}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
parts.push(`page-status-${res.statusCode}`);
|
||||
return parts.join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user