UNPKG

@angular/common

Version:

Angular - commonly needed directives and services

1,538 lines (1,526 loc) 69.3 kB
/** * @license Angular v21.0.6 * (c) 2010-2025 Google LLC. https://angular.dev/ * License: MIT */ import * as i0 from '@angular/core'; import { ɵRuntimeError as _RuntimeError, InjectionToken, inject, NgZone, DestroyRef, Injectable, ɵformatRuntimeError as _formatRuntimeError, ɵTracingService as _TracingService, runInInjectionContext, PendingTasks, ɵConsole as _Console, DOCUMENT, Inject, EnvironmentInjector, makeEnvironmentProviders, NgModule } from '@angular/core'; import { switchMap, finalize, concatMap, filter, map } from 'rxjs/operators'; import { Observable, from, of } from 'rxjs'; import { XhrFactory, parseCookieValue } from './_xhr-chunk.mjs'; import { PlatformLocation } from './_platform_location-chunk.mjs'; class HttpHeaders { headers; normalizedNames = new Map(); lazyInit; lazyUpdate = null; constructor(headers) { if (!headers) { this.headers = new Map(); } else if (typeof headers === 'string') { this.lazyInit = () => { this.headers = new Map(); headers.split('\n').forEach(line => { const index = line.indexOf(':'); if (index > 0) { const name = line.slice(0, index); const value = line.slice(index + 1).trim(); this.addHeaderEntry(name, value); } }); }; } else if (typeof Headers !== 'undefined' && headers instanceof Headers) { this.headers = new Map(); headers.forEach((value, name) => { this.addHeaderEntry(name, value); }); } else { this.lazyInit = () => { if (typeof ngDevMode === 'undefined' || ngDevMode) { assertValidHeaders(headers); } this.headers = new Map(); Object.entries(headers).forEach(([name, values]) => { this.setHeaderEntries(name, values); }); }; } } has(name) { this.init(); return this.headers.has(name.toLowerCase()); } get(name) { this.init(); const values = this.headers.get(name.toLowerCase()); return values && values.length > 0 ? values[0] : null; } keys() { this.init(); return Array.from(this.normalizedNames.values()); } getAll(name) { this.init(); return this.headers.get(name.toLowerCase()) || null; } append(name, value) { return this.clone({ name, value, op: 'a' }); } set(name, value) { return this.clone({ name, value, op: 's' }); } delete(name, value) { return this.clone({ name, value, op: 'd' }); } maybeSetNormalizedName(name, lcName) { if (!this.normalizedNames.has(lcName)) { this.normalizedNames.set(lcName, name); } } init() { if (!!this.lazyInit) { if (this.lazyInit instanceof HttpHeaders) { this.copyFrom(this.lazyInit); } else { this.lazyInit(); } this.lazyInit = null; if (!!this.lazyUpdate) { this.lazyUpdate.forEach(update => this.applyUpdate(update)); this.lazyUpdate = null; } } } copyFrom(other) { other.init(); Array.from(other.headers.keys()).forEach(key => { this.headers.set(key, other.headers.get(key)); this.normalizedNames.set(key, other.normalizedNames.get(key)); }); } clone(update) { const clone = new HttpHeaders(); clone.lazyInit = !!this.lazyInit && this.lazyInit instanceof HttpHeaders ? this.lazyInit : this; clone.lazyUpdate = (this.lazyUpdate || []).concat([update]); return clone; } applyUpdate(update) { const key = update.name.toLowerCase(); switch (update.op) { case 'a': case 's': let value = update.value; if (typeof value === 'string') { value = [value]; } if (value.length === 0) { return; } this.maybeSetNormalizedName(update.name, key); const base = (update.op === 'a' ? this.headers.get(key) : undefined) || []; base.push(...value); this.headers.set(key, base); break; case 'd': const toDelete = update.value; if (!toDelete) { this.headers.delete(key); this.normalizedNames.delete(key); } else { let existing = this.headers.get(key); if (!existing) { return; } existing = existing.filter(value => toDelete.indexOf(value) === -1); if (existing.length === 0) { this.headers.delete(key); this.normalizedNames.delete(key); } else { this.headers.set(key, existing); } } break; } } addHeaderEntry(name, value) { const key = name.toLowerCase(); this.maybeSetNormalizedName(name, key); if (this.headers.has(key)) { this.headers.get(key).push(value); } else { this.headers.set(key, [value]); } } setHeaderEntries(name, values) { const headerValues = (Array.isArray(values) ? values : [values]).map(value => value.toString()); const key = name.toLowerCase(); this.headers.set(key, headerValues); this.maybeSetNormalizedName(name, key); } forEach(fn) { this.init(); Array.from(this.normalizedNames.keys()).forEach(key => fn(this.normalizedNames.get(key), this.headers.get(key))); } } function assertValidHeaders(headers) { for (const [key, value] of Object.entries(headers)) { if (!(typeof value === 'string' || typeof value === 'number') && !Array.isArray(value)) { throw new Error(`Unexpected value of the \`${key}\` header provided. ` + `Expecting either a string, a number or an array, but got: \`${value}\`.`); } } } class HttpContextToken { defaultValue; constructor(defaultValue) { this.defaultValue = defaultValue; } } class HttpContext { map = new Map(); set(token, value) { this.map.set(token, value); return this; } get(token) { if (!this.map.has(token)) { this.map.set(token, token.defaultValue()); } return this.map.get(token); } delete(token) { this.map.delete(token); return this; } has(token) { return this.map.has(token); } keys() { return this.map.keys(); } } class HttpUrlEncodingCodec { encodeKey(key) { return standardEncoding(key); } encodeValue(value) { return standardEncoding(value); } decodeKey(key) { return decodeURIComponent(key); } decodeValue(value) { return decodeURIComponent(value); } } function paramParser(rawParams, codec) { const map = new Map(); if (rawParams.length > 0) { const params = rawParams.replace(/^\?/, '').split('&'); params.forEach(param => { const eqIdx = param.indexOf('='); const [key, val] = eqIdx == -1 ? [codec.decodeKey(param), ''] : [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))]; const list = map.get(key) || []; list.push(val); map.set(key, list); }); } return map; } const STANDARD_ENCODING_REGEX = /%(\d[a-f0-9])/gi; const STANDARD_ENCODING_REPLACEMENTS = { '40': '@', '3A': ':', '24': '$', '2C': ',', '3B': ';', '3D': '=', '3F': '?', '2F': '/' }; function standardEncoding(v) { return encodeURIComponent(v).replace(STANDARD_ENCODING_REGEX, (s, t) => STANDARD_ENCODING_REPLACEMENTS[t] ?? s); } function valueToString(value) { return `${value}`; } class HttpParams { map; encoder; updates = null; cloneFrom = null; constructor(options = {}) { this.encoder = options.encoder || new HttpUrlEncodingCodec(); if (options.fromString) { if (options.fromObject) { throw new _RuntimeError(2805, ngDevMode && 'Cannot specify both fromString and fromObject.'); } this.map = paramParser(options.fromString, this.encoder); } else if (!!options.fromObject) { this.map = new Map(); Object.keys(options.fromObject).forEach(key => { const value = options.fromObject[key]; const values = Array.isArray(value) ? value.map(valueToString) : [valueToString(value)]; this.map.set(key, values); }); } else { this.map = null; } } has(param) { this.init(); return this.map.has(param); } get(param) { this.init(); const res = this.map.get(param); return !!res ? res[0] : null; } getAll(param) { this.init(); return this.map.get(param) || null; } keys() { this.init(); return Array.from(this.map.keys()); } append(param, value) { return this.clone({ param, value, op: 'a' }); } appendAll(params) { const updates = []; Object.keys(params).forEach(param => { const value = params[param]; if (Array.isArray(value)) { value.forEach(_value => { updates.push({ param, value: _value, op: 'a' }); }); } else { updates.push({ param, value: value, op: 'a' }); } }); return this.clone(updates); } set(param, value) { return this.clone({ param, value, op: 's' }); } delete(param, value) { return this.clone({ param, value, op: 'd' }); } toString() { this.init(); return this.keys().map(key => { const eKey = this.encoder.encodeKey(key); return this.map.get(key).map(value => eKey + '=' + this.encoder.encodeValue(value)).join('&'); }).filter(param => param !== '').join('&'); } clone(update) { const clone = new HttpParams({ encoder: this.encoder }); clone.cloneFrom = this.cloneFrom || this; clone.updates = (this.updates || []).concat(update); return clone; } init() { if (this.map === null) { this.map = new Map(); } if (this.cloneFrom !== null) { this.cloneFrom.init(); this.cloneFrom.keys().forEach(key => this.map.set(key, this.cloneFrom.map.get(key))); this.updates.forEach(update => { switch (update.op) { case 'a': case 's': const base = (update.op === 'a' ? this.map.get(update.param) : undefined) || []; base.push(valueToString(update.value)); this.map.set(update.param, base); break; case 'd': if (update.value !== undefined) { let base = this.map.get(update.param) || []; const idx = base.indexOf(valueToString(update.value)); if (idx !== -1) { base.splice(idx, 1); } if (base.length > 0) { this.map.set(update.param, base); } else { this.map.delete(update.param); } } else { this.map.delete(update.param); break; } } }); this.cloneFrom = this.updates = null; } } } function mightHaveBody(method) { switch (method) { case 'DELETE': case 'GET': case 'HEAD': case 'OPTIONS': case 'JSONP': return false; default: return true; } } function isArrayBuffer(value) { return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer; } function isBlob(value) { return typeof Blob !== 'undefined' && value instanceof Blob; } function isFormData(value) { return typeof FormData !== 'undefined' && value instanceof FormData; } function isUrlSearchParams(value) { return typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams; } const CONTENT_TYPE_HEADER = 'Content-Type'; const ACCEPT_HEADER = 'Accept'; const TEXT_CONTENT_TYPE = 'text/plain'; const JSON_CONTENT_TYPE = 'application/json'; const ACCEPT_HEADER_VALUE = `${JSON_CONTENT_TYPE}, ${TEXT_CONTENT_TYPE}, */*`; class HttpRequest { url; body = null; headers; context; reportProgress = false; withCredentials = false; credentials; keepalive = false; cache; priority; mode; redirect; referrer; integrity; referrerPolicy; responseType = 'json'; method; params; urlWithParams; transferCache; timeout; constructor(method, url, third, fourth) { this.url = url; this.method = method.toUpperCase(); let options; if (mightHaveBody(this.method) || !!fourth) { this.body = third !== undefined ? third : null; options = fourth; } else { options = third; } if (options) { this.reportProgress = !!options.reportProgress; this.withCredentials = !!options.withCredentials; this.keepalive = !!options.keepalive; if (!!options.responseType) { this.responseType = options.responseType; } if (options.headers) { this.headers = options.headers; } if (options.context) { this.context = options.context; } if (options.params) { this.params = options.params; } if (options.priority) { this.priority = options.priority; } if (options.cache) { this.cache = options.cache; } if (options.credentials) { this.credentials = options.credentials; } if (typeof options.timeout === 'number') { if (options.timeout < 1 || !Number.isInteger(options.timeout)) { throw new _RuntimeError(2822, ngDevMode ? '`timeout` must be a positive integer value' : ''); } this.timeout = options.timeout; } if (options.mode) { this.mode = options.mode; } if (options.redirect) { this.redirect = options.redirect; } if (options.integrity) { this.integrity = options.integrity; } if (options.referrer) { this.referrer = options.referrer; } if (options.referrerPolicy) { this.referrerPolicy = options.referrerPolicy; } this.transferCache = options.transferCache; } this.headers ??= new HttpHeaders(); this.context ??= new HttpContext(); if (!this.params) { this.params = new HttpParams(); this.urlWithParams = url; } else { const params = this.params.toString(); if (params.length === 0) { this.urlWithParams = url; } else { const qIdx = url.indexOf('?'); const sep = qIdx === -1 ? '?' : qIdx < url.length - 1 ? '&' : ''; this.urlWithParams = url + sep + params; } } } serializeBody() { if (this.body === null) { return null; } if (typeof this.body === 'string' || isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) || isUrlSearchParams(this.body)) { return this.body; } if (this.body instanceof HttpParams) { return this.body.toString(); } if (typeof this.body === 'object' || typeof this.body === 'boolean' || Array.isArray(this.body)) { return JSON.stringify(this.body); } return this.body.toString(); } detectContentTypeHeader() { if (this.body === null) { return null; } if (isFormData(this.body)) { return null; } if (isBlob(this.body)) { return this.body.type || null; } if (isArrayBuffer(this.body)) { return null; } if (typeof this.body === 'string') { return TEXT_CONTENT_TYPE; } if (this.body instanceof HttpParams) { return 'application/x-www-form-urlencoded;charset=UTF-8'; } if (typeof this.body === 'object' || typeof this.body === 'number' || typeof this.body === 'boolean') { return JSON_CONTENT_TYPE; } return null; } clone(update = {}) { const method = update.method || this.method; const url = update.url || this.url; const responseType = update.responseType || this.responseType; const keepalive = update.keepalive ?? this.keepalive; const priority = update.priority || this.priority; const cache = update.cache || this.cache; const mode = update.mode || this.mode; const redirect = update.redirect || this.redirect; const credentials = update.credentials || this.credentials; const referrer = update.referrer || this.referrer; const integrity = update.integrity || this.integrity; const referrerPolicy = update.referrerPolicy || this.referrerPolicy; const transferCache = update.transferCache ?? this.transferCache; const timeout = update.timeout ?? this.timeout; const body = update.body !== undefined ? update.body : this.body; const withCredentials = update.withCredentials ?? this.withCredentials; const reportProgress = update.reportProgress ?? this.reportProgress; let headers = update.headers || this.headers; let params = update.params || this.params; const context = update.context ?? this.context; if (update.setHeaders !== undefined) { headers = Object.keys(update.setHeaders).reduce((headers, name) => headers.set(name, update.setHeaders[name]), headers); } if (update.setParams) { params = Object.keys(update.setParams).reduce((params, param) => params.set(param, update.setParams[param]), params); } return new HttpRequest(method, url, body, { params, headers, context, reportProgress, responseType, withCredentials, transferCache, keepalive, cache, priority, timeout, mode, redirect, credentials, referrer, integrity, referrerPolicy }); } } var HttpEventType; (function (HttpEventType) { HttpEventType[HttpEventType["Sent"] = 0] = "Sent"; HttpEventType[HttpEventType["UploadProgress"] = 1] = "UploadProgress"; HttpEventType[HttpEventType["ResponseHeader"] = 2] = "ResponseHeader"; HttpEventType[HttpEventType["DownloadProgress"] = 3] = "DownloadProgress"; HttpEventType[HttpEventType["Response"] = 4] = "Response"; HttpEventType[HttpEventType["User"] = 5] = "User"; })(HttpEventType || (HttpEventType = {})); class HttpResponseBase { headers; status; statusText; url; ok; type; redirected; responseType; constructor(init, defaultStatus = 200, defaultStatusText = 'OK') { this.headers = init.headers || new HttpHeaders(); this.status = init.status !== undefined ? init.status : defaultStatus; this.statusText = init.statusText || defaultStatusText; this.url = init.url || null; this.redirected = init.redirected; this.responseType = init.responseType; this.ok = this.status >= 200 && this.status < 300; } } class HttpHeaderResponse extends HttpResponseBase { constructor(init = {}) { super(init); } type = HttpEventType.ResponseHeader; clone(update = {}) { return new HttpHeaderResponse({ headers: update.headers || this.headers, status: update.status !== undefined ? update.status : this.status, statusText: update.statusText || this.statusText, url: update.url || this.url || undefined }); } } class HttpResponse extends HttpResponseBase { body; constructor(init = {}) { super(init); this.body = init.body !== undefined ? init.body : null; } type = HttpEventType.Response; clone(update = {}) { return new HttpResponse({ body: update.body !== undefined ? update.body : this.body, headers: update.headers || this.headers, status: update.status !== undefined ? update.status : this.status, statusText: update.statusText || this.statusText, url: update.url || this.url || undefined, redirected: update.redirected ?? this.redirected, responseType: update.responseType ?? this.responseType }); } } class HttpErrorResponse extends HttpResponseBase { name = 'HttpErrorResponse'; message; error; ok = false; constructor(init) { super(init, 0, 'Unknown Error'); if (this.status >= 200 && this.status < 300) { this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`; } else { this.message = `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${init.statusText}`; } this.error = init.error || null; } } const HTTP_STATUS_CODE_OK = 200; const HTTP_STATUS_CODE_NO_CONTENT = 204; var HttpStatusCode; (function (HttpStatusCode) { HttpStatusCode[HttpStatusCode["Continue"] = 100] = "Continue"; HttpStatusCode[HttpStatusCode["SwitchingProtocols"] = 101] = "SwitchingProtocols"; HttpStatusCode[HttpStatusCode["Processing"] = 102] = "Processing"; HttpStatusCode[HttpStatusCode["EarlyHints"] = 103] = "EarlyHints"; HttpStatusCode[HttpStatusCode["Ok"] = 200] = "Ok"; HttpStatusCode[HttpStatusCode["Created"] = 201] = "Created"; HttpStatusCode[HttpStatusCode["Accepted"] = 202] = "Accepted"; HttpStatusCode[HttpStatusCode["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation"; HttpStatusCode[HttpStatusCode["NoContent"] = 204] = "NoContent"; HttpStatusCode[HttpStatusCode["ResetContent"] = 205] = "ResetContent"; HttpStatusCode[HttpStatusCode["PartialContent"] = 206] = "PartialContent"; HttpStatusCode[HttpStatusCode["MultiStatus"] = 207] = "MultiStatus"; HttpStatusCode[HttpStatusCode["AlreadyReported"] = 208] = "AlreadyReported"; HttpStatusCode[HttpStatusCode["ImUsed"] = 226] = "ImUsed"; HttpStatusCode[HttpStatusCode["MultipleChoices"] = 300] = "MultipleChoices"; HttpStatusCode[HttpStatusCode["MovedPermanently"] = 301] = "MovedPermanently"; HttpStatusCode[HttpStatusCode["Found"] = 302] = "Found"; HttpStatusCode[HttpStatusCode["SeeOther"] = 303] = "SeeOther"; HttpStatusCode[HttpStatusCode["NotModified"] = 304] = "NotModified"; HttpStatusCode[HttpStatusCode["UseProxy"] = 305] = "UseProxy"; HttpStatusCode[HttpStatusCode["Unused"] = 306] = "Unused"; HttpStatusCode[HttpStatusCode["TemporaryRedirect"] = 307] = "TemporaryRedirect"; HttpStatusCode[HttpStatusCode["PermanentRedirect"] = 308] = "PermanentRedirect"; HttpStatusCode[HttpStatusCode["BadRequest"] = 400] = "BadRequest"; HttpStatusCode[HttpStatusCode["Unauthorized"] = 401] = "Unauthorized"; HttpStatusCode[HttpStatusCode["PaymentRequired"] = 402] = "PaymentRequired"; HttpStatusCode[HttpStatusCode["Forbidden"] = 403] = "Forbidden"; HttpStatusCode[HttpStatusCode["NotFound"] = 404] = "NotFound"; HttpStatusCode[HttpStatusCode["MethodNotAllowed"] = 405] = "MethodNotAllowed"; HttpStatusCode[HttpStatusCode["NotAcceptable"] = 406] = "NotAcceptable"; HttpStatusCode[HttpStatusCode["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; HttpStatusCode[HttpStatusCode["RequestTimeout"] = 408] = "RequestTimeout"; HttpStatusCode[HttpStatusCode["Conflict"] = 409] = "Conflict"; HttpStatusCode[HttpStatusCode["Gone"] = 410] = "Gone"; HttpStatusCode[HttpStatusCode["LengthRequired"] = 411] = "LengthRequired"; HttpStatusCode[HttpStatusCode["PreconditionFailed"] = 412] = "PreconditionFailed"; HttpStatusCode[HttpStatusCode["PayloadTooLarge"] = 413] = "PayloadTooLarge"; HttpStatusCode[HttpStatusCode["UriTooLong"] = 414] = "UriTooLong"; HttpStatusCode[HttpStatusCode["UnsupportedMediaType"] = 415] = "UnsupportedMediaType"; HttpStatusCode[HttpStatusCode["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable"; HttpStatusCode[HttpStatusCode["ExpectationFailed"] = 417] = "ExpectationFailed"; HttpStatusCode[HttpStatusCode["ImATeapot"] = 418] = "ImATeapot"; HttpStatusCode[HttpStatusCode["MisdirectedRequest"] = 421] = "MisdirectedRequest"; HttpStatusCode[HttpStatusCode["UnprocessableEntity"] = 422] = "UnprocessableEntity"; HttpStatusCode[HttpStatusCode["Locked"] = 423] = "Locked"; HttpStatusCode[HttpStatusCode["FailedDependency"] = 424] = "FailedDependency"; HttpStatusCode[HttpStatusCode["TooEarly"] = 425] = "TooEarly"; HttpStatusCode[HttpStatusCode["UpgradeRequired"] = 426] = "UpgradeRequired"; HttpStatusCode[HttpStatusCode["PreconditionRequired"] = 428] = "PreconditionRequired"; HttpStatusCode[HttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests"; HttpStatusCode[HttpStatusCode["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge"; HttpStatusCode[HttpStatusCode["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons"; HttpStatusCode[HttpStatusCode["InternalServerError"] = 500] = "InternalServerError"; HttpStatusCode[HttpStatusCode["NotImplemented"] = 501] = "NotImplemented"; HttpStatusCode[HttpStatusCode["BadGateway"] = 502] = "BadGateway"; HttpStatusCode[HttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable"; HttpStatusCode[HttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout"; HttpStatusCode[HttpStatusCode["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported"; HttpStatusCode[HttpStatusCode["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates"; HttpStatusCode[HttpStatusCode["InsufficientStorage"] = 507] = "InsufficientStorage"; HttpStatusCode[HttpStatusCode["LoopDetected"] = 508] = "LoopDetected"; HttpStatusCode[HttpStatusCode["NotExtended"] = 510] = "NotExtended"; HttpStatusCode[HttpStatusCode["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired"; })(HttpStatusCode || (HttpStatusCode = {})); const XSSI_PREFIX$1 = /^\)\]\}',?\n/; const FETCH_BACKEND = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'FETCH_BACKEND' : ''); class FetchBackend { fetchImpl = inject(FetchFactory, { optional: true })?.fetch ?? ((...args) => globalThis.fetch(...args)); ngZone = inject(NgZone); destroyRef = inject(DestroyRef); handle(request) { return new Observable(observer => { const aborter = new AbortController(); this.doRequest(request, aborter.signal, observer).then(noop, error => observer.error(new HttpErrorResponse({ error }))); let timeoutId; if (request.timeout) { timeoutId = this.ngZone.runOutsideAngular(() => setTimeout(() => { if (!aborter.signal.aborted) { aborter.abort(new DOMException('signal timed out', 'TimeoutError')); } }, request.timeout)); } return () => { if (timeoutId !== undefined) { clearTimeout(timeoutId); } aborter.abort(); }; }); } async doRequest(request, signal, observer) { const init = this.createRequestInit(request); let response; try { const fetchPromise = this.ngZone.runOutsideAngular(() => this.fetchImpl(request.urlWithParams, { signal, ...init })); silenceSuperfluousUnhandledPromiseRejection(fetchPromise); observer.next({ type: HttpEventType.Sent }); response = await fetchPromise; } catch (error) { observer.error(new HttpErrorResponse({ error, status: error.status ?? 0, statusText: error.statusText, url: request.urlWithParams, headers: error.headers })); return; } const headers = new HttpHeaders(response.headers); const statusText = response.statusText; const url = response.url || request.urlWithParams; let status = response.status; let body = null; if (request.reportProgress) { observer.next(new HttpHeaderResponse({ headers, status, statusText, url })); } if (response.body) { const contentLength = response.headers.get('content-length'); const chunks = []; const reader = response.body.getReader(); let receivedLength = 0; let decoder; let partialText; const reqZone = typeof Zone !== 'undefined' && Zone.current; let canceled = false; await this.ngZone.runOutsideAngular(async () => { while (true) { if (this.destroyRef.destroyed) { await reader.cancel(); canceled = true; break; } const { done, value } = await reader.read(); if (done) { break; } chunks.push(value); receivedLength += value.length; if (request.reportProgress) { partialText = request.responseType === 'text' ? (partialText ?? '') + (decoder ??= new TextDecoder()).decode(value, { stream: true }) : undefined; const reportProgress = () => observer.next({ type: HttpEventType.DownloadProgress, total: contentLength ? +contentLength : undefined, loaded: receivedLength, partialText }); reqZone ? reqZone.run(reportProgress) : reportProgress(); } } }); if (canceled) { observer.complete(); return; } const chunksAll = this.concatChunks(chunks, receivedLength); try { const contentType = response.headers.get(CONTENT_TYPE_HEADER) ?? ''; body = this.parseBody(request, chunksAll, contentType, status); } catch (error) { observer.error(new HttpErrorResponse({ error, headers: new HttpHeaders(response.headers), status: response.status, statusText: response.statusText, url: response.url || request.urlWithParams })); return; } } if (status === 0) { status = body ? HTTP_STATUS_CODE_OK : 0; } const ok = status >= 200 && status < 300; const redirected = response.redirected; const responseType = response.type; if (ok) { observer.next(new HttpResponse({ body, headers, status, statusText, url, redirected, responseType })); observer.complete(); } else { observer.error(new HttpErrorResponse({ error: body, headers, status, statusText, url, redirected, responseType })); } } parseBody(request, binContent, contentType, status) { switch (request.responseType) { case 'json': const text = new TextDecoder().decode(binContent).replace(XSSI_PREFIX$1, ''); if (text === '') { return null; } try { return JSON.parse(text); } catch (e) { if (status < 200 || status >= 300) { return text; } throw e; } case 'text': return new TextDecoder().decode(binContent); case 'blob': return new Blob([binContent], { type: contentType }); case 'arraybuffer': return binContent.buffer; } } createRequestInit(req) { const headers = {}; let credentials; credentials = req.credentials; if (req.withCredentials) { (typeof ngDevMode === 'undefined' || ngDevMode) && warningOptionsMessage(req); credentials = 'include'; } req.headers.forEach((name, values) => headers[name] = values.join(',')); if (!req.headers.has(ACCEPT_HEADER)) { headers[ACCEPT_HEADER] = ACCEPT_HEADER_VALUE; } if (!req.headers.has(CONTENT_TYPE_HEADER)) { const detectedType = req.detectContentTypeHeader(); if (detectedType !== null) { headers[CONTENT_TYPE_HEADER] = detectedType; } } return { body: req.serializeBody(), method: req.method, headers, credentials, keepalive: req.keepalive, cache: req.cache, priority: req.priority, mode: req.mode, redirect: req.redirect, referrer: req.referrer, integrity: req.integrity, referrerPolicy: req.referrerPolicy }; } concatChunks(chunks, totalLength) { const chunksAll = new Uint8Array(totalLength); let position = 0; for (const chunk of chunks) { chunksAll.set(chunk, position); position += chunk.length; } return chunksAll; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FetchBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FetchBackend }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: FetchBackend, decorators: [{ type: Injectable }] }); class FetchFactory {} function noop() {} function warningOptionsMessage(req) { if (req.credentials && req.withCredentials) { console.warn(_formatRuntimeError(2819, `Angular detected that a \`HttpClient\` request has both \`withCredentials: true\` and \`credentials: '${req.credentials}'\` options. The \`withCredentials\` option is overriding the explicit \`credentials\` setting to 'include'. Consider removing \`withCredentials\` and using \`credentials: '${req.credentials}'\` directly for clarity.`)); } } function silenceSuperfluousUnhandledPromiseRejection(promise) { promise.then(noop, noop); } const XSSI_PREFIX = /^\)\]\}',?\n/; function validateXhrCompatibility(req) { const unsupportedOptions = [{ property: 'keepalive', errorCode: 2813 }, { property: 'cache', errorCode: 2814 }, { property: 'priority', errorCode: 2815 }, { property: 'mode', errorCode: 2816 }, { property: 'redirect', errorCode: 2817 }, { property: 'credentials', errorCode: 2818 }, { property: 'integrity', errorCode: 2820 }, { property: 'referrer', errorCode: 2821 }, { property: 'referrerPolicy', errorCode: 2823 }]; for (const { property, errorCode } of unsupportedOptions) { if (req[property]) { console.warn(_formatRuntimeError(errorCode, `Angular detected that a \`HttpClient\` request with the \`${property}\` option was sent using XHR, which does not support it. To use the \`${property}\` option, enable Fetch API support by passing \`withFetch()\` as an argument to \`provideHttpClient()\`.`)); } } } class HttpXhrBackend { xhrFactory; tracingService = inject(_TracingService, { optional: true }); constructor(xhrFactory) { this.xhrFactory = xhrFactory; } maybePropagateTrace(fn) { return this.tracingService?.propagate ? this.tracingService.propagate(fn) : fn; } handle(req) { if (req.method === 'JSONP') { throw new _RuntimeError(-2800, (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot make a JSONP request without JSONP support. To fix the problem, either add the \`withJsonpSupport()\` call (if \`provideHttpClient()\` is used) or import the \`HttpClientJsonpModule\` in the root NgModule.`); } ngDevMode && validateXhrCompatibility(req); const xhrFactory = this.xhrFactory; const source = typeof ngServerMode !== 'undefined' && ngServerMode && xhrFactory.ɵloadImpl ? from(xhrFactory.ɵloadImpl()) : of(null); return source.pipe(switchMap(() => { return new Observable(observer => { const xhr = xhrFactory.build(); xhr.open(req.method, req.urlWithParams); if (req.withCredentials) { xhr.withCredentials = true; } req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(','))); if (!req.headers.has(ACCEPT_HEADER)) { xhr.setRequestHeader(ACCEPT_HEADER, ACCEPT_HEADER_VALUE); } if (!req.headers.has(CONTENT_TYPE_HEADER)) { const detectedType = req.detectContentTypeHeader(); if (detectedType !== null) { xhr.setRequestHeader(CONTENT_TYPE_HEADER, detectedType); } } if (req.timeout) { xhr.timeout = req.timeout; } if (req.responseType) { const responseType = req.responseType.toLowerCase(); xhr.responseType = responseType !== 'json' ? responseType : 'text'; } const reqBody = req.serializeBody(); let headerResponse = null; const partialFromXhr = () => { if (headerResponse !== null) { return headerResponse; } const statusText = xhr.statusText || 'OK'; const headers = new HttpHeaders(xhr.getAllResponseHeaders()); const url = xhr.responseURL || req.url; headerResponse = new HttpHeaderResponse({ headers, status: xhr.status, statusText, url }); return headerResponse; }; const onLoad = this.maybePropagateTrace(() => { let { headers, status, statusText, url } = partialFromXhr(); let body = null; if (status !== HTTP_STATUS_CODE_NO_CONTENT) { body = typeof xhr.response === 'undefined' ? xhr.responseText : xhr.response; } if (status === 0) { status = !!body ? HTTP_STATUS_CODE_OK : 0; } let ok = status >= 200 && status < 300; if (req.responseType === 'json' && typeof body === 'string') { const originalBody = body; body = body.replace(XSSI_PREFIX, ''); try { body = body !== '' ? JSON.parse(body) : null; } catch (error) { body = originalBody; if (ok) { ok = false; body = { error, text: body }; } } } if (ok) { observer.next(new HttpResponse({ body, headers, status, statusText, url: url || undefined })); observer.complete(); } else { observer.error(new HttpErrorResponse({ error: body, headers, status, statusText, url: url || undefined })); } }); const onError = this.maybePropagateTrace(error => { const { url } = partialFromXhr(); const res = new HttpErrorResponse({ error, status: xhr.status || 0, statusText: xhr.statusText || 'Unknown Error', url: url || undefined }); observer.error(res); }); let onTimeout = onError; if (req.timeout) { onTimeout = this.maybePropagateTrace(_ => { const { url } = partialFromXhr(); const res = new HttpErrorResponse({ error: new DOMException('Request timed out', 'TimeoutError'), status: xhr.status || 0, statusText: xhr.statusText || 'Request timeout', url: url || undefined }); observer.error(res); }); } let sentHeaders = false; const onDownProgress = this.maybePropagateTrace(event => { if (!sentHeaders) { observer.next(partialFromXhr()); sentHeaders = true; } let progressEvent = { type: HttpEventType.DownloadProgress, loaded: event.loaded }; if (event.lengthComputable) { progressEvent.total = event.total; } if (req.responseType === 'text' && !!xhr.responseText) { progressEvent.partialText = xhr.responseText; } observer.next(progressEvent); }); const onUpProgress = this.maybePropagateTrace(event => { let progress = { type: HttpEventType.UploadProgress, loaded: event.loaded }; if (event.lengthComputable) { progress.total = event.total; } observer.next(progress); }); xhr.addEventListener('load', onLoad); xhr.addEventListener('error', onError); xhr.addEventListener('timeout', onTimeout); xhr.addEventListener('abort', onError); if (req.reportProgress) { xhr.addEventListener('progress', onDownProgress); if (reqBody !== null && xhr.upload) { xhr.upload.addEventListener('progress', onUpProgress); } } xhr.send(reqBody); observer.next({ type: HttpEventType.Sent }); return () => { xhr.removeEventListener('error', onError); xhr.removeEventListener('abort', onError); xhr.removeEventListener('load', onLoad); xhr.removeEventListener('timeout', onTimeout); if (req.reportProgress) { xhr.removeEventListener('progress', onDownProgress); if (reqBody !== null && xhr.upload) { xhr.upload.removeEventListener('progress', onUpProgress); } } if (xhr.readyState !== xhr.DONE) { xhr.abort(); } }; }); })); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpXhrBackend, deps: [{ token: XhrFactory }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpXhrBackend, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpXhrBackend, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: XhrFactory }] }); function interceptorChainEndFn(req, finalHandlerFn) { return finalHandlerFn(req); } function adaptLegacyInterceptorToChain(chainTailFn, interceptor) { return (initialRequest, finalHandlerFn) => interceptor.intercept(initialRequest, { handle: downstreamRequest => chainTailFn(downstreamRequest, finalHandlerFn) }); } function chainedInterceptorFn(chainTailFn, interceptorFn, injector) { return (initialRequest, finalHandlerFn) => runInInjectionContext(injector, () => interceptorFn(initialRequest, downstreamRequest => chainTailFn(downstreamRequest, finalHandlerFn))); } const HTTP_INTERCEPTORS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'HTTP_INTERCEPTORS' : ''); const HTTP_INTERCEPTOR_FNS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'HTTP_INTERCEPTOR_FNS' : '', { factory: () => [] }); const HTTP_ROOT_INTERCEPTOR_FNS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'HTTP_ROOT_INTERCEPTOR_FNS' : ''); const REQUESTS_CONTRIBUTE_TO_STABILITY = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'REQUESTS_CONTRIBUTE_TO_STABILITY' : '', { factory: () => true }); function legacyInterceptorFnFactory() { let chain = null; return (req, handler) => { if (chain === null) { const interceptors = inject(HTTP_INTERCEPTORS, { optional: true }) ?? []; chain = interceptors.reduceRight(adaptLegacyInterceptorToChain, interceptorChainEndFn); } const pendingTasks = inject(PendingTasks); const contributeToStability = inject(REQUESTS_CONTRIBUTE_TO_STABILITY); if (contributeToStability) { const removeTask = pendingTasks.add(); return chain(req, handler).pipe(finalize(removeTask)); } else { return chain(req, handler); } }; } class HttpBackend { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpBackend, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpBackend, providedIn: 'root', useExisting: HttpXhrBackend }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpBackend, decorators: [{ type: Injectable, args: [{ providedIn: 'root', useExisting: HttpXhrBackend }] }] }); let fetchBackendWarningDisplayed = false; class HttpInterceptorHandler { backend; injector; chain = null; pendingTasks = inject(PendingTasks); contributeToStability = inject(REQUESTS_CONTRIBUTE_TO_STABILITY); constructor(backend, injector) { this.backend = backend; this.injector = injector; if ((typeof ngDevMode === 'undefined' || ngDevMode) && !fetchBackendWarningDisplayed) { const isTestingBackend = this.backend.isTestingBackend; if (typeof ngServerMode !== 'undefined' && ngServerMode && !(this.backend instanceof FetchBackend) && !isTestingBackend) { fetchBackendWarningDisplayed = true; injector.get(_Console).warn(_formatRuntimeError(2801, 'Angular detected that `HttpClient` is not configured ' + "to use `fetch` APIs. It's strongly recommended to " + 'enable `fetch` for applications that use Server-Side Rendering ' + 'for better performance and compatibility. ' + 'To enable `fetch`, add the `withFetch()` to the `provideHttpClient()` ' + 'call at the root of the application.')); } } } handle(initialRequest) { if (this.chain === null) { const dedupedInterceptorFns = Array.from(new Set([...this.injector.get(HTTP_INTERCEPTOR_FNS), ...this.injector.get(HTTP_ROOT_INTERCEPTOR_FNS, [])])); this.chain = dedupedInterceptorFns.reduceRight((nextSequencedFn, interceptorFn) => chainedInterceptorFn(nextSequencedFn, interceptorFn, this.injector), interceptorChainEndFn); } if (this.contributeToStability) { const removeTask = this.pendingTasks.add(); return this.chain(initialRequest, downstreamRequest => this.backend.handle(downstreamRequest)).pipe(finalize(removeTask)); } else { return this.chain(initialRequest, downstreamRequest => this.backend.handle(downstreamRequest)); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpInterceptorHandler, deps: [{ token: HttpBackend }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpInterceptorHandler, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpInterceptorHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: HttpBackend }, { type: i0.EnvironmentInjector }] }); class HttpHandler { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpHandler, providedIn: 'root', useExisting: HttpInterceptorHandler }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: HttpHandler, decorators: [{ type: Injectable, args: [{ providedIn: 'root', useExisting: HttpInterceptorHandler }] }] }); function addBody(options, body) { return { body, headers: options.headers, context: options.context, observe: options.observe, params: options.params, reportProgress: options.reportProgress, responseType: options.responseType, withCredentials: options.withCredentials, credentials: options.credentials, transferCache: options.transferCache, timeout: options.timeout, keepalive: options.keepalive, priority: options.priority, cache: options.cache, mode: options.mode, redirect: options.redirect, integrity: options.integrity, referrer: options.referrer, referrerPolicy: options.referrerPolicy }; } class HttpClient { handler; constructor(handler) { this.handler = handler; } request(first, url, options = {}) { let req; if (first instanceof HttpRequest) { req = first; } else { let headers = undefined; if (options.headers instanceof HttpHeaders) { headers = options.headers; } else { headers = new HttpHeaders(options.headers); } let params = undefined; if (!!options.params) { if (options.params instanceof HttpParams) { params = options.params; } else { params = new HttpParams({ fromObject: options.params }); } } req = new HttpRequest(first, url, options.body !== undefined ? options.body : null, { headers, context: options.context, params, reportProgress: options.reportProgress, responseType: options.responseType || 'json', withCredentials: options.withCredentials, transferCache: options.transferCache, keepalive: options.keepalive, priority: options.priority, cache: options.cache, mode: options.mode, redirect: options.redirect, credentials: options.credentials, referrer: options.referrer, referrerPolicy: options.referrerPolicy, integrity: options.integrity, timeout: options.timeout }); } const events$ = of(req).pipe(concatMap(req => this.handler.handle(req))); if (first instanceof HttpRequest || options.observe === 'events') { return events$; } const res$ = events$.pipe(filter(event => event instanceof HttpResponse)); switch (options.observe || 'body') { case 'body': switch (req.responseType) { case 'arraybuffer': return res$.pipe(map(res => { if (res.body !== null && !(res.body instanceof ArrayBuffer)) { throw new _RuntimeError(2806, ngDevMode && 'Response is not an ArrayBuffer.'); } return res.body; })); case 'blob': return res$.pipe(map(res => { if (res.body !== null && !(res.body instanceof Blob)) { throw new _RuntimeError(2807, ngDevMode && 'Response is not a Blob.'); }