From ccc5cc068f788013c19498c44d13530c1bc98912 Mon Sep 17 00:00:00 2001 From: SkyZeroZx <73321943+SkyZeroZx@users.noreply.github.com> Date: Fri, 28 Mar 2025 19:32:28 -0500 Subject: [PATCH] feat(http): add keepalive support for fetch requests (#60621) This commit adds support for the Fetch API's keepalive option when using HttpClient with the withFetch provider. The change includes: - Added keepalive to HttpRequestInit interface - Modified FetchBackend to pass the option - Added some unit test PR Close #60621 --- goldens/public-api/common/http/errors.api.md | 2 + goldens/public-api/common/http/index.api.md | 129 ++++++++++++++++++ packages/common/http/src/client.ts | 134 ++++++++++++++++++- packages/common/http/src/errors.ts | 1 + packages/common/http/src/fetch.ts | 2 +- packages/common/http/src/request.ts | 21 ++- packages/common/http/src/xhr.ts | 15 ++- packages/common/http/test/fetch_spec.ts | 14 ++ packages/common/http/test/request_spec.ts | 12 ++ 9 files changed, 324 insertions(+), 6 deletions(-) diff --git a/goldens/public-api/common/http/errors.api.md b/goldens/public-api/common/http/errors.api.md index 3b07efc72c9..01952b39c21 100644 --- a/goldens/public-api/common/http/errors.api.md +++ b/goldens/public-api/common/http/errors.api.md @@ -21,6 +21,8 @@ export const enum RuntimeErrorCode { // (undocumented) JSONP_WRONG_RESPONSE_TYPE = 2811, // (undocumented) + KEEPALIVE_NOT_SUPPORTED_WITH_XHR = 2813, + // (undocumented) MISSING_JSONP_MODULE = -2800, // (undocumented) NOT_USING_FETCH_BACKEND_IN_SSR = 2801, diff --git a/goldens/public-api/common/http/index.api.md b/goldens/public-api/common/http/index.api.md index d038f7032b2..278ad9a29d7 100644 --- a/goldens/public-api/common/http/index.api.md +++ b/goldens/public-api/common/http/index.api.md @@ -50,6 +50,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable; delete(url: string, options: { @@ -60,6 +61,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable; delete(url: string, options: { @@ -70,6 +72,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable; delete(url: string, options: { @@ -80,6 +83,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -90,6 +94,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -100,6 +105,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -110,6 +116,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -120,6 +127,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -130,6 +138,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -140,6 +149,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -150,6 +160,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -160,6 +171,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options: { @@ -170,6 +182,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable>; delete(url: string, options?: { @@ -180,6 +193,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable; delete(url: string, options?: { @@ -190,6 +204,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }): Observable; get(url: string, options: { @@ -200,6 +215,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -212,6 +228,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -224,6 +241,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -236,6 +254,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -248,6 +267,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -260,6 +280,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -272,6 +293,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -284,6 +306,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -296,6 +319,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -308,6 +332,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -320,6 +345,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -332,6 +358,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -344,6 +371,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -356,6 +384,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -368,6 +397,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -380,6 +410,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -392,6 +423,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -404,6 +436,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -416,6 +449,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -428,6 +462,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -440,6 +475,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -452,6 +488,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -464,6 +501,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -476,6 +514,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -488,6 +527,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -500,6 +540,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -512,6 +553,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -524,6 +566,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -536,6 +579,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -548,6 +592,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -562,6 +607,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; options(url: string, options: { headers?: HttpHeaders | Record; @@ -571,6 +617,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; options(url: string, options: { headers?: HttpHeaders | Record; @@ -580,6 +627,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; options(url: string, options: { headers?: HttpHeaders | Record; @@ -589,6 +637,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -598,6 +647,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -607,6 +657,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -616,6 +667,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -625,6 +677,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -634,6 +687,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -643,6 +697,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -652,6 +707,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -661,6 +717,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options: { headers?: HttpHeaders | Record; @@ -670,6 +727,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; options(url: string, options?: { headers?: HttpHeaders | Record; @@ -679,6 +737,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; options(url: string, options?: { headers?: HttpHeaders | Record; @@ -688,6 +747,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -697,6 +757,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -706,6 +767,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -715,6 +777,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -724,6 +787,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -733,6 +797,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -742,6 +807,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -751,6 +817,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -760,6 +827,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -769,6 +837,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -778,6 +847,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -787,6 +857,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -796,6 +867,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -805,6 +877,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; patch(url: string, body: any | null, options?: { headers?: HttpHeaders | Record; @@ -814,6 +887,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; patch(url: string, body: any | null, options?: { headers?: HttpHeaders | Record; @@ -823,6 +897,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; post(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -832,6 +907,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -844,6 +920,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -856,6 +933,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -868,6 +946,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -880,6 +959,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -892,6 +972,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -904,6 +985,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -916,6 +998,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -928,6 +1011,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -940,6 +1024,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -952,6 +1037,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -964,6 +1050,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -976,6 +1063,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -988,6 +1076,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1000,6 +1089,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1012,6 +1102,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1021,6 +1112,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1030,6 +1122,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1039,6 +1132,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1048,6 +1142,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1057,6 +1152,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1066,6 +1162,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1075,6 +1172,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1084,6 +1182,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1093,6 +1192,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1102,6 +1202,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1111,6 +1212,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options: { headers?: HttpHeaders | Record; @@ -1120,6 +1222,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; put(url: string, body: any | null, options?: { headers?: HttpHeaders | Record; @@ -1129,6 +1232,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; put(url: string, body: any | null, options?: { headers?: HttpHeaders | Record; @@ -1138,6 +1242,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable; request(req: HttpRequest): Observable>; request(method: string, url: string, options: { @@ -1149,6 +1254,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1162,6 +1268,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1175,6 +1282,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1188,6 +1296,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1201,6 +1310,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1214,6 +1324,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1227,6 +1338,7 @@ export class HttpClient { params?: HttpParams | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1240,6 +1352,7 @@ export class HttpClient { params?: HttpParams | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1253,6 +1366,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1266,6 +1380,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1279,6 +1394,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1292,6 +1408,7 @@ export class HttpClient { params?: HttpParams | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }): Observable>; request(method: string, url: string, options: { body?: any; @@ -1302,6 +1419,7 @@ export class HttpClient { params?: HttpParams | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1315,6 +1433,7 @@ export class HttpClient { responseType?: 'json'; reportProgress?: boolean; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1328,6 +1447,7 @@ export class HttpClient { responseType?: 'json'; reportProgress?: boolean; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1341,6 +1461,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1569,6 +1690,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1580,6 +1702,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; }); constructor(method: 'POST', url: string, body: T | null, init?: { headers?: HttpHeaders; @@ -1588,6 +1711,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1599,6 +1723,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; }); constructor(method: string, url: string, body: T | null, init?: { headers?: HttpHeaders; @@ -1607,6 +1732,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1622,6 +1748,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: { includeHeaders?: string[]; } | boolean; @@ -1642,6 +1769,7 @@ export class HttpRequest { reportProgress?: boolean; params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; + keepalive?: boolean; withCredentials?: boolean; transferCache?: { includeHeaders?: string[]; @@ -1659,6 +1787,7 @@ export class HttpRequest { readonly context: HttpContext; detectContentTypeHeader(): string | null; readonly headers: HttpHeaders; + readonly keepalive: boolean; readonly method: string; readonly params: HttpParams; readonly reportProgress: boolean; diff --git a/packages/common/http/src/client.ts b/packages/common/http/src/client.ts index 82f6b28b7d5..55b31a4c769 100644 --- a/packages/common/http/src/client.ts +++ b/packages/common/http/src/client.ts @@ -39,6 +39,7 @@ function addBody( reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, body: T | null, @@ -53,6 +54,7 @@ function addBody( responseType: options.responseType, withCredentials: options.withCredentials, transferCache: options.transferCache, + keepalive: options.keepalive, }; } @@ -145,6 +147,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -173,6 +176,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -201,6 +205,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -230,6 +235,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -259,6 +265,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -288,6 +295,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -317,6 +325,7 @@ export class HttpClient { | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -346,6 +355,7 @@ export class HttpClient { | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -374,6 +384,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -401,6 +412,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -429,6 +441,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -458,6 +471,7 @@ export class HttpClient { | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -485,6 +499,7 @@ export class HttpClient { | Record>; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -513,6 +528,7 @@ export class HttpClient { responseType?: 'json'; reportProgress?: boolean; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -541,6 +557,7 @@ export class HttpClient { responseType?: 'json'; reportProgress?: boolean; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -568,6 +585,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -612,6 +630,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; } = {}, ): Observable { @@ -643,7 +662,6 @@ export class HttpClient { params = new HttpParams({fromObject: options.params} as HttpParamsOptions); } } - // Construct the request. req = new HttpRequest(first, url!, options.body !== undefined ? options.body : null, { headers, @@ -654,9 +672,9 @@ export class HttpClient { responseType: options.responseType || 'json', withCredentials: options.withCredentials, transferCache: options.transferCache, + keepalive: options.keepalive, }); } - // Start with an Observable.of() the initial request, and run the handler (which // includes all interceptors) inside a concatMap(). This way, the handler runs // inside an Observable chain, which causes interceptors to be re-run on every @@ -765,6 +783,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable; @@ -790,6 +809,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable; @@ -815,6 +835,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable; @@ -841,6 +862,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -867,6 +889,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -893,6 +916,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -919,6 +943,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -945,6 +970,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -970,6 +996,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -995,6 +1022,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -1020,6 +1048,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -1046,6 +1075,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -1071,6 +1101,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable>; @@ -1096,6 +1127,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable; @@ -1121,6 +1153,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; }, ): Observable; @@ -1146,6 +1179,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; body?: any | null; } = {}, ): Observable { @@ -1173,6 +1207,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1198,6 +1233,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1223,6 +1259,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1249,6 +1286,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1274,6 +1312,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1299,6 +1338,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1324,6 +1364,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1349,6 +1390,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1375,6 +1417,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1401,6 +1444,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1427,6 +1471,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1453,6 +1498,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1479,6 +1525,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1505,6 +1552,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1530,6 +1578,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1551,6 +1600,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; } = {}, ): Observable { @@ -1578,6 +1628,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1604,6 +1655,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1629,6 +1681,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1655,6 +1708,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1681,6 +1735,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1707,6 +1762,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1733,6 +1789,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1759,6 +1816,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1785,6 +1843,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1811,6 +1870,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1837,6 +1897,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1863,6 +1924,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1889,6 +1951,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -1915,6 +1978,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1941,6 +2005,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -1964,6 +2029,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; } = {}, ): Observable { @@ -2041,6 +2107,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2065,6 +2132,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2089,6 +2157,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2114,6 +2183,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2139,6 +2209,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2164,6 +2235,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2189,6 +2261,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2214,6 +2287,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2239,6 +2313,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2264,6 +2339,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2289,6 +2365,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2314,6 +2391,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2339,6 +2417,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2364,6 +2443,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2388,6 +2468,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2410,6 +2491,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; } = {}, ): Observable { return this.request('OPTIONS', url, options as any); @@ -2438,6 +2520,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2464,6 +2547,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2490,6 +2574,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2518,6 +2603,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2545,6 +2631,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2572,6 +2659,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2599,6 +2687,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2626,6 +2715,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2653,6 +2743,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2680,6 +2771,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2707,6 +2799,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2734,6 +2827,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2761,6 +2855,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -2788,6 +2883,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2815,6 +2911,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -2836,6 +2933,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; } = {}, ): Observable { return this.request('PATCH', url, addBody(options, body)); @@ -2864,6 +2962,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -2891,6 +2990,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -2918,6 +3018,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -2946,6 +3047,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -2973,6 +3075,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3001,6 +3104,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3029,6 +3133,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3057,6 +3162,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3085,6 +3191,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3113,6 +3220,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3141,6 +3249,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3169,6 +3278,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3198,6 +3308,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable>; @@ -3225,6 +3336,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -3253,6 +3365,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ): Observable; @@ -3276,6 +3389,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; } = {}, ): Observable { @@ -3305,6 +3419,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -3331,6 +3446,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -3357,6 +3473,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -3384,6 +3501,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3411,6 +3529,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3438,6 +3557,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3465,6 +3585,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3492,6 +3613,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3519,6 +3641,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'arraybuffer'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3546,6 +3669,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'blob'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3573,6 +3697,7 @@ export class HttpClient { reportProgress?: boolean; responseType: 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3600,6 +3725,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3627,6 +3753,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable>; @@ -3653,6 +3780,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -3679,6 +3807,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; + keepalive?: boolean; }, ): Observable; @@ -3701,6 +3830,7 @@ export class HttpClient { reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; } = {}, ): Observable { return this.request('PUT', url, addBody(options, body)); diff --git a/packages/common/http/src/errors.ts b/packages/common/http/src/errors.ts index 35a752c7d9b..48b04444e2a 100644 --- a/packages/common/http/src/errors.ts +++ b/packages/common/http/src/errors.ts @@ -24,4 +24,5 @@ export const enum RuntimeErrorCode { JSONP_WRONG_METHOD = 2810, JSONP_WRONG_RESPONSE_TYPE = 2811, JSONP_HEADERS_NOT_SUPPORTED = 2812, + KEEPALIVE_NOT_SUPPORTED_WITH_XHR = 2813, } diff --git a/packages/common/http/src/fetch.ts b/packages/common/http/src/fetch.ts index c1a82ca8cf3..c35d0d71e77 100644 --- a/packages/common/http/src/fetch.ts +++ b/packages/common/http/src/fetch.ts @@ -88,7 +88,6 @@ export class FetchBackend implements HttpBackend { ): Promise { const init = this.createRequestInit(request); let response; - try { // Run fetch outside of Angular zone. // This is due to Node.js fetch implementation (Undici) which uses a number of setTimeouts to check if @@ -282,6 +281,7 @@ export class FetchBackend implements HttpBackend { method: req.method, headers, credentials, + keepalive: req.keepalive, }; } diff --git a/packages/common/http/src/request.ts b/packages/common/http/src/request.ts index 505b490476e..ef85f10bb72 100644 --- a/packages/common/http/src/request.ts +++ b/packages/common/http/src/request.ts @@ -23,6 +23,7 @@ interface HttpRequestInit { responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; + keepalive?: boolean; } /** @@ -163,6 +164,11 @@ export class HttpRequest { */ readonly withCredentials: boolean = false; + /** + * When using the fetch implementation and set to `true`, the browser will not abort the associated request if the page that initiated it is unloaded before the request is complete. + */ + readonly keepalive: boolean = false; + /** * The expected response type of the server. * @@ -208,6 +214,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; /** * This property accepts either a boolean to enable/disable transferring cache for eligible * requests performed using `HttpClient`, or an object, which allows to configure cache @@ -229,6 +236,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ); constructor( @@ -242,6 +250,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; /** * This property accepts either a boolean to enable/disable transferring cache for eligible * requests performed using `HttpClient`, or an object, which allows to configure cache @@ -264,6 +273,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; }, ); constructor( @@ -277,6 +287,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; /** * This property accepts either a boolean to enable/disable transferring cache for eligible * requests performed using `HttpClient`, or an object, which allows to configure cache @@ -300,6 +311,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; } | null, @@ -310,6 +322,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; }, ) { @@ -334,7 +347,7 @@ export class HttpRequest { // Normalize reportProgress and withCredentials. this.reportProgress = !!options.reportProgress; this.withCredentials = !!options.withCredentials; - + this.keepalive = !!options.keepalive; // Override default response type of 'json' if one is provided. if (!!options.responseType) { this.responseType = options.responseType; @@ -478,6 +491,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; body?: T | null; method?: string; @@ -491,6 +505,7 @@ export class HttpRequest { reportProgress?: boolean; params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; + keepalive?: boolean; withCredentials?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; body?: V | null; @@ -507,6 +522,7 @@ export class HttpRequest { params?: HttpParams; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; + keepalive?: boolean; transferCache?: {includeHeaders?: string[]} | boolean; body?: any | null; method?: string; @@ -520,7 +536,7 @@ export class HttpRequest { const method = update.method || this.method; const url = update.url || this.url; const responseType = update.responseType || this.responseType; - + const keepalive = update.keepalive ?? this.keepalive; // Carefully handle the transferCache to differentiate between // `false` and `undefined` in the update args. const transferCache = update.transferCache ?? this.transferCache; @@ -571,6 +587,7 @@ export class HttpRequest { responseType, withCredentials, transferCache, + keepalive, }); } } diff --git a/packages/common/http/src/xhr.ts b/packages/common/http/src/xhr.ts index b431725e019..e6ef8ab0bba 100644 --- a/packages/common/http/src/xhr.ts +++ b/packages/common/http/src/xhr.ts @@ -7,7 +7,11 @@ */ import {XhrFactory} from '../../index'; -import {Injectable, ɵRuntimeError as RuntimeError} from '@angular/core'; +import { + Injectable, + ɵRuntimeError as RuntimeError, + ɵformatRuntimeError as formatRuntimeError, +} from '@angular/core'; import {from, Observable, Observer, of} from 'rxjs'; import {switchMap} from 'rxjs/operators'; @@ -79,6 +83,15 @@ export class HttpXhrBackend implements HttpBackend { ); } + if (req.keepalive && ngDevMode) { + console.warn( + formatRuntimeError( + RuntimeErrorCode.KEEPALIVE_NOT_SUPPORTED_WITH_XHR, + `Angular detected that a \`HttpClient\` request with the \`keepalive\` option was sent using XHR, which does not support it. To use the \`keepalive\` option, enable Fetch API support by passing \`withFetch()\` as an argument to \`provideHttpClient()\`.`, + ), + ); + } + // Check whether this factory has a special function to load an XHR implementation // for various non-browser environments. We currently limit it to only `ServerXhr` // class, which needs to load an XHR implementation. diff --git a/packages/common/http/test/fetch_spec.ts b/packages/common/http/test/fetch_spec.ts index 347eecbb1e4..749ef43dddd 100644 --- a/packages/common/http/test/fetch_spec.ts +++ b/packages/common/http/test/fetch_spec.ts @@ -291,6 +291,20 @@ describe('FetchBackend', async () => { fetchMock.mockAbortEvent(); }); + it('should pass keepalive option to fetch', () => { + const req = new HttpRequest('GET', '/test', {keepalive: true}); + backend.handle(req).subscribe(); + + expect(fetchSpy).toHaveBeenCalledWith( + '/test', + jasmine.objectContaining({ + keepalive: true, + }), + ); + + fetchMock.mockFlush(HttpStatusCode.Ok, 'OK'); + }); + describe('progress events', () => { it('are emitted for download progress', (done) => { backend diff --git a/packages/common/http/test/request_spec.ts b/packages/common/http/test/request_spec.ts index 15a9500e360..c48eaec3ba3 100644 --- a/packages/common/http/test/request_spec.ts +++ b/packages/common/http/test/request_spec.ts @@ -64,6 +64,13 @@ describe('HttpRequest', () => { const req = new HttpRequest('GET', TEST_URL); expect(req.responseType).toBe('json'); }); + it('should allow setting keepalive option', () => { + const req = new HttpRequest('GET', '/test', {keepalive: true}); + expect(req.keepalive).toBe(true); + + const req2 = new HttpRequest('GET', '/test', {keepalive: false}); + expect(req2.keepalive).toBe(false); + }); }); describe('clone() copies the request', () => { const headers = new HttpHeaders({ @@ -77,6 +84,7 @@ describe('HttpRequest', () => { responseType: 'text', withCredentials: true, transferCache: true, + keepalive: true, }); it('in the base case', () => { const clone = req.clone(); @@ -89,6 +97,7 @@ describe('HttpRequest', () => { expect(clone.context).toBe(context); expect(clone.transferCache).toBe(true); + expect(clone.keepalive).toBe(true); }); it('and updates the url', () => { expect(req.clone({url: '/changed'}).url).toBe('/changed'); @@ -106,6 +115,9 @@ describe('HttpRequest', () => { it('and updates the transferCache', () => { expect(req.clone({transferCache: false}).transferCache).toBe(false); }); + it('and updates the keepalive', () => { + expect(req.clone({keepalive: false}).keepalive).toBe(false); + }); }); describe('content type detection', () => { const baseReq = new HttpRequest('POST', '/test', null);