mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
fix: PagesRouter header parameters are not URL-encoded to support non-ASCII characters in app name (#10078)
This commit is contained in:
@@ -1251,6 +1251,47 @@ describe('Pages Router', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('special characters in config', () => {
|
||||
it('should not URI-encode page param headers by default', async () => {
|
||||
await reconfigureServer({
|
||||
appId: 'test',
|
||||
appName: 'ExampleAppName',
|
||||
publicServerURL: 'http://localhost:8378/1',
|
||||
});
|
||||
|
||||
const response = await request({
|
||||
url: 'http://localhost:8378/1/apps/choose_password?appId=test',
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers['x-parse-page-param-appname']).toBe('ExampleAppName');
|
||||
expect(response.headers['x-parse-page-param-publicserverurl']).toBe(
|
||||
'http://localhost:8378/1'
|
||||
);
|
||||
});
|
||||
|
||||
it('should URI-encode page param headers when encodePageParamHeaders is true', async () => {
|
||||
await reconfigureServer({
|
||||
appId: 'test',
|
||||
appName: 'Product™',
|
||||
publicServerURL: 'http://localhost:8378/1',
|
||||
pages: {
|
||||
encodePageParamHeaders: true,
|
||||
},
|
||||
});
|
||||
|
||||
const response = await request({
|
||||
url: 'http://localhost:8378/1/apps/choose_password?appId=test',
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers['x-parse-page-param-appname']).toBe(
|
||||
encodeURIComponent('Product™')
|
||||
);
|
||||
expect(response.headers['x-parse-page-param-publicserverurl']).toBe(
|
||||
encodeURIComponent('http://localhost:8378/1')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('XSS Protection', () => {
|
||||
beforeEach(async () => {
|
||||
await reconfigureServer({
|
||||
|
||||
@@ -339,6 +339,11 @@ export class Config {
|
||||
} else if (!(pages.customRoutes instanceof Array)) {
|
||||
throw 'Parse Server option pages.customRoutes must be an array.';
|
||||
}
|
||||
if (pages.encodePageParamHeaders === undefined) {
|
||||
pages.encodePageParamHeaders = PagesOptions.encodePageParamHeaders.default;
|
||||
} else if (!isBoolean(pages.encodePageParamHeaders)) {
|
||||
throw 'Parse Server option pages.encodePageParamHeaders must be a boolean.';
|
||||
}
|
||||
}
|
||||
|
||||
static validateIdempotencyOptions(idempotencyOptions) {
|
||||
|
||||
@@ -21,4 +21,9 @@ module.exports = [
|
||||
changeNewDefault: '[]',
|
||||
solution: "Set 'fileUpload.allowedFileUrlDomains' to the domains you want to allow, or to '[]' to block all file URLs.",
|
||||
},
|
||||
{
|
||||
optionKey: 'pages.encodePageParamHeaders',
|
||||
changeNewDefault: 'true',
|
||||
solution: "Set 'pages.encodePageParamHeaders' to 'true' to URI-encode non-ASCII characters in page parameter headers.",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -688,6 +688,12 @@ module.exports.PagesOptions = {
|
||||
action: parsers.booleanParser,
|
||||
default: false,
|
||||
},
|
||||
encodePageParamHeaders: {
|
||||
env: 'PARSE_SERVER_PAGES_ENCODE_PAGE_PARAM_HEADERS',
|
||||
help: 'Is `true` if the page parameter headers should be URI-encoded. This is required if any page parameter value contains non-ASCII characters, such as the app name.',
|
||||
action: parsers.booleanParser,
|
||||
default: false,
|
||||
},
|
||||
forceRedirect: {
|
||||
env: 'PARSE_SERVER_PAGES_FORCE_REDIRECT',
|
||||
help: 'Is true if responses should always be redirects and never content, false if the response type should depend on the request type (GET request -> content response; POST request -> redirect response).',
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
* @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} encodePageParamHeaders Is `true` if the page parameter headers should be URI-encoded. This is required if any page parameter value contains non-ASCII characters, such as the app name.
|
||||
* @property {Boolean} forceRedirect Is true if responses should always be redirects and never content, false if the response type should depend on the request type (GET request -> content response; POST request -> redirect response).
|
||||
* @property {String} localizationFallbackLocale The fallback locale for localization if no matching translation is provided for the given locale. This is only relevant when providing translation resources via JSON file.
|
||||
* @property {String} localizationJsonPath The path to the JSON file for localization; the translations will be used to fill template placeholders according to the locale.
|
||||
|
||||
@@ -445,6 +445,9 @@ export interface PagesOptions {
|
||||
/* The custom routes.
|
||||
:DEFAULT: [] */
|
||||
customRoutes: ?(PagesRoute[]);
|
||||
/* Is `true` if the page parameter headers should be URI-encoded. This is required if any page parameter value contains non-ASCII characters, such as the app name.
|
||||
:DEFAULT: false */
|
||||
encodePageParamHeaders: ?boolean;
|
||||
}
|
||||
|
||||
export interface PagesRoute {
|
||||
|
||||
@@ -454,9 +454,10 @@ export class PagesRouter extends PromiseRouter {
|
||||
|
||||
// Add placeholders in header to allow parsing for programmatic use
|
||||
// of response, instead of having to parse the HTML content.
|
||||
const encode = this.pagesConfig.encodePageParamHeaders;
|
||||
const headers = Object.entries(params).reduce((m, p) => {
|
||||
if (p[1] !== undefined) {
|
||||
m[`${pageParamHeaderPrefix}${p[0].toLowerCase()}`] = p[1];
|
||||
m[`${pageParamHeaderPrefix}${p[0].toLowerCase()}`] = encode ? encodeURIComponent(p[1]) : p[1];
|
||||
}
|
||||
return m;
|
||||
}, {});
|
||||
@@ -576,9 +577,10 @@ export class PagesRouter extends PromiseRouter {
|
||||
|
||||
// Add parameters to header to allow parsing for programmatic use
|
||||
// of response, instead of having to parse the HTML content.
|
||||
const encode = this.pagesConfig.encodePageParamHeaders;
|
||||
const headers = Object.entries(params).reduce((m, p) => {
|
||||
if (p[1] !== undefined) {
|
||||
m[`${pageParamHeaderPrefix}${p[0].toLowerCase()}`] = p[1];
|
||||
m[`${pageParamHeaderPrefix}${p[0].toLowerCase()}`] = encode ? encodeURIComponent(p[1]) : p[1];
|
||||
}
|
||||
return m;
|
||||
}, {});
|
||||
|
||||
Reference in New Issue
Block a user