diff --git a/lib/context.js b/lib/context.js index 5ca7697..0289e4f 100644 --- a/lib/context.js +++ b/lib/context.js @@ -4,6 +4,8 @@ import abslog from 'abslog'; import assert from 'assert'; import * as schemas from '@podium/schemas'; import * as utils from '@podium/utils'; +import AppId from './get-app-id.js'; +import BaseFontSize from './get-base-font-size.js'; import PublicPathname from './get-public-pathname.js'; import MountPathname from './get-mount-pathname.js'; import MountOrigin from './get-mount-origin.js'; @@ -106,6 +108,8 @@ export default class PodiumContext { buckets: [0.001, 0.01, 0.1, 0.5, 1], }); + this.register('appId', new AppId()); + this.register('baseFontSize', new BaseFontSize()); this.register( 'publicPathname', new PublicPathname(options.publicPathname), diff --git a/lib/get-app-id.js b/lib/get-app-id.js new file mode 100644 index 0000000..8340936 --- /dev/null +++ b/lib/get-app-id.js @@ -0,0 +1,19 @@ +export default class PodiumContextAppIdParser { + get [Symbol.toStringTag]() { + return 'PodiumContextAppIdParser'; + } + + /** + * @param {import('@podium/utils').HttpIncoming} incoming + * @returns {string | null} + */ + parse(incoming) { + let value = incoming.request.headers + ? incoming.request.headers['x-podium-app-id'] + : null; + if (!value || value === '') { + return null; + } + return value; + } +} diff --git a/lib/get-base-font-size.js b/lib/get-base-font-size.js new file mode 100644 index 0000000..f79828c --- /dev/null +++ b/lib/get-base-font-size.js @@ -0,0 +1,19 @@ +export default class PodiumContextBaseFontSizeParser { + get [Symbol.toStringTag]() { + return 'PodiumContextBaseFontSizeParser'; + } + + /** + * @param {import('@podium/utils').HttpIncoming} incoming + * @returns {string | null} + */ + parse(incoming) { + let value = incoming.request.headers + ? incoming.request.headers['x-podium-base-font-size'] + : null; + if (!value || value === '') { + return null; + } + return value; + } +} diff --git a/lib/get-device-type.js b/lib/get-device-type.js index 4909ed0..dec8125 100644 --- a/lib/get-device-type.js +++ b/lib/get-device-type.js @@ -55,12 +55,22 @@ export default class PodiumContextDeviceTypeParser { const userAgent = incoming.request.headers ? incoming.request.headers['user-agent'] : ''; + const deviceType = incoming.request.headers + ? incoming.request.headers['x-podium-device-type'] + : ''; - if (!userAgent || userAgent === '') { + if ( + (!userAgent || userAgent === '') && + (!deviceType || deviceType === '') + ) { // @ts-expect-error because of Object.defineProperty return this.default; } + if (deviceType) { + return deviceType; + } + let type = this.cache.get(userAgent.toLowerCase()); /* istanbul ignore next */ diff --git a/tests/context.test.js b/tests/context.test.js index 13b5229..e6000d3 100644 --- a/tests/context.test.js +++ b/tests/context.test.js @@ -4,6 +4,9 @@ import Context from '../lib/context.js'; const HEADER_RICH = { host: 'localhost:3030', + 'x-podium-app-id': 'io.podium-lib.app@1.2.3', + 'x-podium-base-font-size': '1rem', + 'x-podium-device-type': 'mobile', 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', @@ -236,6 +239,8 @@ tap.test( t.equal(result.context['podium-mount-origin'], 'http://localhost:3030'); t.equal(result.context['podium-mount-pathname'], '/'); t.equal(result.context['podium-device-type'], 'mobile'); + t.equal(result.context['podium-app-id'], 'io.podium-lib.app@1.2.3'); + t.equal(result.context['podium-base-font-size'], '1rem'); t.equal(result.context['podium-locale'], 'en-US'); t.equal(result.context['podium-debug'], 'false'); t.equal(result.context['podium-requested-by'], 'foo'); diff --git a/tests/get-device-type.test.js b/tests/get-device-type.test.js index 28ac6e1..febfdb5 100644 --- a/tests/get-device-type.test.js +++ b/tests/get-device-type.test.js @@ -147,6 +147,24 @@ tap.test( }, ); +tap.test( + 'PodiumContextDeviceTypeParser.parse() - "x-podium-device-type" should override "user-agent"', + (t) => { + const parser = new DeviceType(); + const incoming = new HttpIncoming( + Object.assign(REQ, { + headers: { + 'x-podium-device-type': 'hybrid-ios', + 'user-agent': UA_DESKTOP, + }, + }), + ); + const result = parser.parse(incoming); + t.equal(result, 'hybrid-ios'); + t.end(); + }, +); + tap.test( 'PodiumContextDeviceTypeParser.parse() - parse a new UA - should not exist in cache pre parsing and should exist in cache post parsing', (t) => {