diff --git a/README.md b/README.md index b60803e0791e506358e8ad9894c8cdcdb912a3b8..7df5f4cd0e9fcc64a4dc22f4408962eb24fa2e74 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,16 @@ It is possible to horizontally scale the UI Middleware, as more clients are fetc | `compressFileSize` | Larger files will be gzipped | `600` | | `compressFileTypes` | Set of compression mime types |see values| +**config map** + +```yaml +# List of urls where to find ui containers +baseUrls: + - http://service.namespace.svc.cluster.local/ +# optional, when this number is changed, the changes on clients will be invalidated and will reload the ui-sources +salt: '1234' +``` + ## Ingress When using Ingress to make the service available to the public, the service is intended to be diff --git a/spec/salt_test.js b/spec/salt_test.js new file mode 100644 index 0000000000000000000000000000000000000000..a3b36325d4a8577e87da43e7272860d85dff92c9 --- /dev/null +++ b/spec/salt_test.js @@ -0,0 +1,46 @@ +import request from 'supertest' +import { brotliParser, generateSimpleViteManifest, mockApp, mockConfig, mockFetch, mockRedis } from './util.js' +import { expect } from 'chai' +import * as td from 'testdouble' +import RedisMock from 'ioredis-mock' + +describe('Salt', function () { + let app + let config + + beforeEach(async function () { + mockConfig(config = { baseUrls: ['http://ui-server/'] }) + mockRedis() + mockFetch({ + 'http://ui-server': { + '/manifest.json': generateSimpleViteManifest({ 'example.js': 'test' }), + '/example.js': '' + } + }) + app = await mockApp() + }) + + afterEach(async function () { + td.reset() + await new RedisMock().flushdb() + }) + + it('change version when salt changes', async function () { + const response = await request(app.server).get('/manifests').parse(brotliParser) + expect(response.statusCode).to.equal(200) + expect(response.headers.version).to.equal('1916675216') + + // update salt + config.salt = '1' + + await import('../src/version.js').then(async ({ updateVersionProcessor }) => { + // need to process two times to actually trigger the update + await updateVersionProcessor() + await updateVersionProcessor() + }) + + const responseAfterUpdate = await request(app.server).get('/manifests').parse(brotliParser) + expect(responseAfterUpdate.statusCode).to.equal(200) + expect(responseAfterUpdate.headers.version).to.equal('1916675216-1') + }) +}) diff --git a/src/configMap.js b/src/configMap.js index 095ff3a69aa18aba1bc8596b13f7ea59efcf0840..d3ba89c2825cdf2f685447c38b08126f7c3bba43 100644 --- a/src/configMap.js +++ b/src/configMap.js @@ -7,12 +7,18 @@ class Config { const doc = yaml.load(await fs.readFile('./config/config.yaml', 'utf8')) // @ts-ignore this._urls = doc.baseUrls + // @ts-ignore + this._salt = doc.salt logger.debug('[Config] Config has been loaded') } get urls () { return this._urls || [] } + + get salt () { + return this._salt + } } export const configMap = new Config() diff --git a/src/version.js b/src/version.js index c0828ebad6e47837d34d27d15ccf744a22d9881c..de716432b15babf2499878a287f608fbb7de8511 100644 --- a/src/version.js +++ b/src/version.js @@ -45,7 +45,7 @@ export const fetchLatestVersion = async () => { logger.error(`[Version] Cannot fetch manifest from ${baseUrl}. Version info will not be correct.`) } })) - return hash(infos) + return `${hash(infos)}${configMap.salt ? `-${configMap.salt}` : ''}` } export async function getLatestVersion () {