Add custom routes to pages router (#7231)
* added custom routes * fixed docs typos * added page.customRoutes config validation * added 404 response if missing custom route response * added docs * minor README formatting * added CHANGELOG entry * fixed bug in definitions builder that did not recognize array of custom type * added missing route handler definition * fixed custom routes definition
This commit is contained in:
@@ -168,6 +168,11 @@ export class Config {
|
||||
} else if (Object.prototype.toString.call(pages.customUrls) !== '[object Object]') {
|
||||
throw 'Parse Server option pages.customUrls must be an object.';
|
||||
}
|
||||
if (pages.customRoutes === undefined) {
|
||||
pages.customRoutes = PagesOptions.customRoutes.default;
|
||||
} else if (!(pages.customRoutes instanceof Array)) {
|
||||
throw 'Parse Server option pages.customRoutes must be an array.';
|
||||
}
|
||||
}
|
||||
|
||||
static validateIdempotencyOptions(idempotencyOptions) {
|
||||
|
||||
@@ -425,6 +425,12 @@ module.exports.ParseServerOptions = {
|
||||
},
|
||||
};
|
||||
module.exports.PagesOptions = {
|
||||
customRoutes: {
|
||||
env: 'PARSE_SERVER_PAGES_CUSTOM_ROUTES',
|
||||
help: 'The custom routes.',
|
||||
action: parsers.arrayParser,
|
||||
default: [],
|
||||
},
|
||||
customUrls: {
|
||||
env: 'PARSE_SERVER_PAGES_CUSTOM_URLS',
|
||||
help: 'The URLs to the custom pages.',
|
||||
@@ -481,6 +487,23 @@ module.exports.PagesOptions = {
|
||||
default: {},
|
||||
},
|
||||
};
|
||||
module.exports.PagesRoute = {
|
||||
handler: {
|
||||
env: 'PARSE_SERVER_PAGES_ROUTE_HANDLER',
|
||||
help: 'The route handler that is an async function.',
|
||||
required: true,
|
||||
},
|
||||
method: {
|
||||
env: 'PARSE_SERVER_PAGES_ROUTE_METHOD',
|
||||
help: "The route method, e.g. 'GET' or 'POST'.",
|
||||
required: true,
|
||||
},
|
||||
path: {
|
||||
env: 'PARSE_SERVER_PAGES_ROUTE_PATH',
|
||||
help: 'The route path.',
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
module.exports.PagesCustomUrlsOptions = {
|
||||
emailVerificationLinkExpired: {
|
||||
env: 'PARSE_SERVER_PAGES_CUSTOM_URL_EMAIL_VERIFICATION_LINK_EXPIRED',
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
|
||||
/**
|
||||
* @interface PagesOptions
|
||||
* @property {PagesRoute[]} customRoutes The custom routes.
|
||||
* @property {PagesCustomUrlsOptions} customUrls The URLs to the custom pages.
|
||||
* @property {Boolean} enableLocalization Is true if pages should be localized; this has no effect on custom page redirects.
|
||||
* @property {Boolean} enableRouter Is true if the pages router should be enabled; this is required for any of the pages options to take effect. Caution, this is an experimental feature that may not be appropriate for production.
|
||||
@@ -93,6 +94,13 @@
|
||||
* @property {Object} placeholders The placeholder keys and values which will be filled in pages; this can be a simple object or a callback function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @interface PagesRoute
|
||||
* @property {Function} handler The route handler that is an async function.
|
||||
* @property {String} method The route method, e.g. 'GET' or 'POST'.
|
||||
* @property {String} path The route path.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @interface PagesCustomUrlsOptions
|
||||
* @property {String} emailVerificationLinkExpired The URL to the custom page for email verification -> link expired.
|
||||
|
||||
@@ -256,6 +256,18 @@ export interface PagesOptions {
|
||||
/* The URLs to the custom pages.
|
||||
:DEFAULT: {} */
|
||||
customUrls: ?PagesCustomUrlsOptions;
|
||||
/* The custom routes.
|
||||
:DEFAULT: [] */
|
||||
customRoutes: ?(PagesRoute[]);
|
||||
}
|
||||
|
||||
export interface PagesRoute {
|
||||
/* The route path. */
|
||||
path: string;
|
||||
/* The route method, e.g. 'GET' or 'POST'. */
|
||||
method: string;
|
||||
/* The route handler that is an async function. */
|
||||
handler: () => void;
|
||||
}
|
||||
|
||||
export interface PagesCustomUrlsOptions {
|
||||
|
||||
@@ -77,6 +77,8 @@ export class PagesRouter extends PromiseRouter {
|
||||
: path.resolve(__dirname, '../../public');
|
||||
this.loadJsonResource();
|
||||
this.mountPagesRoutes();
|
||||
this.mountCustomRoutes();
|
||||
this.mountStaticRoute();
|
||||
}
|
||||
|
||||
verifyEmail(req) {
|
||||
@@ -283,7 +285,7 @@ export class PagesRouter extends PromiseRouter {
|
||||
|
||||
// Add locale to params to ensure it is passed on with every request;
|
||||
// that means, once a locale is set, it is passed on to any follow-up page,
|
||||
// e.g. request_password_reset -> password_reset -> passwort_reset_success
|
||||
// e.g. request_password_reset -> password_reset -> password_reset_success
|
||||
const locale = this.getLocale(req);
|
||||
params[pageParams.locale] = locale;
|
||||
|
||||
@@ -563,7 +565,7 @@ export class PagesRouter extends PromiseRouter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a response with http rediret.
|
||||
* Creates a response with http redirect.
|
||||
* @param {Object} req The express request.
|
||||
* @param {String} path The path of the file to return.
|
||||
* @param {Object} params The query parameters to include.
|
||||
@@ -696,7 +698,33 @@ export class PagesRouter extends PromiseRouter {
|
||||
return this.requestResetPassword(req);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mountCustomRoutes() {
|
||||
for (const route of this.pagesConfig.customRoutes || []) {
|
||||
this.route(
|
||||
route.method,
|
||||
`/${this.pagesEndpoint}/:appId/${route.path}`,
|
||||
req => {
|
||||
this.setConfig(req);
|
||||
},
|
||||
async req => {
|
||||
const { file, query = {} } = (await route.handler(req)) || {};
|
||||
|
||||
// If route handler did not return a page send 404 response
|
||||
if (!file) {
|
||||
return this.notFound();
|
||||
}
|
||||
|
||||
// Send page response
|
||||
const page = new Page({ id: file, defaultFile: file });
|
||||
return this.goToPage(req, page, query, false);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
mountStaticRoute() {
|
||||
this.route(
|
||||
'GET',
|
||||
`/${this.pagesEndpoint}/(*)?`,
|
||||
|
||||
Reference in New Issue
Block a user