Ghost/core/server/web/shared/middleware/uncapitalise.js
Naz 9c64d7af81 Centralized base API path value across server codebase
refs https://github.com/TryGhost/Team/issues/1420

- This changeset makes the "/ghost/api" base path for the APIs centralized in one place and reused by dependent modules. There are couple benefits this refactor brings: easy way to spot where the API base path is used (was hard to find it in regexp) and makes it easy to change the hardcoded path to a configurable one in the future (e.g. host all APIs under `domain.tld/custom-path/awesome-apis/posts`)
- I hear that scream from the back of your head: "But hey! This introduced coupling to url-utils!". To that my unswer is: "No. This change only makes the coupling explicit, it's been there already and now can be addressed if we need to!".
- A neat thing about his change, making the API work on a custom path is one line away, by moving the hardcoded `/ghost/api` to a config ;)
2022-03-09 17:15:51 +08:00

64 lines
1.9 KiB
JavaScript

// # uncapitalise Middleware
// Usage: uncapitalise(req, res, next)
// After:
// Before:
// App: Admin|Site|API
//
// Detect upper case in req.path.
//
// Example req:
// req.originalUrl = /blog/ghost/signin/?asdAD=asdAS
// req.url = /ghost/signin/?asdAD=asdAS
// req.baseUrl = /blog
// req.path = /ghost/signin/
const errors = require('@tryghost/errors');
const urlUtils = require('../../../../shared/url-utils');
const tpl = require('@tryghost/tpl');
const localUtils = require('../utils');
const messages = {
pageNotFound: 'Page not found"'
};
const uncapitalise = (req, res, next) => {
let pathToTest = (req.baseUrl ? req.baseUrl : '') + req.path;
let redirectPath;
let decodedURI;
const isSignupOrReset = pathToTest.match(/^(.*\/ghost\/(signup|reset)\/)/i);
const isAPIRegExp = new RegExp(`^(.*${urlUtils.BASE_API_PATH}(/(v[\\d.]+|canary))?/.*?/)`, 'i');
const isAPI = pathToTest.match(isAPIRegExp);
if (isSignupOrReset) {
pathToTest = isSignupOrReset[1];
}
// Do not lowercase anything after e.g. /ghost/api(/v{X})?/ to protect :key/:slug
if (isAPI) {
pathToTest = isAPI[1];
}
try {
decodedURI = decodeURIComponent(pathToTest);
} catch (err) {
return next(new errors.NotFoundError({
message: tpl(messages.pageNotFound),
err: err
}));
}
/**
* In node < 0.11.1 req.path is not encoded, afterwards, it is always encoded such that | becomes %7C etc.
* That encoding isn't useful here, as it triggers an extra uncapitalise redirect, so we decode the path first
*/
if (/[A-Z]/.test(decodedURI)) {
redirectPath = (localUtils.removeOpenRedirectFromUrl((req.originalUrl || req.url).replace(pathToTest, pathToTest.toLowerCase())));
return urlUtils.redirect301(res, redirectPath);
}
next();
};
module.exports = uncapitalise;