@adobe/alloy 2.36.0 → 2.36.1-beta.0
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.
- package/dist/alloy.js +124 -51
- package/dist/alloy.min.js +2 -2
- package/dist/types/browser/src/services/injectSendFetchRequest.d.ts +7 -3
- package/dist/types/core/src/core/network/injectSendNetworkRequest.d.ts +2 -1
- package/dist/types/core/src/services/types.d.ts +17 -1
- package/dist/types/core/src/utils/request/createRequest.d.ts +1 -0
- package/dist/types/core/src/utils/request/types.d.ts +2 -0
- package/package.json +5 -3
- package/src/services/createBrowserNetworkService.js +1 -1
- package/src/services/injectSendBeaconRequest.js +3 -1
- package/src/services/injectSendFetchRequest.js +41 -4
package/dist/alloy.js
CHANGED
|
@@ -3750,7 +3750,14 @@
|
|
|
3750
3750
|
/**
|
|
3751
3751
|
* Send a network request and returns details about the response.
|
|
3752
3752
|
*/
|
|
3753
|
-
return ({
|
|
3753
|
+
return ({
|
|
3754
|
+
requestId,
|
|
3755
|
+
url,
|
|
3756
|
+
payload,
|
|
3757
|
+
useSendBeacon,
|
|
3758
|
+
useKeepalive,
|
|
3759
|
+
headers,
|
|
3760
|
+
}) => {
|
|
3754
3761
|
// We want to log raw payload and event data rather than
|
|
3755
3762
|
// our fancy wrapper objects. Calling payload.toJSON() is
|
|
3756
3763
|
// insufficient to get all the nested raw data, because it's
|
|
@@ -3771,53 +3778,55 @@
|
|
|
3771
3778
|
// navigator.sendBeacon() has no way to attach custom headers, so a
|
|
3772
3779
|
// request that needs any (e.g. authenticated Server API requests)
|
|
3773
3780
|
// must always go through fetch, regardless of useSendBeacon.
|
|
3774
|
-
const
|
|
3775
|
-
useSendBeacon && !headers
|
|
3781
|
+
const request =
|
|
3782
|
+
useSendBeacon && !headers
|
|
3783
|
+
? sendBeaconRequest(url, stringifiedPayload)
|
|
3784
|
+
: sendFetchRequest(url, stringifiedPayload, headers, {
|
|
3785
|
+
keepalive: Boolean(useKeepalive),
|
|
3786
|
+
});
|
|
3776
3787
|
|
|
3777
|
-
return
|
|
3778
|
-
|
|
3779
|
-
|
|
3788
|
+
return request.then((response) => {
|
|
3789
|
+
const requestIsRetryable = isRequestRetryable({
|
|
3790
|
+
response,
|
|
3791
|
+
retriesAttempted,
|
|
3792
|
+
});
|
|
3793
|
+
|
|
3794
|
+
if (requestIsRetryable) {
|
|
3795
|
+
const requestRetryDelay = getRequestRetryDelay({
|
|
3780
3796
|
response,
|
|
3781
3797
|
retriesAttempted,
|
|
3782
3798
|
});
|
|
3799
|
+
return new Promise((resolve) => {
|
|
3800
|
+
setTimeout(() => {
|
|
3801
|
+
resolve(executeRequest(retriesAttempted + 1));
|
|
3802
|
+
}, requestRetryDelay);
|
|
3803
|
+
});
|
|
3804
|
+
}
|
|
3783
3805
|
|
|
3784
|
-
|
|
3785
|
-
const requestRetryDelay = getRequestRetryDelay({
|
|
3786
|
-
response,
|
|
3787
|
-
retriesAttempted,
|
|
3788
|
-
});
|
|
3789
|
-
return new Promise((resolve) => {
|
|
3790
|
-
setTimeout(() => {
|
|
3791
|
-
resolve(executeRequest(retriesAttempted + 1));
|
|
3792
|
-
}, requestRetryDelay);
|
|
3793
|
-
});
|
|
3794
|
-
}
|
|
3795
|
-
|
|
3796
|
-
let parsedBody;
|
|
3806
|
+
let parsedBody;
|
|
3797
3807
|
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3808
|
+
try {
|
|
3809
|
+
parsedBody = JSON.parse(response.body);
|
|
3810
|
+
} catch {
|
|
3811
|
+
// Non-JSON. Something went wrong.
|
|
3812
|
+
}
|
|
3803
3813
|
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3814
|
+
logger.logOnNetworkResponse({
|
|
3815
|
+
requestId,
|
|
3816
|
+
url,
|
|
3817
|
+
payload: parsedPayload,
|
|
3818
|
+
...response,
|
|
3819
|
+
parsedBody,
|
|
3820
|
+
retriesAttempted,
|
|
3821
|
+
});
|
|
3812
3822
|
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
);
|
|
3823
|
+
return {
|
|
3824
|
+
statusCode: response.statusCode,
|
|
3825
|
+
body: response.body,
|
|
3826
|
+
parsedBody,
|
|
3827
|
+
getHeader: response.getHeader,
|
|
3828
|
+
};
|
|
3829
|
+
});
|
|
3821
3830
|
};
|
|
3822
3831
|
|
|
3823
3832
|
return executeRequest().catch((error) => {
|
|
@@ -5229,6 +5238,15 @@
|
|
|
5229
5238
|
},
|
|
5230
5239
|
logOnNetworkResponse(data) {
|
|
5231
5240
|
notifyMonitors("onNetworkResponse", data);
|
|
5241
|
+
if (data.sentWithBeacon) {
|
|
5242
|
+
// sendBeacon only tells us the browser queued the request; there is
|
|
5243
|
+
// no server response to report.
|
|
5244
|
+
log(
|
|
5245
|
+
"info",
|
|
5246
|
+
`Request ${data.requestId}: Sent using sendBeacon. No response is available for sendBeacon requests. If the page navigates away, the browser keeps sending the request in the background, but its developer tools may show it as canceled.`,
|
|
5247
|
+
);
|
|
5248
|
+
return;
|
|
5249
|
+
}
|
|
5232
5250
|
const messagesSuffix =
|
|
5233
5251
|
data.parsedBody || data.body ? `response body:` : `no response body.`;
|
|
5234
5252
|
log(
|
|
@@ -5335,6 +5353,9 @@
|
|
|
5335
5353
|
* @param {RequestPayload} options.payload
|
|
5336
5354
|
* @param {function({isIdentityEstablished: boolean}): string} options.getAction
|
|
5337
5355
|
* @param {function({isIdentityEstablished: boolean}): boolean} options.getUseSendBeacon
|
|
5356
|
+
* @param {function(): boolean} [options.getUseKeepalive] Whether a fetch
|
|
5357
|
+
* request should be sent with `keepalive` so it survives a page unload.
|
|
5358
|
+
* Defaults to false.
|
|
5338
5359
|
* @param {string} [options.datastreamIdOverride]
|
|
5339
5360
|
* @param {string} [options.edgeSubPath]
|
|
5340
5361
|
*
|
|
@@ -5358,6 +5379,7 @@
|
|
|
5358
5379
|
payload,
|
|
5359
5380
|
getAction,
|
|
5360
5381
|
getUseSendBeacon,
|
|
5382
|
+
getUseKeepalive = () => false,
|
|
5361
5383
|
datastreamIdOverride,
|
|
5362
5384
|
edgeSubPath,
|
|
5363
5385
|
requestParams = {},
|
|
@@ -5383,6 +5405,9 @@
|
|
|
5383
5405
|
getUseSendBeacon() {
|
|
5384
5406
|
return getUseSendBeacon({ isIdentityEstablished });
|
|
5385
5407
|
},
|
|
5408
|
+
getUseKeepalive() {
|
|
5409
|
+
return getUseKeepalive();
|
|
5410
|
+
},
|
|
5386
5411
|
getEdgeSubPath() {
|
|
5387
5412
|
if (edgeSubPath) {
|
|
5388
5413
|
return edgeSubPath;
|
|
@@ -5451,9 +5476,9 @@
|
|
|
5451
5476
|
// No error will be thrown and an identity is established. This is good.
|
|
5452
5477
|
// 3. The document is unloaded and Alloy does not receive the empty response
|
|
5453
5478
|
// back from the collect endpoint before navigation is completed. In this
|
|
5454
|
-
// case, no error is thrown, but no identity was established
|
|
5455
|
-
//
|
|
5456
|
-
//
|
|
5479
|
+
// case, no error is thrown, but no identity was established. Because the
|
|
5480
|
+
// fetch is sent with `keepalive` (see getUseKeepalive below), the browser
|
|
5481
|
+
// still delivers the request to the server after the page unloads.
|
|
5457
5482
|
//
|
|
5458
5483
|
// The second approach seemed preferable.
|
|
5459
5484
|
return (
|
|
@@ -5462,6 +5487,12 @@
|
|
|
5462
5487
|
);
|
|
5463
5488
|
};
|
|
5464
5489
|
|
|
5490
|
+
// When the document may be unloading but we use fetch anyway (for example,
|
|
5491
|
+
// before an identity is established), send the fetch with `keepalive` so the
|
|
5492
|
+
// browser doesn't cancel the request when the page navigates away.
|
|
5493
|
+
const getUseKeepalive = () =>
|
|
5494
|
+
dataCollectionRequestPayload.getDocumentMayUnload();
|
|
5495
|
+
|
|
5465
5496
|
return createRequest({
|
|
5466
5497
|
payload: dataCollectionRequestPayload,
|
|
5467
5498
|
getAction({ isIdentityEstablished }) {
|
|
@@ -5470,6 +5501,7 @@
|
|
|
5470
5501
|
: "interact";
|
|
5471
5502
|
},
|
|
5472
5503
|
getUseSendBeacon,
|
|
5504
|
+
getUseKeepalive,
|
|
5473
5505
|
datastreamIdOverride,
|
|
5474
5506
|
});
|
|
5475
5507
|
};
|
|
@@ -6335,6 +6367,7 @@
|
|
|
6335
6367
|
url,
|
|
6336
6368
|
payload: outgoingPayload,
|
|
6337
6369
|
useSendBeacon: request.getUseSendBeacon(),
|
|
6370
|
+
useKeepalive: request.getUseKeepalive(),
|
|
6338
6371
|
headers,
|
|
6339
6372
|
});
|
|
6340
6373
|
})
|
|
@@ -6355,6 +6388,7 @@
|
|
|
6355
6388
|
url,
|
|
6356
6389
|
payload,
|
|
6357
6390
|
useSendBeacon: request.getUseSendBeacon(),
|
|
6391
|
+
useKeepalive: request.getUseKeepalive(),
|
|
6358
6392
|
});
|
|
6359
6393
|
}
|
|
6360
6394
|
return handleRequestFailure(onRequestFailureCallbackAggregator)(error);
|
|
@@ -7956,10 +7990,10 @@
|
|
|
7956
7990
|
governing permissions and limitations under the License.
|
|
7957
7991
|
*/
|
|
7958
7992
|
|
|
7959
|
-
// The 2.36.0 keyword will be replace at alloy build time with the package.json version.
|
|
7993
|
+
// The 2.36.1-beta.0 keyword will be replace at alloy build time with the package.json version.
|
|
7960
7994
|
// see babel-plugin-version
|
|
7961
7995
|
|
|
7962
|
-
var libraryVersion = "2.36.0";
|
|
7996
|
+
var libraryVersion = "2.36.1-beta.0";
|
|
7963
7997
|
|
|
7964
7998
|
/*
|
|
7965
7999
|
Copyright 2019 Adobe. All rights reserved.
|
|
@@ -22117,9 +22151,23 @@
|
|
|
22117
22151
|
governing permissions and limitations under the License.
|
|
22118
22152
|
*/
|
|
22119
22153
|
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22154
|
+
/** @import { NetworkService } from "@adobe/alloy-core/services" */
|
|
22155
|
+
|
|
22156
|
+
/**
|
|
22157
|
+
* @param {Object} params
|
|
22158
|
+
* @param {typeof window.fetch} params.fetch
|
|
22159
|
+
* @param {{ info: (...args: any[]) => void }} params.logger
|
|
22160
|
+
* @returns {NetworkService["sendFetchRequest"]}
|
|
22161
|
+
*/
|
|
22162
|
+
var injectSendFetchRequest = ({ fetch, logger }) => {
|
|
22163
|
+
/**
|
|
22164
|
+
* @param {string} url
|
|
22165
|
+
* @param {string} body
|
|
22166
|
+
* @param {Record<string, string> | undefined} headers
|
|
22167
|
+
* @param {boolean} keepalive
|
|
22168
|
+
*/
|
|
22169
|
+
const startFetch = (url, body, headers, keepalive) =>
|
|
22170
|
+
fetch(url, {
|
|
22123
22171
|
method: "POST",
|
|
22124
22172
|
cache: "no-cache",
|
|
22125
22173
|
credentials: "include", // To set the cookie header in the request.
|
|
@@ -22129,7 +22177,30 @@
|
|
|
22129
22177
|
},
|
|
22130
22178
|
referrerPolicy: "no-referrer-when-downgrade",
|
|
22131
22179
|
body,
|
|
22132
|
-
|
|
22180
|
+
...(keepalive ? { keepalive: true } : {}),
|
|
22181
|
+
});
|
|
22182
|
+
|
|
22183
|
+
return (url, body, headers, { keepalive = false } = {}) => {
|
|
22184
|
+
let responsePromise = startFetch(url, body, headers, keepalive);
|
|
22185
|
+
|
|
22186
|
+
if (keepalive) {
|
|
22187
|
+
// Browsers reject keepalive requests whose body, together with every
|
|
22188
|
+
// other in-flight keepalive request and sendBeacon on the page, exceeds
|
|
22189
|
+
// 64 KiB. The rejection is a TypeError that looks the same as any other
|
|
22190
|
+
// network error ("Failed to fetch", "NetworkError when attempting to
|
|
22191
|
+
// fetch resource.", "Load failed") and arrives before anything is sent,
|
|
22192
|
+
// so retry once without keepalive. Only fetch() itself is covered here;
|
|
22193
|
+
// a failure while reading the response is not retried because the
|
|
22194
|
+
// server already received the request.
|
|
22195
|
+
responsePromise = responsePromise.catch(() => {
|
|
22196
|
+
logger.info(
|
|
22197
|
+
"Unable to send the request with `keepalive`; falling back to a regular `fetch`.",
|
|
22198
|
+
);
|
|
22199
|
+
return startFetch(url, body, headers, false);
|
|
22200
|
+
});
|
|
22201
|
+
}
|
|
22202
|
+
|
|
22203
|
+
return responsePromise.then((response) => {
|
|
22133
22204
|
return response.text().then((responseBody) => ({
|
|
22134
22205
|
statusCode: response.status,
|
|
22135
22206
|
// We expose headers through a function instead of creating an object
|
|
@@ -22166,13 +22237,15 @@
|
|
|
22166
22237
|
|
|
22167
22238
|
// Using sendBeacon, we technically don't get a response back from
|
|
22168
22239
|
// the server, but we'll resolve the promise with an object to maintain
|
|
22169
|
-
// consistency with other network strategies.
|
|
22240
|
+
// consistency with other network strategies. `sentWithBeacon` marks the
|
|
22241
|
+
// response as synthetic so it isn't logged as a real server response.
|
|
22170
22242
|
return Promise.resolve({
|
|
22171
22243
|
statusCode: 204,
|
|
22172
22244
|
getHeader() {
|
|
22173
22245
|
return null;
|
|
22174
22246
|
},
|
|
22175
22247
|
body: "",
|
|
22248
|
+
sentWithBeacon: true,
|
|
22176
22249
|
});
|
|
22177
22250
|
};
|
|
22178
22251
|
};
|
|
@@ -22196,7 +22269,7 @@
|
|
|
22196
22269
|
*/
|
|
22197
22270
|
const createBrowserNetworkService = ({ logger }) => {
|
|
22198
22271
|
const { fetch, navigator } = window;
|
|
22199
|
-
const sendFetchRequest = injectSendFetchRequest({ fetch });
|
|
22272
|
+
const sendFetchRequest = injectSendFetchRequest({ fetch, logger });
|
|
22200
22273
|
const sendBeaconRequest =
|
|
22201
22274
|
typeof navigator.sendBeacon === "function"
|
|
22202
22275
|
? injectSendBeaconRequest({
|