Skip to content

Commit f3a1554

Browse files
prepare 3.2.1 release (#14)
1 parent b0b34b2 commit f3a1554

File tree

5 files changed

+72
-29
lines changed

5 files changed

+72
-29
lines changed

src/Stream.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { base64URLEncode, getLDHeaders } from './utils';
1010
// it is in an active state (connected or connecting).
1111
// eventSourceAllowsReport: true if REPORT is supported.
1212

13-
export default function Stream(platform, config, environment, diagnosticsAccumulator, hash) {
13+
export default function Stream(platform, config, environment, diagnosticsAccumulator) {
1414
const baseUrl = config.streamUrl;
1515
const logger = config.logger;
1616
const stream = {};
@@ -24,10 +24,12 @@ export default function Stream(platform, config, environment, diagnosticsAccumul
2424
let reconnectTimeoutReference = null;
2525
let connectionAttemptStartTime;
2626
let user = null;
27+
let hash = null;
2728
let handlers = null;
2829

29-
stream.connect = function(newUser, newHandlers) {
30+
stream.connect = function(newUser, newHash, newHandlers) {
3031
user = newUser;
32+
hash = newHash;
3133
handlers = {};
3234
for (const key in newHandlers || {}) {
3335
handlers[key] = function(e) {

src/__tests__/LDClient-streaming-test.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { makeBootstrap } from './testUtils';
1313
// implementation, verifying that the SDK interacts properly with the stream abstraction.
1414

1515
describe('LDClient streaming', () => {
16+
const defaultStreamBaseUrl = 'https://clientstream.launchdarkly.com';
1617
const envName = 'UNKNOWN_ENVIRONMENT_ID';
1718
const lsKey = 'ld:UNKNOWN_ENVIRONMENT_ID:' + utils.btoa('{"key":"user"}');
1819
const user = { key: 'user' };
@@ -32,9 +33,20 @@ describe('LDClient streaming', () => {
3233
return await withCloseable(client, async () => await asyncCallback(client, server));
3334
}
3435

36+
function makeExpectedStreamUrl(base64User, userHash, withReasons) {
37+
const baseUrl = defaultStreamBaseUrl + '/eval/' + envName + '/' + base64User;
38+
const queryParams = [];
39+
if (userHash) {
40+
queryParams.push('h=' + userHash);
41+
}
42+
if (withReasons) {
43+
queryParams.push('?withReasons=true');
44+
}
45+
return baseUrl + (queryParams.length ? '?' + queryParams.join('&') : '');
46+
}
47+
3548
describe('streaming/event listening', () => {
36-
const streamUrl = 'https://clientstream.launchdarkly.com';
37-
const fullStreamUrlWithUser = streamUrl + '/eval/' + envName + '/' + encodedUser;
49+
const fullStreamUrlWithUser = makeExpectedStreamUrl(encodedUser);
3850

3951
async function expectStreamConnecting(url) {
4052
const stream = await platform.testing.expectStream(url);
@@ -599,10 +611,26 @@ describe('LDClient streaming', () => {
599611
await client.waitForInitialization();
600612
client.setStreaming(true);
601613

602-
await expectStreamConnecting(streamUrl + '/eval/' + envName + '/' + encodedUser);
614+
await expectStreamConnecting(makeExpectedStreamUrl(encodedUser));
603615

604616
await client.identify(user2);
605-
await expectStreamConnecting(streamUrl + '/eval/' + envName + '/' + encodedUser2);
617+
await expectStreamConnecting(makeExpectedStreamUrl(encodedUser2));
618+
});
619+
});
620+
621+
it('reconnects to stream with new hash value in secure mode if the user changes', async () => {
622+
const newUser = { key: 'user2' };
623+
const newEncodedUser = 'eyJrZXkiOiJ1c2VyMiJ9';
624+
const newHash = hash + 'xxx';
625+
626+
await withClientAndServer({ hash }, async client => {
627+
await client.waitForInitialization();
628+
client.setStreaming(true);
629+
630+
await expectStreamConnecting(makeExpectedStreamUrl(encodedUser, hash));
631+
632+
await client.identify(newUser, newHash);
633+
await expectStreamConnecting(makeExpectedStreamUrl(newEncodedUser, newHash));
606634
});
607635
});
608636
});

src/__tests__/Stream-test.js

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ describe('Stream', () => {
2727
baseHeaders = getLDHeaders(platform, defaultConfig);
2828
});
2929

30+
function makeExpectedStreamUrl(base64User, userHash, withReasons) {
31+
const url = baseUrl + '/eval/' + envName + '/' + base64User;
32+
const queryParams = [];
33+
if (userHash) {
34+
queryParams.push('h=' + userHash);
35+
}
36+
if (withReasons) {
37+
queryParams.push('?withReasons=true');
38+
}
39+
return url + (queryParams.length ? '?' + queryParams.join('&') : '');
40+
}
41+
3042
it('should not throw on EventSource when it does not exist', () => {
3143
const platform1 = { ...platform };
3244
delete platform1['eventSourceFactory'];
@@ -51,22 +63,22 @@ describe('Stream', () => {
5163

5264
it('connects to EventSource with eval stream URL by default', async () => {
5365
const stream = new Stream(platform, defaultConfig, envName);
54-
stream.connect(user, {});
66+
stream.connect(user, null, {});
5567

56-
await platform.testing.expectStream(baseUrl + '/eval/' + envName + '/' + encodedUser);
68+
await platform.testing.expectStream(makeExpectedStreamUrl(encodedUser));
5769
});
5870

5971
it('adds secure mode hash to URL if provided', async () => {
60-
const stream = new Stream(platform, defaultConfig, envName, null, hash);
61-
stream.connect(user, {});
72+
const stream = new Stream(platform, defaultConfig, envName);
73+
stream.connect(user, hash, {});
6274

63-
await platform.testing.expectStream(baseUrl + '/eval/' + envName + '/' + encodedUser + '?h=' + hash);
75+
await platform.testing.expectStream(makeExpectedStreamUrl(encodedUser, hash));
6476
});
6577

6678
it('falls back to ping stream URL if useReport is true and REPORT is not supported', async () => {
6779
const config = { ...defaultConfig, useReport: true };
6880
const stream = new Stream(platform, config, envName);
69-
stream.connect(user, {});
81+
stream.connect(user, null, {});
7082

7183
await platform.testing.expectStream(baseUrl + '/ping/' + envName);
7284
});
@@ -75,7 +87,7 @@ describe('Stream', () => {
7587
const platform1 = { ...platform, eventSourceAllowsReport: true };
7688
const config = { ...defaultConfig, useReport: true };
7789
const stream = new Stream(platform1, config, envName);
78-
stream.connect(user, {});
90+
stream.connect(user, null, {});
7991

8092
const created = await platform.testing.expectStream(baseUrl + '/eval/' + envName);
8193
expect(created.options.method).toEqual('REPORT');
@@ -84,27 +96,27 @@ describe('Stream', () => {
8496

8597
it('sends default SDK headers', async () => {
8698
const stream = new Stream(platform, defaultConfig, envName);
87-
stream.connect(user, {});
99+
stream.connect(user, null, {});
88100

89-
const created = await platform.testing.expectStream(baseUrl + '/eval/' + envName + '/' + encodedUser);
101+
const created = await platform.testing.expectStream(makeExpectedStreamUrl(encodedUser));
90102
expect(created.options.headers).toEqual(baseHeaders);
91103
});
92104

93105
it('sends SDK headers with wrapper info', async () => {
94106
const config = { ...defaultConfig, wrapperName: 'FakeSDK' };
95107
const stream = new Stream(platform, config, envName);
96-
stream.connect(user, {});
108+
stream.connect(user, null, {});
97109

98-
const created = await platform.testing.expectStream(baseUrl + '/eval/' + envName + '/' + encodedUser);
110+
const created = await platform.testing.expectStream(makeExpectedStreamUrl(encodedUser));
99111
expect(created.options.headers).toEqual({ ...baseHeaders, 'X-LaunchDarkly-Wrapper': 'FakeSDK' });
100112
});
101113

102114
it('does not send SDK headers when sendLDHeaders is false', async () => {
103115
const config = { ...defaultConfig, sendLDHeaders: false };
104116
const stream = new Stream(platform, config, envName);
105-
stream.connect(user, {});
117+
stream.connect(user, null, {});
106118

107-
const created = await platform.testing.expectStream(baseUrl + '/eval/' + envName + '/' + encodedUser);
119+
const created = await platform.testing.expectStream(makeExpectedStreamUrl(encodedUser));
108120
expect(created.options.headers).toEqual({});
109121
});
110122

@@ -113,7 +125,7 @@ describe('Stream', () => {
113125
const fn1 = jest.fn();
114126
const fn2 = jest.fn();
115127

116-
stream.connect(user, {
128+
stream.connect(user, null, {
117129
birthday: fn1,
118130
anniversary: fn2,
119131
});
@@ -184,7 +196,7 @@ describe('Stream', () => {
184196
const config = { ...defaultConfig, streamReconnectDelay: 1 };
185197
const stream = new Stream(platform, config, envName);
186198
const fakePut = jest.fn();
187-
stream.connect(user, {
199+
stream.connect(user, null, {
188200
put: fakePut,
189201
});
190202

@@ -227,7 +239,7 @@ describe('Stream', () => {
227239

228240
expect(acc.getProps().streamInits.length).toEqual(0);
229241

230-
stream.connect(user, {
242+
stream.connect(user, null, {
231243
put: jest.fn(),
232244
});
233245

@@ -255,7 +267,7 @@ describe('Stream', () => {
255267

256268
expect(acc.getProps().streamInits.length).toEqual(0);
257269

258-
stream.connect(user, {
270+
stream.connect(user, null, {
259271
put: jest.fn(),
260272
});
261273

src/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ export function initialize(env, user, specifiedOptions, platform, extraOptionDef
3232
const logger = createLogger();
3333
const emitter = EventEmitter(logger);
3434
const options = configuration.validate(specifiedOptions, emitter, extraOptionDefs, logger);
35-
const hash = options.hash;
3635
const sendEvents = options.sendEvents;
3736
let environment = env;
37+
let hash = options.hash;
3838

3939
const eventSender = EventSender(platform, environment, options);
4040

@@ -48,7 +48,7 @@ export function initialize(env, user, specifiedOptions, platform, extraOptionDef
4848
diagnosticsManager.start();
4949
}
5050

51-
const stream = Stream(platform, options, environment, diagnosticsAccumulator, hash);
51+
const stream = Stream(platform, options, environment, diagnosticsAccumulator);
5252

5353
const events =
5454
options.eventProcessor ||
@@ -198,7 +198,7 @@ export function initialize(env, user, specifiedOptions, platform, extraOptionDef
198198
enqueueEvent(event);
199199
}
200200

201-
function identify(user, hash, onDone) {
201+
function identify(user, newHash, onDone) {
202202
if (closed) {
203203
return utils.wrapPromiseCallback(Promise.resolve({}), onDone);
204204
}
@@ -213,11 +213,12 @@ export function initialize(env, user, specifiedOptions, platform, extraOptionDef
213213
.then(() => userValidator.validateUser(user))
214214
.then(realUser =>
215215
requestor
216-
.fetchFlagSettings(realUser, hash)
216+
.fetchFlagSettings(realUser, newHash)
217217
// the following then() is nested within this one so we can use realUser from the previous closure
218218
.then(requestedFlags => {
219219
const flagValueMap = utils.transformVersionedValuesToValues(requestedFlags);
220220
ident.setUser(realUser);
221+
hash = newHash;
221222
if (requestedFlags) {
222223
return replaceAllFlags(requestedFlags).then(() => flagValueMap);
223224
} else {
@@ -334,7 +335,7 @@ export function initialize(env, user, specifiedOptions, platform, extraOptionDef
334335
if (!ident.getUser()) {
335336
return;
336337
}
337-
stream.connect(ident.getUser(), {
338+
stream.connect(ident.getUser(), hash, {
338339
ping: function() {
339340
logger.debug(messages.debugStreamPing());
340341
requestor

typings.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ declare module 'launchdarkly-js-sdk-common' {
468468
* @param user
469469
* The user properties. Must contain at least the `key` property.
470470
* @param hash
471-
* The signed user key for [Secure Mode](http://docs.launchdarkly.com/docs/js-sdk-reference#secure-mode).
471+
* The signed user key if you are using [Secure Mode](http://docs.launchdarkly.com/docs/js-sdk-reference#secure-mode).
472472
* @param onDone
473473
* A function which will be called as soon as the flag values for the new user are available,
474474
* with two parameters: an error value (if any), and an [[LDFlagSet]] containing the new values

0 commit comments

Comments
 (0)