Improved routes.js (0.1.3)
Build docker image / docker (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Deploy Jekyll with GitHub Pages dependencies preinstalled / build (push) Has been cancelled
Deploy Jekyll with GitHub Pages dependencies preinstalled / deploy (push) Has been cancelled

Key Fixes:

Error Handling: Wrapped asynchronous calls in try-catch blocks.

Cookie Security: Added secure: true to cookies.

Improved Readability: Simplified conditional logic and grouped similar code blocks.

Dynamic Language Handling: Improved language variant handling for custom logos and Chinese variants.

Parameter Validation: Added checks for required parameters like page.
This commit is contained in:
xbdm
2024-11-22 19:01:38 -08:00
committed by GitHub
parent caa9326435
commit b45c688f02
+95 -148
View File
@@ -1,178 +1,125 @@
const config = require('../config');
const path = require('path');
module.exports = (app, utils) => {
const config = require('../config')
const path = require('path')
// Middleware to handle cookies and theme/language overrides
app.all('*', (req, res, next) => {
let themeOverride = req.query.theme
if(themeOverride) {
themeOverride = themeOverride.toLowerCase()
req.cookies.theme = themeOverride
res.cookie('theme', themeOverride, { maxAge: 31536000, httpOnly: true })
} else if(!req.cookies.theme && req.cookies.theme !== '') {
req.cookies.theme = config.theme
const { theme, default_lang: lang } = req.query;
if (theme) {
req.cookies.theme = theme.toLowerCase();
res.cookie('theme', req.cookies.theme, { maxAge: 31536000, httpOnly: true, secure: true });
} else if (!req.cookies.theme || req.cookies.theme === '') {
req.cookies.theme = config.theme;
}
let langOverride = req.query.default_lang
if(langOverride) {
langOverride = langOverride.toLowerCase()
req.cookies.default_lang = langOverride
res.cookie('default_lang', langOverride, { maxAge: 31536000, httpOnly: true })
} else if(!req.cookies.default_lang) {
req.cookies.default_lang = config.default_lang
if (lang) {
req.cookies.default_lang = lang.toLowerCase();
res.cookie('default_lang', req.cookies.default_lang, { maxAge: 31536000, httpOnly: true, secure: true });
} else if (!req.cookies.default_lang) {
req.cookies.default_lang = config.default_lang;
}
return next()
})
next();
});
// Route for handling media requests
app.get('*', async (req, res, next) => {
if(req.url.startsWith('/w/load.php')) {
return res.sendStatus(404)
}
try {
if (req.url.startsWith('/w/load.php')) return res.sendStatus(404);
if(req.url.startsWith('/media')) {
let media
let mime = ''
if(req.url.startsWith('/media/maps_wikimedia_org/')) {
media = await proxyMedia(req, 'maps.wikimedia.org')
} else if(req.url.startsWith('/media/api/rest_v1/media')) {
media = await proxyMedia(req, 'wikimedia.org/api/rest_v1/media')
if(req.url.includes('render/svg/')) {
mime = 'image/svg+xml'
if (req.url.startsWith('/media')) {
const media = await utils.proxyMedia(req);
if (media?.success) {
if (media.mime) res.setHeader('Content-Type', media.mime);
return res.sendFile(media.path);
}
} else {
media = await proxyMedia(req)
return res.sendStatus(404);
}
if(media.success === true) {
if(mime != '') {
res.setHeader('Content-Type', mime)
}
return res.sendFile(media.path)
if (req.url.startsWith('/static/images/project-logos/') || req.url === '/static/images/mobile/copyright/wikipedia.png') {
return res.sendFile(utils.wikilessLogo());
}
return res.sendStatus(404)
if (req.url.startsWith('/static/favicon/wikipedia.ico')) {
return res.sendFile(utils.wikilessFavicon());
}
if (req.url.startsWith('/static/images/mobile/copyright/')) {
const lang = req.url.match(/-(\w+)\.svg/)?.[1] || '';
const customLogo = utils.customLogos(req.url, lang);
if (customLogo) return res.sendFile(customLogo);
}
next();
} catch (error) {
console.error('Error in media handling route:', error);
res.sendStatus(500);
}
});
if(req.url.startsWith('/static/images/project-logos/') || req.url === '/static/images/mobile/copyright/wikipedia.png' || req.url === '/static/apple-touch/wikipedia.png') {
return res.sendFile(wikilessLogo())
// Wiki routes
app.get(['/wiki/:page?/:sub_page?', '/wiki//:page?/:sub_page?'], (req, res) => {
if (req.url.startsWith('/wiki//') && req.params.page) {
req.params.page = `/${req.params.page}`;
}
return utils.handleWikiPage(req, res, '/wiki/');
});
if(req.url.startsWith('/static/favicon/wikipedia.ico')) {
return res.sendFile(wikilessFavicon())
}
// custom wikipedia logos for different languages
if(req.url.startsWith('/static/images/mobile/copyright/')) {
let custom_lang = ''
if(req.url.includes('-fr.svg')) {
custom_lang = 'fr'
}
if(req.url.includes('-ko.svg')) {
custom_lang = 'ko'
}
if(req.url.includes('-vi.svg')) {
custom_lang = 'vi'
}
const custom_logo = customLogos(req.url, custom_lang)
if(custom_logo) {
return res.sendFile(custom_logo)
}
}
return next()
})
app.get('/wiki/:page?/:sub_page?', (req, res, next) => {
return handleWikiPage(req, res, '/wiki/')
})
app.get('/wiki//:page?/:sub_page?', (req, res, next) => {
const page = req.params.page
if(page) {
// issue #25
req.params.page = `/${req.params.page}`
}
return handleWikiPage(req, res, '/wiki/')
})
// Handle the search request and redirect to the correct wiki page
app.get('/w/index.php', (req, res, next) => {
const searchQuery = req.query.search
const searchQuery = req.query.search;
if (searchQuery) {
// Construct the URL to redirect to the proper wiki page
const lang = req.query.lang || req.cookies.default_lang || config.default_lang
const redirectUrl = `/wiki/${encodeURIComponent(searchQuery)}?lang=${lang}`
return res.redirect(redirectUrl)
const lang = req.query.lang || req.cookies.default_lang || config.default_lang;
const redirectUrl = `/wiki/${encodeURIComponent(searchQuery)}?lang=${lang}`;
return res.redirect(redirectUrl);
}
return next()
})
next();
});
app.get('/w/:file', (req, res, next) => {
return handleWikiPage(req, res, '/w/')
})
app.get('/wiki/Special:Map/*', (req, res, next) => {
return handleWikiPage(req, res, '/wiki/Map')
})
app.get('/api/rest_v1/page/pdf/:page', async (req, res, next) => {
if(!req.params.page) {
return res.redirect('/')
app.get('/api/rest_v1/page/pdf/:page', async (req, res) => {
if (!req.params.page) return res.redirect('/');
try {
const media = await utils.proxyMedia(req, '/api/rest_v1/page/pdf');
if (media?.success) {
const filename = `${req.params.page}.pdf`;
return res.download(media.path, filename);
}
res.sendStatus(404);
} catch (error) {
console.error('Error in PDF generation:', error);
res.sendStatus(500);
}
});
const media = await proxyMedia(req, '/api/rest_v1/page/pdf')
// Chinese variants redirect
app.get('/zh*', (req, res) => {
const [, lang, page] = req.path.split('/');
return res.redirect(`/wiki/${page}?lang=${lang}`);
});
if(media.success === true) {
let filename = `${req.params.page}.pdf`
return res.download(media.path, filename)
}
return res.sendStatus(404)
})
// Home route
app.get('/', (req, res) => utils.handleWikiPage(req, res, '/'));
// handle chinese variants
app.get('/zh*', (req, res, next) => {
const pathSplit = req.path.split('/')
const lang = pathSplit[1]
const page = pathSplit[2]
return res.redirect(`/wiki/${page}?lang=${lang}`)
})
// Static routes
app.get('/about', (req, res) => res.sendFile(path.join(__dirname, '../static/about.html')));
app.get('/', (req, res, next) => {
return handleWikiPage(req, res, '/')
})
app.get('/preferences', (req, res) => res.send(utils.preferencesPage(req, res)));
app.get('/about', (req, res, next) => {
return res.sendFile(path.join(__dirname, '../static/about.html'))
})
app.post('/preferences', (req, res) => {
const { theme, default_lang } = req.body;
const back = req.url.split('?back=')[1] || '/';
app.get('/preferences', (req, res, next) => {
return res.send(preferencesPage(req, res))
})
res.cookie('theme', theme, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true, secure: true });
res.cookie('default_lang', default_lang, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true, secure: true });
app.post('/preferences', (req, res, next) => {
const theme = req.body.theme
const default_lang = req.body.default_lang
let back = req.url.split('?back=')[1]
return res.redirect(back.startsWith('/') ? back : '/');
});
res.cookie('theme', theme, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true })
res.cookie('default_lang', default_lang, { maxAge: 365 * 24 * 60 * 60 * 1000, httpOnly: true })
if(back === 'undefined' || !back.startsWith('/')) {
back = '/'
}
return res.redirect(back)
})
app.post(/DownloadAsPdf/, (req, res, next) => {
if(!req.body.page) {
return res.redirect('/')
}
const lang = req.body.lang || req.cookies.default_lang || config.default_lang
return res.redirect(`/w/index.php?title=Special%3ADownloadAsPdf&page=${req.body.page}&action=redirect-to-electron&lang=${lang}`)
})
}
app.post('/DownloadAsPdf', (req, res) => {
const { page, lang } = req.body;
if (!page) return res.redirect('/');
const language = lang || req.cookies.default_lang || config.default_lang;
const url = `/w/index.php?title=Special%3ADownloadAsPdf&page=${encodeURIComponent(page)}&action=redirect-to-electron&lang=${language}`;
return res.redirect(url);
});
};