diff --git a/spec/index.spec.js b/spec/index.spec.js index 5093a6ea25..be2b86b7de 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -615,6 +615,17 @@ describe('server', () => { expect(config.masterKeyCache.expiresAt.getTime()).toBeGreaterThan(Date.now()); }); + it('should load publicServerURL', async () => { + await reconfigureServer({ + publicServerURL: () => 'https://myserver.com/1', + }); + + await new Parse.Object('TestObject').save(); + + const config = Config.get(Parse.applicationId); + expect(config.publicServerURL).toEqual('https://myserver.com/1'); + }); + it('should not reload if ttl is not set', async () => { const masterKeySpy = jasmine.createSpy().and.returnValue(Promise.resolve('initialMasterKey')); diff --git a/src/Config.js b/src/Config.js index bf6d50626c..98344f9ecb 100644 --- a/src/Config.js +++ b/src/Config.js @@ -32,6 +32,7 @@ function removeTrailingSlash(str) { return str; } +const asyncKeys = ['publicServerURL']; export class Config { static get(applicationId: string, mount: string) { const cacheInfo = AppCache.get(applicationId); @@ -56,9 +57,33 @@ export class Config { return config; } + async loadKeys() { + const asyncKeys = ['publicServerURL']; + + await Promise.all( + asyncKeys.map(async key => { + if (typeof this[`_${key}`] === 'function') { + this[key] = await this[`_${key}`](); + } + }) + ); + + AppCache.put(this.appId, this); + } + + static transformConfiguration(serverConfiguration) { + for (const key of Object.keys(serverConfiguration)) { + if (asyncKeys.includes(key) && typeof serverConfiguration[key] === 'function') { + serverConfiguration[`_${key}`] = serverConfiguration[key]; + delete serverConfiguration[key]; + } + } + } + static put(serverConfiguration) { Config.validateOptions(serverConfiguration); Config.validateControllers(serverConfiguration); + Config.transformConfiguration(serverConfiguration); AppCache.put(serverConfiguration.appId, serverConfiguration); Config.setupPasswordValidator(serverConfiguration.passwordPolicy); return serverConfiguration; @@ -116,7 +141,11 @@ export class Config { } if (publicServerURL) { - if (!publicServerURL.startsWith('http://') && !publicServerURL.startsWith('https://')) { + if ( + typeof publicServerURL !== 'function' && + !publicServerURL.startsWith('http://') && + !publicServerURL.startsWith('https://') + ) { throw 'publicServerURL should be a valid HTTPS URL starting with https://'; } } @@ -757,7 +786,6 @@ export class Config { return this.masterKey; } - // TODO: Remove this function once PagesRouter replaces the PublicAPIRouter; // the (default) endpoint has to be defined in PagesRouter only. get pagesEndpoint() { diff --git a/src/middlewares.js b/src/middlewares.js index bf8029844a..d660063297 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -213,6 +213,7 @@ export async function handleParseHeaders(req, res, next) { }); return; } + await config.loadKeys(); info.app = AppCache.get(info.appId); req.config = config; diff --git a/types/Options/index.d.ts b/types/Options/index.d.ts index ac1c71e886..165a411545 100644 --- a/types/Options/index.d.ts +++ b/types/Options/index.d.ts @@ -85,7 +85,7 @@ export interface ParseServerOptions { cacheAdapter?: Adapter; emailAdapter?: Adapter; encodeParseObjectInCloudFunction?: boolean; - publicServerURL?: string; + publicServerURL?: string | (() => string) | Promise; pages?: PagesOptions; customPages?: CustomPagesOptions; liveQuery?: LiveQueryOptions;