@contrail/flexplm 1.7.7-alpha.7ad4e7e → 1.7.7-alpha.89ddfa2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -6,10 +6,6 @@ export interface FCConfig {
|
|
|
6
6
|
eventObjectClassParam?: string;
|
|
7
7
|
eventFlexTypePathParam?: string;
|
|
8
8
|
flexplmConnect?: any;
|
|
9
|
-
'flexplmConnect.sessionReuse.enabled'?: boolean | string;
|
|
10
|
-
'flexplmConnect.sessionReuse.ttlSeconds'?: number | string;
|
|
11
|
-
'flexplmConnect.sessionReuse.cookieName'?: string;
|
|
12
|
-
'flexplmConnect.sessionReuse.retryStatuses'?: number | number[] | string;
|
|
13
9
|
taskId?: string;
|
|
14
10
|
apiHost: string;
|
|
15
11
|
userName(): string;
|
|
@@ -6,14 +6,6 @@ export declare class FlexPLMConnect {
|
|
|
6
6
|
payloadSendAsArray: boolean;
|
|
7
7
|
constructor(_config: FCConfig, endPoint?: any, payloadAsArray?: any);
|
|
8
8
|
private get sessionOptions();
|
|
9
|
-
/**
|
|
10
|
-
* Waits until no cold session acquisition is running for this key.
|
|
11
|
-
* Callers must `await` this only when it returns a promise: awaiting even a resolved promise yields,
|
|
12
|
-
* and the check-then-register in runColdAcquisition has to stay synchronous to be race free.
|
|
13
|
-
*/
|
|
14
|
-
private waitForInFlightAcquisition;
|
|
15
|
-
/** Runs a cold acquisition and registers it so concurrent callers wait for it instead of opening their own session. */
|
|
16
|
-
private runColdAcquisition;
|
|
17
9
|
private getSessionKey;
|
|
18
10
|
private getCachedSession;
|
|
19
11
|
private storeSession;
|
|
@@ -22,8 +14,11 @@ export declare class FlexPLMConnect {
|
|
|
22
14
|
private extractSessionCookie;
|
|
23
15
|
private cookieHeader;
|
|
24
16
|
private getRequestOptions;
|
|
25
|
-
getCSRF(getNewSession?: boolean
|
|
26
|
-
|
|
17
|
+
getCSRF(getNewSession?: boolean): Promise<{
|
|
18
|
+
nonce_key: any;
|
|
19
|
+
nonce: any;
|
|
20
|
+
sessionCookie: string;
|
|
21
|
+
}>;
|
|
27
22
|
sendRequest(csrf: any, payload: any): Promise<Response>;
|
|
28
23
|
protected processRequest(payload: any): Promise<FlexPLMResponseData>;
|
|
29
24
|
sendToFlexPLM(payload: PayloadType): Promise<FlexPLMResponseData>;
|
|
@@ -2,41 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FlexPLMConnect = void 0;
|
|
4
4
|
const app_framework_1 = require("@contrail/app-framework");
|
|
5
|
-
// Module-level on purpose: a new FlexPLMConnect is constructed for every event. Declaring for Session
|
|
5
|
+
// Module-level on purpose: a new FlexPLMConnect is constructed for every event. Declaring for Session resuing use case.
|
|
6
6
|
const sessionCache = new Map();
|
|
7
|
-
// In-flight cold session acquisitions per key, so concurrent events share one FlexPLM session instead of each creating their own.
|
|
8
|
-
const inFlightAcquisitions = new Map();
|
|
9
|
-
const DEFAULT_SESSION_COOKIE_NAME = 'JSESSIONID';
|
|
10
|
-
const DEFAULT_SESSION_TTL_SECONDS = 900;
|
|
11
|
-
const DEFAULT_RETRY_STATUSES = [401, 403];
|
|
12
|
-
const COOKIE_NAME_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
13
|
-
// Thrown internally when a cached cookie was rejected, so the caller can re-acquire under the lock.
|
|
14
|
-
class SessionRejectedError extends Error {
|
|
15
|
-
}
|
|
16
|
-
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
-
const parseRetryStatuses = (value) => {
|
|
18
|
-
let list = [];
|
|
19
|
-
if (Array.isArray(value))
|
|
20
|
-
list = value;
|
|
21
|
-
else if (typeof value === 'string')
|
|
22
|
-
list = value.split(',');
|
|
23
|
-
else if (value !== undefined && value !== null)
|
|
24
|
-
list = [value];
|
|
25
|
-
const statuses = list
|
|
26
|
-
.map(v => (typeof v === 'string' ? v.trim() : v))
|
|
27
|
-
.filter(v => v !== '' && v !== null && v !== undefined)
|
|
28
|
-
.map(Number)
|
|
29
|
-
.filter(n => Number.isInteger(n) && n >= 100 && n <= 599);
|
|
30
|
-
return statuses.length ? statuses : DEFAULT_RETRY_STATUSES;
|
|
31
|
-
};
|
|
32
|
-
const parseTtlSeconds = (value) => {
|
|
33
|
-
const ttl = Number(value);
|
|
34
|
-
return Number.isFinite(ttl) && ttl > 0 ? ttl : DEFAULT_SESSION_TTL_SECONDS;
|
|
35
|
-
};
|
|
36
|
-
const parseCookieName = (value) => {
|
|
37
|
-
const name = typeof value === 'string' ? value.trim() : '';
|
|
38
|
-
return COOKIE_NAME_TOKEN.test(name) ? name : DEFAULT_SESSION_COOKIE_NAME;
|
|
39
|
-
};
|
|
40
7
|
// Added for Session reuse - ET-390 - Ends
|
|
41
8
|
class FlexPLMConnect {
|
|
42
9
|
constructor(_config, endPoint = undefined, payloadAsArray = undefined) {
|
|
@@ -76,41 +43,11 @@ class FlexPLMConnect {
|
|
|
76
43
|
const enabled = sessReuseEntries('enabled');
|
|
77
44
|
return {
|
|
78
45
|
enabled: enabled === true || String(enabled).toLowerCase() === 'true',
|
|
79
|
-
ttlMs:
|
|
80
|
-
cookieName:
|
|
81
|
-
retryStatuses:
|
|
46
|
+
ttlMs: (sessReuseEntries('ttlSeconds') ?? 900) * 1000,
|
|
47
|
+
cookieName: sessReuseEntries('cookieName') ?? 'JSESSIONID',
|
|
48
|
+
retryStatuses: (sessReuseEntries('retryStatuses') ?? [401, 403]),
|
|
82
49
|
};
|
|
83
50
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Waits until no cold session acquisition is running for this key.
|
|
86
|
-
* Callers must `await` this only when it returns a promise: awaiting even a resolved promise yields,
|
|
87
|
-
* and the check-then-register in runColdAcquisition has to stay synchronous to be race free.
|
|
88
|
-
*/
|
|
89
|
-
waitForInFlightAcquisition() {
|
|
90
|
-
const key = this.getSessionKey();
|
|
91
|
-
if (!inFlightAcquisitions.has(key))
|
|
92
|
-
return undefined;
|
|
93
|
-
return (async () => {
|
|
94
|
-
let pending = inFlightAcquisitions.get(key);
|
|
95
|
-
while (pending) {
|
|
96
|
-
await pending.catch(() => undefined);
|
|
97
|
-
pending = inFlightAcquisitions.get(key);
|
|
98
|
-
}
|
|
99
|
-
})();
|
|
100
|
-
}
|
|
101
|
-
/** Runs a cold acquisition and registers it so concurrent callers wait for it instead of opening their own session. */
|
|
102
|
-
async runColdAcquisition(acquire) {
|
|
103
|
-
const key = this.getSessionKey();
|
|
104
|
-
const acquisition = acquire();
|
|
105
|
-
inFlightAcquisitions.set(key, acquisition);
|
|
106
|
-
try {
|
|
107
|
-
return await acquisition;
|
|
108
|
-
}
|
|
109
|
-
finally {
|
|
110
|
-
if (inFlightAcquisitions.get(key) === acquisition)
|
|
111
|
-
inFlightAcquisitions.delete(key);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
51
|
getSessionKey() {
|
|
115
52
|
return [this.config.apiHost, this.config.urlContext, this.config.userName(), this.config.plmEnviornment].join('|');
|
|
116
53
|
}
|
|
@@ -147,7 +84,7 @@ class FlexPLMConnect {
|
|
|
147
84
|
raw = [respHeader.get('set-cookie')];
|
|
148
85
|
}
|
|
149
86
|
const name = this.sessionOptions.cookieName;
|
|
150
|
-
const regexFilter = new RegExp('(?:^|[,\\s])' +
|
|
87
|
+
const regexFilter = new RegExp('(?:^|[,\\s])' + name + '=([^;,\\s]+)', 'g');
|
|
151
88
|
let jSession;
|
|
152
89
|
for (const line of raw) {
|
|
153
90
|
let cookieNameMatcher = regexFilter.exec(line);
|
|
@@ -202,47 +139,26 @@ class FlexPLMConnect {
|
|
|
202
139
|
/////////////////////////////////////////////////////////////////////////////
|
|
203
140
|
// ET-390 - adding a new parameter getNewSession to the getCSRF function
|
|
204
141
|
// Whenever a getCSRF is called without getNewSession, the default value of false will be used
|
|
205
|
-
|
|
206
|
-
async getCSRF(getNewSession = false, rejectedCookie) {
|
|
207
|
-
// Added for Session reuse - ET-390 - Starts
|
|
208
|
-
if (!this.sessionOptions.enabled)
|
|
209
|
-
return this.fetchCSRF(undefined);
|
|
210
|
-
for (let wait = this.waitForInFlightAcquisition(); wait; wait = this.waitForInFlightAcquisition())
|
|
211
|
-
await wait;
|
|
212
|
-
if (getNewSession) {
|
|
213
|
-
const current = this.getCachedSession();
|
|
214
|
-
if (!current || current === rejectedCookie)
|
|
215
|
-
this.clearSession();
|
|
216
|
-
}
|
|
217
|
-
const cached = this.getCachedSession();
|
|
218
|
-
if (cached) {
|
|
219
|
-
try {
|
|
220
|
-
return await this.fetchCSRF(cached);
|
|
221
|
-
}
|
|
222
|
-
catch (e) {
|
|
223
|
-
if (!(e instanceof SessionRejectedError))
|
|
224
|
-
throw e;
|
|
225
|
-
// if the cached cookie is rejected (401/403), drop it and acquire a new session (serialized)
|
|
226
|
-
if (this.getCachedSession() === cached)
|
|
227
|
-
this.clearSession();
|
|
228
|
-
return this.getCSRF();
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return this.runColdAcquisition(() => this.fetchCSRF(undefined));
|
|
232
|
-
// Added for Session reuse - ET-390 - Ends
|
|
233
|
-
}
|
|
234
|
-
async fetchCSRF(sentCookie) {
|
|
142
|
+
async getCSRF(getNewSession = false) {
|
|
235
143
|
const urlContext = this.config.urlContext;
|
|
236
144
|
const csrfEndpoint = this.config.csrfEndpoint;
|
|
237
145
|
const csrfURL = this.config.apiHost + urlContext + csrfEndpoint;
|
|
238
146
|
console.info('csrfURL: ' + csrfURL);
|
|
147
|
+
// Added for Session reuse - ET-390 - Starts
|
|
148
|
+
if (getNewSession)
|
|
149
|
+
this.clearSession();
|
|
150
|
+
let sentCookie = this.getCachedSession();
|
|
239
151
|
// getRequestOptions will be called with additional sentCookie parameter
|
|
240
152
|
const csrfOptions = this.getRequestOptions('GET', sentCookie);
|
|
241
|
-
|
|
153
|
+
// Added for Session reuse - ET-390 - Ends
|
|
154
|
+
let response = await fetch(csrfURL, csrfOptions);
|
|
242
155
|
// Added for Session reuse - ET-390 - Starts
|
|
156
|
+
// if the response status is 401 or 403, then get a new session id
|
|
243
157
|
if (sentCookie && this.sessionOptions.retryStatuses.includes(response.status)) {
|
|
244
158
|
console.warn('Cached FlexPLM session rejected on csrf call (status ' + response.status + '). Retrying with a new session.');
|
|
245
|
-
|
|
159
|
+
this.clearSession();
|
|
160
|
+
sentCookie = undefined;
|
|
161
|
+
response = await fetch(csrfURL, this.getRequestOptions('GET'));
|
|
246
162
|
}
|
|
247
163
|
// Added for Session reuse - ET-390 - Ends
|
|
248
164
|
if (response.status >= 300) {
|
|
@@ -325,7 +241,7 @@ class FlexPLMConnect {
|
|
|
325
241
|
let response = await this.sendRequest(csrf, payload);
|
|
326
242
|
if (csrf.sessionCookie && this.sessionOptions.retryStatuses.includes(response.status)) {
|
|
327
243
|
console.warn('FlexPLM rejected session/nonce (status ' + response.status + '). Getting a new session and retrying once.');
|
|
328
|
-
csrf = await this.getCSRF(true
|
|
244
|
+
csrf = await this.getCSRF(true);
|
|
329
245
|
response = await this.sendRequest(csrf, payload);
|
|
330
246
|
}
|
|
331
247
|
// Added for Session reuse - ET-390 - Ends
|
|
@@ -382,31 +298,17 @@ class FlexPLMConnect {
|
|
|
382
298
|
const path = urlPath || ('/servlet/rest' + this.vibeEventEndpoint);
|
|
383
299
|
const vibeEventsURL = this.config.apiHost + urlContext + path;
|
|
384
300
|
// Added for Session reuse - ET-390 - Starts
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const cookie = this.extractSessionCookie(res) ?? sent;
|
|
397
|
-
if (cookie)
|
|
398
|
-
this.storeSession(cookie);
|
|
399
|
-
}
|
|
400
|
-
return { response: res, sent };
|
|
401
|
-
};
|
|
402
|
-
return sent ? call() : this.runColdAcquisition(call);
|
|
403
|
-
};
|
|
404
|
-
const first = await attempt();
|
|
405
|
-
let response = first.response;
|
|
406
|
-
if (first.sent && this.sessionOptions.retryStatuses.includes(response.status)) {
|
|
407
|
-
if (this.getCachedSession() === first.sent)
|
|
408
|
-
this.clearSession();
|
|
409
|
-
response = (await attempt()).response;
|
|
301
|
+
const cached = this.getCachedSession();
|
|
302
|
+
const csrfOptions = this.getRequestOptions('GET', cached);
|
|
303
|
+
let response = await fetch(vibeEventsURL, csrfOptions);
|
|
304
|
+
if (cached && this.sessionOptions.retryStatuses.includes(response.status)) {
|
|
305
|
+
this.clearSession();
|
|
306
|
+
response = await fetch(vibeEventsURL, this.getRequestOptions('GET'));
|
|
307
|
+
}
|
|
308
|
+
if (this.sessionOptions.enabled) {
|
|
309
|
+
const cachedCookie = this.extractSessionCookie(response) ?? cached;
|
|
310
|
+
if (cachedCookie)
|
|
311
|
+
this.storeSession(cachedCookie);
|
|
410
312
|
}
|
|
411
313
|
// Added for Session reuse - ET-390 - Ends
|
|
412
314
|
if (response.status >= 300) {
|
|
@@ -145,7 +145,7 @@ describe('FlexPLMConnect.sendRequest', () => {
|
|
|
145
145
|
// Added for Session reuse - ET-390 - Starts
|
|
146
146
|
describe('FlexPLMConnect session reuse', () => {
|
|
147
147
|
const payload = { id: '123' };
|
|
148
|
-
it('
|
|
148
|
+
it('captures JSESSIONID from the csrf GET and sends it on the POST', async () => {
|
|
149
149
|
const u = uniqueUser();
|
|
150
150
|
fetchMock()
|
|
151
151
|
.mockResolvedValueOnce(resp(200, ['JSESSIONID=abc.tomcat1; Path=/; HttpOnly']))
|
|
@@ -326,121 +326,6 @@ describe('FlexPLMConnect session reuse', () => {
|
|
|
326
326
|
isInfoOn.mockRestore();
|
|
327
327
|
info.mockRestore();
|
|
328
328
|
});
|
|
329
|
-
describe('option normalisation', () => {
|
|
330
|
-
const rejectedOnceThenOk = (u, opts) => {
|
|
331
|
-
fetchMock()
|
|
332
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=old.tomcat1']))
|
|
333
|
-
.mockResolvedValueOnce(resp(403, [], {}))
|
|
334
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=new.tomcat1']))
|
|
335
|
-
.mockResolvedValueOnce(resp(200, [], {}));
|
|
336
|
-
return new flexplm_connect_1.FlexPLMConnect(sessionConfig(u, { enabled: true, ...opts })).sendToFlexPLM(payload);
|
|
337
|
-
};
|
|
338
|
-
it.each([
|
|
339
|
-
['a scalar number', 403],
|
|
340
|
-
['a comma separated string', '401, 403'],
|
|
341
|
-
['garbage (falls back to 401/403)', 'abc'],
|
|
342
|
-
['an empty array (falls back to 401/403)', []],
|
|
343
|
-
])('retryStatuses given as %s does not throw and still retries on 403', async (_label, retryStatuses) => {
|
|
344
|
-
await rejectedOnceThenOk(uniqueUser(), { retryStatuses });
|
|
345
|
-
expect(fetchMock()).toHaveBeenCalledTimes(4);
|
|
346
|
-
});
|
|
347
|
-
it.each([['abc'], [0], [-5]])('invalid ttlSeconds (%p) falls back to the 900s default', async (ttlSeconds) => {
|
|
348
|
-
const u = uniqueUser();
|
|
349
|
-
const realNow = Date.now();
|
|
350
|
-
const nowSpy = jest.spyOn(Date, 'now').mockReturnValue(realNow);
|
|
351
|
-
fetchMock()
|
|
352
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=abc.tomcat1']))
|
|
353
|
-
.mockResolvedValueOnce(resp(200, [], {}))
|
|
354
|
-
.mockResolvedValueOnce(resp(200, []))
|
|
355
|
-
.mockResolvedValueOnce(resp(200, [], {}));
|
|
356
|
-
const cfg = sessionConfig(u, { enabled: true, ttlSeconds });
|
|
357
|
-
await new flexplm_connect_1.FlexPLMConnect(cfg).sendToFlexPLM(payload);
|
|
358
|
-
nowSpy.mockReturnValue(realNow + 2000);
|
|
359
|
-
await new flexplm_connect_1.FlexPLMConnect(cfg).sendToFlexPLM(payload);
|
|
360
|
-
expect(callHeaders(2).Cookie).toBe('JSESSIONID=abc.tomcat1');
|
|
361
|
-
nowSpy.mockRestore();
|
|
362
|
-
});
|
|
363
|
-
it('a blank cookieName falls back to JSESSIONID', async () => {
|
|
364
|
-
const u = uniqueUser();
|
|
365
|
-
fetchMock()
|
|
366
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=abc.tomcat1']))
|
|
367
|
-
.mockResolvedValueOnce(resp(200, [], {}));
|
|
368
|
-
await new flexplm_connect_1.FlexPLMConnect(sessionConfig(u, { enabled: true, cookieName: ' ' })).sendToFlexPLM(payload);
|
|
369
|
-
expect(callHeaders(1).Cookie).toBe('JSESSIONID=abc.tomcat1');
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
describe('cookie names containing regex metacharacters', () => {
|
|
373
|
-
it('extracts a cookie whose name contains "+"', async () => {
|
|
374
|
-
const u = uniqueUser();
|
|
375
|
-
fetchMock()
|
|
376
|
-
.mockResolvedValueOnce(resp(200, ['SID+=abc; Path=/']))
|
|
377
|
-
.mockResolvedValueOnce(resp(200, [], {}));
|
|
378
|
-
await new flexplm_connect_1.FlexPLMConnect(sessionConfig(u, { enabled: true, cookieName: 'SID+' })).sendToFlexPLM(payload);
|
|
379
|
-
expect(callHeaders(1).Cookie).toBe('SID+=abc');
|
|
380
|
-
});
|
|
381
|
-
it('treats "." literally and does not match a look-alike cookie', async () => {
|
|
382
|
-
const u = uniqueUser();
|
|
383
|
-
fetchMock()
|
|
384
|
-
.mockResolvedValueOnce(resp(200, ['AxB=wrong; Path=/']))
|
|
385
|
-
.mockResolvedValueOnce(resp(200, [], {}));
|
|
386
|
-
await new flexplm_connect_1.FlexPLMConnect(sessionConfig(u, { enabled: true, cookieName: 'A.B' })).sendToFlexPLM(payload);
|
|
387
|
-
expect(callHeaders(1).Cookie).toBeUndefined();
|
|
388
|
-
});
|
|
389
|
-
});
|
|
390
|
-
describe('concurrent session acquisition', () => {
|
|
391
|
-
const flush = () => new Promise(r => setImmediate(r));
|
|
392
|
-
const isColdGet = (call) => call[1].method === 'GET' && !call[1].headers.Cookie;
|
|
393
|
-
it('shares one session across concurrent events on a cold cache', async () => {
|
|
394
|
-
const u = uniqueUser();
|
|
395
|
-
let release;
|
|
396
|
-
const gate = new Promise(r => { release = r; });
|
|
397
|
-
fetchMock().mockImplementation(async (_url, opts) => {
|
|
398
|
-
if (opts.method === 'GET' && !opts.headers.Cookie) {
|
|
399
|
-
await gate;
|
|
400
|
-
return resp(200, ['JSESSIONID=abc.tomcat1']);
|
|
401
|
-
}
|
|
402
|
-
return resp(200, []);
|
|
403
|
-
});
|
|
404
|
-
const all = Promise.all([1, 2, 3].map(() => new flexplm_connect_1.FlexPLMConnect(sessionConfig(u)).getCSRF()));
|
|
405
|
-
await flush();
|
|
406
|
-
expect(fetchMock()).toHaveBeenCalledTimes(1); // the other two are waiting for the first acquisition
|
|
407
|
-
release();
|
|
408
|
-
const results = await all;
|
|
409
|
-
expect(fetchMock().mock.calls.filter(isColdGet)).toHaveLength(1);
|
|
410
|
-
results.forEach(r => expect(r.sessionCookie).toBe('abc.tomcat1'));
|
|
411
|
-
});
|
|
412
|
-
it('a waiter does not inherit the failure of the first acquisition', async () => {
|
|
413
|
-
const u = uniqueUser();
|
|
414
|
-
let release;
|
|
415
|
-
const gate = new Promise(r => { release = r; });
|
|
416
|
-
fetchMock()
|
|
417
|
-
.mockImplementationOnce(async () => { await gate; return resp(500, []); })
|
|
418
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=abc.tomcat1']));
|
|
419
|
-
const first = new flexplm_connect_1.FlexPLMConnect(sessionConfig(u)).getCSRF();
|
|
420
|
-
const firstResult = first.catch(e => e);
|
|
421
|
-
const second = new flexplm_connect_1.FlexPLMConnect(sessionConfig(u)).getCSRF();
|
|
422
|
-
await flush();
|
|
423
|
-
release();
|
|
424
|
-
expect(await firstResult).toBeInstanceOf(Error);
|
|
425
|
-
expect((await second).sessionCookie).toBe('abc.tomcat1');
|
|
426
|
-
});
|
|
427
|
-
it('parallel events rejected with 403 create only one replacement session', async () => {
|
|
428
|
-
const u = uniqueUser();
|
|
429
|
-
fetchMock().mockResolvedValueOnce(resp(200, ['JSESSIONID=old.tomcat1']));
|
|
430
|
-
await new flexplm_connect_1.FlexPLMConnect(sessionConfig(u)).getCSRF(); // prime the cache with the old session
|
|
431
|
-
fetchMock().mockReset();
|
|
432
|
-
fetchMock().mockImplementation(async (_url, opts) => {
|
|
433
|
-
const cookie = opts.headers.Cookie;
|
|
434
|
-
if (opts.method === 'POST')
|
|
435
|
-
return cookie === 'JSESSIONID=new.tomcat1' ? resp(200, [], {}) : resp(403, [], {});
|
|
436
|
-
if (!cookie)
|
|
437
|
-
return resp(200, ['JSESSIONID=new.tomcat1']);
|
|
438
|
-
return resp(200, []);
|
|
439
|
-
});
|
|
440
|
-
await Promise.all([1, 2, 3].map(() => new flexplm_connect_1.FlexPLMConnect(sessionConfig(u)).sendToFlexPLM(payload)));
|
|
441
|
-
expect(fetchMock().mock.calls.filter(isColdGet)).toHaveLength(1);
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
329
|
});
|
|
445
330
|
describe('FlexPLMConnect session reuse - feature disabled (default)', () => {
|
|
446
331
|
const payload = { id: '123' };
|
|
@@ -476,7 +361,7 @@ describe('FlexPLMConnect session reuse - feature disabled (default)', () => {
|
|
|
476
361
|
expect(callHeaders(1).Cookie).toBeUndefined();
|
|
477
362
|
});
|
|
478
363
|
});
|
|
479
|
-
describe('FlexPLMConnect.getRequest session reuse', () => {
|
|
364
|
+
describe('FlexPLMConnect.getRequest session reuse (only if you applied step 2g)', () => {
|
|
480
365
|
it('sends the cached cookie on image/GET requests', async () => {
|
|
481
366
|
const u = uniqueUser();
|
|
482
367
|
fetchMock()
|
|
@@ -501,20 +386,5 @@ describe('FlexPLMConnect.getRequest session reuse', () => {
|
|
|
501
386
|
expect(callHeaders(2).Cookie).toBe('JSESSIONID=abc.tomcat1');
|
|
502
387
|
expect(callHeaders(3).Cookie).toBeUndefined();
|
|
503
388
|
});
|
|
504
|
-
it('does not re-store the rejected cookie when the retry issues no Set-Cookie', async () => {
|
|
505
|
-
const u = uniqueUser();
|
|
506
|
-
fetchMock()
|
|
507
|
-
.mockResolvedValueOnce(resp(200, ['JSESSIONID=stale.tomcat1']))
|
|
508
|
-
.mockResolvedValueOnce(resp(200, [], {}))
|
|
509
|
-
.mockResolvedValueOnce(resp(401, [])) // getRequest with the cached cookie
|
|
510
|
-
.mockResolvedValueOnce(resp(200, [], { items: [] })) // retry succeeds, no Set-Cookie
|
|
511
|
-
.mockResolvedValueOnce(resp(200, [], { items: [] })); // next getRequest
|
|
512
|
-
const connect = new flexplm_connect_1.FlexPLMConnect(sessionConfig(u));
|
|
513
|
-
await connect.sendToFlexPLM({ id: '1' });
|
|
514
|
-
await connect.getRequest();
|
|
515
|
-
await connect.getRequest();
|
|
516
|
-
expect(callHeaders(3).Cookie).toBeUndefined();
|
|
517
|
-
expect(callHeaders(4).Cookie).toBeUndefined(); // stale cookie must not be sent again
|
|
518
|
-
});
|
|
519
389
|
});
|
|
520
390
|
// Added for Session reuse - ET-390 - Ends
|