Skip to content

Commit 2741a7b

Browse files
prepare 3.1.0 release (#5)
1 parent 1cbdb4b commit 2741a7b

16 files changed

+218
-68
lines changed

package-lock.json

Lines changed: 7 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/EventProcessor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as utils from './utils';
77

88
export default function EventProcessor(platform, options, environmentId, emitter = null, sender = null) {
99
const processor = {};
10-
const eventSender = sender || EventSender(platform, options.eventsUrl, environmentId);
10+
const eventSender = sender || EventSender(platform, options.eventsUrl, environmentId, options);
1111
const summarizer = EventSummarizer();
1212
const userFilter = UserFilter(options);
1313
const inlineUsers = options.inlineUsersInEvents;

src/EventSender.js

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@ import * as utils from './utils';
33

44
const MAX_URL_LENGTH = 2000;
55

6-
export default function EventSender(platform, eventsUrl, environmentId, imageCreator) {
6+
export default function EventSender(platform, eventsUrl, environmentId, options) {
77
const postUrl = eventsUrl + '/events/bulk/' + environmentId;
88
const imageUrl = eventsUrl + '/a/' + environmentId + '.gif';
9+
const httpFallbackPing = platform.httpFallbackPing; // this will be set for us if we're in the browser SDK
910
const sender = {};
1011

11-
function loadUrlUsingImage(src) {
12-
const img = new window.Image();
13-
img.src = src;
14-
}
15-
1612
function getResponseInfo(result) {
1713
const ret = { status: result.status };
1814
const dateStr = result.header('date');
@@ -26,7 +22,6 @@ export default function EventSender(platform, eventsUrl, environmentId, imageCre
2622
}
2723

2824
function sendChunk(events, usePost) {
29-
const createImage = imageCreator || loadUrlUsingImage;
3025
const jsonBody = JSON.stringify(events);
3126

3227
function doPostRequest(canRetry) {
@@ -35,7 +30,7 @@ export default function EventSender(platform, eventsUrl, environmentId, imageCre
3530
'Content-Type': 'application/json',
3631
'X-LaunchDarkly-Event-Schema': '3',
3732
},
38-
utils.getLDHeaders(platform)
33+
utils.getLDHeaders(platform, options)
3934
);
4035
return platform
4136
.httpRequest('POST', postUrl, headers, jsonBody)
@@ -61,11 +56,8 @@ export default function EventSender(platform, eventsUrl, environmentId, imageCre
6156
if (usePost) {
6257
return doPostRequest(true).catch(() => {});
6358
} else {
64-
const src = imageUrl + '?d=' + utils.base64URLEncode(jsonBody);
65-
createImage(src);
66-
return Promise.resolve();
67-
// We do not specify an onload handler for the image because we don't want the client to wait around
68-
// for the image to load - it won't provide a server response, there's nothing to be done.
59+
httpFallbackPing && httpFallbackPing(imageUrl + '?d=' + utils.base64URLEncode(jsonBody));
60+
return Promise.resolve(); // we don't wait for this request to complete, it's just a one-way ping
6961
}
7062
}
7163

src/Requestor.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export default function Requestor(platform, options, environment) {
1717
const baseUrl = options.baseUrl;
1818
const useReport = options.useReport;
1919
const withReasons = options.evaluationReasons;
20-
const sendLDHeaders = options.sendLDHeaders;
2120
const logger = options.logger;
2221

2322
const requestor = {};
@@ -32,7 +31,7 @@ export default function Requestor(platform, options, environment) {
3231
}
3332

3433
const method = body ? 'REPORT' : 'GET';
35-
const headers = sendLDHeaders ? utils.getLDHeaders(platform) : {};
34+
const headers = utils.getLDHeaders(platform, options);
3635
if (body) {
3736
headers['Content-Type'] = 'application/json';
3837
}

src/Stream.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as messages from './messages';
2-
import { base64URLEncode } from './utils';
2+
import { base64URLEncode, getLDHeaders } from './utils';
33

44
// The underlying event source implementation is abstracted via the platform object, which should
55
// have these three properties:
@@ -18,6 +18,7 @@ export default function Stream(platform, config, environment, hash) {
1818
const useReport = config.useReport;
1919
const withReasons = config.evaluationReasons;
2020
const streamReconnectDelay = config.streamReconnectDelay;
21+
const headers = getLDHeaders(platform, config);
2122
let firstConnectionErrorLogged = false;
2223
let es = null;
2324
let reconnectTimeoutReference = null;
@@ -73,7 +74,7 @@ export default function Stream(platform, config, environment, hash) {
7374
reconnectTimeoutReference = null;
7475
let url;
7576
let query = '';
76-
const options = {};
77+
const options = { headers };
7778
if (platform.eventSourceFactory) {
7879
if (hash !== null && hash !== undefined) {
7980
query = 'h=' + hash;
@@ -82,7 +83,7 @@ export default function Stream(platform, config, environment, hash) {
8283
if (platform.eventSourceAllowsReport) {
8384
url = evalUrlPrefix;
8485
options.method = 'REPORT';
85-
options.headers = { 'Content-Type': 'application/json' };
86+
options.headers['Content-Type'] = 'application/json';
8687
options.body = JSON.stringify(user);
8788
} else {
8889
// if we can't do REPORT, fall back to the old ping-based stream

src/__tests__/EventSender-test.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ import * as stubPlatform from './stubPlatform';
1414

1515
describe('EventSender', () => {
1616
let platform;
17-
let platformWithoutCors;
1817
const envId = 'env';
1918

2019
beforeEach(() => {
2120
platform = stubPlatform.defaults();
22-
platformWithoutCors = { ...platform, httpAllowsPost: () => false };
2321
});
2422

2523
function fakeImageCreator() {
@@ -53,7 +51,8 @@ describe('EventSender', () => {
5351
it('should encode events in a single chunk if they fit', async () => {
5452
const server = platform.testing.http.newServer();
5553
const imageCreator = fakeImageCreator();
56-
const sender = EventSender(platformWithoutCors, server.url, envId, imageCreator);
54+
const platformWithoutCors = { ...platform, httpAllowsPost: () => false, httpFallbackPing: imageCreator };
55+
const sender = EventSender(platformWithoutCors, server.url, envId);
5756
const event1 = { kind: 'identify', key: 'userKey1' };
5857
const event2 = { kind: 'identify', key: 'userKey2' };
5958
const events = [event1, event2];
@@ -70,7 +69,8 @@ describe('EventSender', () => {
7069
it('should send events in multiple chunks if necessary', async () => {
7170
const server = platform.testing.http.newServer();
7271
const imageCreator = fakeImageCreator();
73-
const sender = EventSender(platformWithoutCors, server.url, envId, imageCreator);
72+
const platformWithoutCors = { ...platform, httpAllowsPost: () => false, httpFallbackPing: imageCreator };
73+
const sender = EventSender(platformWithoutCors, server.url, envId);
7474
const events = [];
7575
for (let i = 0; i < 80; i++) {
7676
events.push({ kind: 'identify', key: 'thisIsALongUserKey' + i });
@@ -106,14 +106,29 @@ describe('EventSender', () => {
106106
});
107107

108108
it('should send custom user-agent header', async () => {
109+
const options = { sendLDHeaders: true };
109110
const server = platform.testing.http.newServer();
110111
server.byDefault(respond(202));
111-
const sender = EventSender(platform, server.url, envId);
112+
const sender = EventSender(platform, server.url, envId, options);
112113
const event = { kind: 'identify', key: 'userKey' };
113114
await sender.sendEvents([event], false);
114115

115116
const r = await server.nextRequest();
116117
expect(r.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
118+
expect(r.headers['x-launchdarkly-wrapper']).toBeUndefined();
119+
});
120+
121+
it('should send wrapper info if present', async () => {
122+
const options = { sendLDHeaders: true, wrapperName: 'FakeSDK' };
123+
const server = platform.testing.http.newServer();
124+
server.byDefault(respond(202));
125+
const sender = EventSender(platform, server.url, envId, options);
126+
const event = { kind: 'identify', key: 'userKey' };
127+
await sender.sendEvents([event], server.url);
128+
129+
const r = await server.nextRequest();
130+
expect(r.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
131+
expect(r.headers['x-launchdarkly-wrapper']).toEqual('FakeSDK');
117132
});
118133

119134
const retryableStatuses = [400, 408, 429, 500, 503];

src/__tests__/LDClient-test.js

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as messages from '../messages';
44
import * as utils from '../utils';
55

66
import semverCompare from 'semver-compare';
7-
import { eventSink, promisifySingle, sleepAsync, withCloseable } from 'launchdarkly-js-test-helpers';
7+
import { eventSink, promisifySingle, sleepAsync, withCloseable, AsyncQueue } from 'launchdarkly-js-test-helpers';
88

99
import { respond, respondJson } from './mockHttp';
1010
import * as stubPlatform from './stubPlatform';
@@ -453,20 +453,30 @@ describe('LDClient', () => {
453453

454454
describe('identify', () => {
455455
it('does not set user until the flag config has been updated', async () => {
456-
function sleep(ms) {
457-
return new Promise(resolve => setTimeout(resolve, ms));
458-
}
459-
460-
const user2 = { key: 'user2' };
461-
const client = platform.testing.makeClient(envName, user);
462-
await client.waitForInitialization();
463-
server.autoRespond = false;
464-
const identifyPromise = client.identify(user2);
465-
await sleep(200); // sleep to jump some async ticks.
466-
expect(client.getUser()).toEqual(user);
467-
server.respond();
468-
await identifyPromise;
469-
expect(client.getUser()).toEqual(user2);
456+
await withServers(async (baseConfig, pollServer) => {
457+
pollServer.byDefault(respondJson({}));
458+
await withClient(user, baseConfig, async client => {
459+
const signal = new AsyncQueue();
460+
const user2 = { key: 'user2' };
461+
await client.waitForInitialization();
462+
463+
// Make the server wait until signaled to return the next response
464+
pollServer.byDefault((req, res) => {
465+
signal.take().then(() => {
466+
respondJson({})(req, res);
467+
});
468+
});
469+
470+
const identifyPromise = client.identify(user2);
471+
await sleepAsync(100); // sleep to jump some async ticks
472+
expect(client.getUser()).toEqual(user);
473+
474+
signal.add();
475+
await identifyPromise;
476+
477+
expect(client.getUser()).toEqual(user2);
478+
});
479+
});
470480
});
471481

472482
it('updates flag values when the user changes', async () => {

src/__tests__/Requestor-test.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,37 +159,71 @@ describe('Requestor', () => {
159159

160160
it('sends custom user-agent header in GET mode when sendLDHeaders is true', async () => {
161161
await withServer(async (baseConfig, server) => {
162-
const requestor = Requestor(platform, { ...baseConfig, sendLDHeaders: true }, env);
162+
const config = { ...baseConfig, sendLDHeaders: true };
163+
const requestor = Requestor(platform, config, env);
163164

164165
await requestor.fetchFlagSettings(user);
165166

166167
expect(server.requests.length()).toEqual(1);
167168
const req = await server.requests.take();
168169
expect(req.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
170+
expect(req.headers['x-launchdarkly-wrapper']).toBeUndefined();
171+
});
172+
});
173+
174+
it('sends wrapper info if specified in GET mode when sendLDHeaders is true', async () => {
175+
await withServer(async (baseConfig, server) => {
176+
const config = { ...baseConfig, sendLDHeaders: true, wrapperName: 'FakeSDK' };
177+
const requestor = Requestor(platform, config, env);
178+
179+
await requestor.fetchFlagSettings(user);
180+
181+
expect(server.requests.length()).toEqual(1);
182+
const req = await server.requests.take();
183+
expect(req.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
184+
expect(req.headers['x-launchdarkly-wrapper']).toEqual('FakeSDK');
169185
});
170186
});
171187

172188
it('sends custom user-agent header in REPORT mode when sendLDHeaders is true', async () => {
173189
await withServer(async (baseConfig, server) => {
174-
const requestor = Requestor(platform, { ...baseConfig, useReport: true, sendLDHeaders: true }, env);
190+
const config = { ...baseConfig, useReport: true, sendLDHeaders: true };
191+
const requestor = Requestor(platform, config, env);
192+
193+
await requestor.fetchFlagSettings(user, 'hash1');
194+
195+
expect(server.requests.length()).toEqual(1);
196+
const req = await server.requests.take();
197+
expect(req.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
198+
expect(req.headers['x-launchdarkly-wrapper']).toBeUndefined();
199+
});
200+
});
201+
202+
it('sends wrapper info if specified in REPORT mode when sendLDHeaders is true', async () => {
203+
await withServer(async (baseConfig, server) => {
204+
const config = { ...baseConfig, useReport: true, sendLDHeaders: true, wrapperName: 'FakeSDK' };
205+
const requestor = Requestor(platform, config, env);
175206

176207
await requestor.fetchFlagSettings(user, 'hash1');
177208

178209
expect(server.requests.length()).toEqual(1);
179210
const req = await server.requests.take();
180211
expect(req.headers['x-launchdarkly-user-agent']).toEqual(utils.getLDUserAgentString(platform));
212+
expect(req.headers['x-launchdarkly-wrapper']).toEqual('FakeSDK');
181213
});
182214
});
183215

184216
it('does NOT send custom user-agent header when sendLDHeaders is false', async () => {
185217
await withServer(async (baseConfig, server) => {
186-
const requestor = Requestor(platform, { ...baseConfig, sendLDHeaders: false }, env);
218+
const config = { ...baseConfig, sendLDHeaders: false };
219+
const requestor = Requestor(platform, config, env);
187220

188221
await requestor.fetchFlagSettings(user);
189222

190223
expect(server.requests.length()).toEqual(1);
191224
const req = await server.requests.take();
192225
expect(req.headers['x-launchdarkly-user-agent']).toBeUndefined();
226+
expect(req.headers['x-launchdarkly-wrapper']).toBeUndefined();
193227
});
194228
});
195229

0 commit comments

Comments
 (0)