2780 lines
92 KiB
JavaScript
2780 lines
92 KiB
JavaScript
import {
|
|
XhrFactory,
|
|
parseCookieValue
|
|
} from "./chunk-OUSM42MY.js";
|
|
import {
|
|
APP_BOOTSTRAP_LISTENER,
|
|
ApplicationRef,
|
|
DOCUMENT,
|
|
DestroyRef,
|
|
EnvironmentInjector,
|
|
Inject,
|
|
Injectable,
|
|
InjectionToken,
|
|
Injector,
|
|
NgModule,
|
|
NgZone,
|
|
PendingTasks,
|
|
ResourceImpl,
|
|
RuntimeError,
|
|
TransferState,
|
|
assertInInjectionContext,
|
|
computed,
|
|
encapsulateResourceError,
|
|
formatRuntimeError,
|
|
inject,
|
|
linkedSignal,
|
|
makeEnvironmentProviders,
|
|
makeStateKey,
|
|
performanceMarkFeature,
|
|
runInInjectionContext,
|
|
setClassMetadata,
|
|
signal,
|
|
truncateMiddle,
|
|
ɵɵdefineInjectable,
|
|
ɵɵdefineInjector,
|
|
ɵɵdefineNgModule,
|
|
ɵɵinject
|
|
} from "./chunk-FVA7C6JK.js";
|
|
import {
|
|
Observable,
|
|
concatMap,
|
|
filter,
|
|
finalize,
|
|
map,
|
|
of,
|
|
switchMap
|
|
} from "./chunk-MARUHEWW.js";
|
|
import {
|
|
__objRest,
|
|
__spreadValues
|
|
} from "./chunk-GOMI4DH3.js";
|
|
|
|
// node_modules/@angular/common/fesm2022/module.mjs
|
|
var HttpHandler = class {
|
|
};
|
|
var HttpBackend = class {
|
|
};
|
|
var HttpHeaders = class _HttpHeaders {
|
|
/**
|
|
* Internal map of lowercase header names to values.
|
|
*/
|
|
headers;
|
|
/**
|
|
* Internal map of lowercased header names to the normalized
|
|
* form of the name (the form seen first).
|
|
*/
|
|
normalizedNames = /* @__PURE__ */ new Map();
|
|
/**
|
|
* Complete the lazy initialization of this object (needed before reading).
|
|
*/
|
|
lazyInit;
|
|
/**
|
|
* Queued updates to be materialized the next initialization.
|
|
*/
|
|
lazyUpdate = null;
|
|
/** Constructs a new HTTP header object with the given values.*/
|
|
constructor(headers) {
|
|
if (!headers) {
|
|
this.headers = /* @__PURE__ */ new Map();
|
|
} else if (typeof headers === "string") {
|
|
this.lazyInit = () => {
|
|
this.headers = /* @__PURE__ */ 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 = /* @__PURE__ */ new Map();
|
|
headers.forEach((value, name) => {
|
|
this.addHeaderEntry(name, value);
|
|
});
|
|
} else {
|
|
this.lazyInit = () => {
|
|
if (typeof ngDevMode === "undefined" || ngDevMode) {
|
|
assertValidHeaders(headers);
|
|
}
|
|
this.headers = /* @__PURE__ */ new Map();
|
|
Object.entries(headers).forEach(([name, values]) => {
|
|
this.setHeaderEntries(name, values);
|
|
});
|
|
};
|
|
}
|
|
}
|
|
/**
|
|
* Checks for existence of a given header.
|
|
*
|
|
* @param name The header name to check for existence.
|
|
*
|
|
* @returns True if the header exists, false otherwise.
|
|
*/
|
|
has(name) {
|
|
this.init();
|
|
return this.headers.has(name.toLowerCase());
|
|
}
|
|
/**
|
|
* Retrieves the first value of a given header.
|
|
*
|
|
* @param name The header name.
|
|
*
|
|
* @returns The value string if the header exists, null otherwise
|
|
*/
|
|
get(name) {
|
|
this.init();
|
|
const values = this.headers.get(name.toLowerCase());
|
|
return values && values.length > 0 ? values[0] : null;
|
|
}
|
|
/**
|
|
* Retrieves the names of the headers.
|
|
*
|
|
* @returns A list of header names.
|
|
*/
|
|
keys() {
|
|
this.init();
|
|
return Array.from(this.normalizedNames.values());
|
|
}
|
|
/**
|
|
* Retrieves a list of values for a given header.
|
|
*
|
|
* @param name The header name from which to retrieve values.
|
|
*
|
|
* @returns A string of values if the header exists, null otherwise.
|
|
*/
|
|
getAll(name) {
|
|
this.init();
|
|
return this.headers.get(name.toLowerCase()) || null;
|
|
}
|
|
/**
|
|
* Appends a new value to the existing set of values for a header
|
|
* and returns them in a clone of the original instance.
|
|
*
|
|
* @param name The header name for which to append the values.
|
|
* @param value The value to append.
|
|
*
|
|
* @returns A clone of the HTTP headers object with the value appended to the given header.
|
|
*/
|
|
append(name, value) {
|
|
return this.clone({
|
|
name,
|
|
value,
|
|
op: "a"
|
|
});
|
|
}
|
|
/**
|
|
* Sets or modifies a value for a given header in a clone of the original instance.
|
|
* If the header already exists, its value is replaced with the given value
|
|
* in the returned object.
|
|
*
|
|
* @param name The header name.
|
|
* @param value The value or values to set or override for the given header.
|
|
*
|
|
* @returns A clone of the HTTP headers object with the newly set header value.
|
|
*/
|
|
set(name, value) {
|
|
return this.clone({
|
|
name,
|
|
value,
|
|
op: "s"
|
|
});
|
|
}
|
|
/**
|
|
* Deletes values for a given header in a clone of the original instance.
|
|
*
|
|
* @param name The header name.
|
|
* @param value The value or values to delete for the given header.
|
|
*
|
|
* @returns A clone of the HTTP headers object with the given value deleted.
|
|
*/
|
|
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) : void 0) || [];
|
|
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((value2) => toDelete.indexOf(value2) === -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);
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
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}\`.`);
|
|
}
|
|
}
|
|
}
|
|
var HttpUrlEncodingCodec = class {
|
|
/**
|
|
* Encodes a key name for a URL parameter or query-string.
|
|
* @param key The key name.
|
|
* @returns The encoded key name.
|
|
*/
|
|
encodeKey(key) {
|
|
return standardEncoding(key);
|
|
}
|
|
/**
|
|
* Encodes the value of a URL parameter or query-string.
|
|
* @param value The value.
|
|
* @returns The encoded value.
|
|
*/
|
|
encodeValue(value) {
|
|
return standardEncoding(value);
|
|
}
|
|
/**
|
|
* Decodes an encoded URL parameter or query-string key.
|
|
* @param key The encoded key name.
|
|
* @returns The decoded key name.
|
|
*/
|
|
decodeKey(key) {
|
|
return decodeURIComponent(key);
|
|
}
|
|
/**
|
|
* Decodes an encoded URL parameter or query-string value.
|
|
* @param value The encoded value.
|
|
* @returns The decoded value.
|
|
*/
|
|
decodeValue(value) {
|
|
return decodeURIComponent(value);
|
|
}
|
|
};
|
|
function paramParser(rawParams, codec) {
|
|
const map2 = /* @__PURE__ */ 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 = map2.get(key) || [];
|
|
list.push(val);
|
|
map2.set(key, list);
|
|
});
|
|
}
|
|
return map2;
|
|
}
|
|
var STANDARD_ENCODING_REGEX = /%(\d[a-f0-9])/gi;
|
|
var 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}`;
|
|
}
|
|
var HttpParams = 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 = /* @__PURE__ */ 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;
|
|
}
|
|
}
|
|
/**
|
|
* Reports whether the body includes one or more values for a given parameter.
|
|
* @param param The parameter name.
|
|
* @returns True if the parameter has one or more values,
|
|
* false if it has no value or is not present.
|
|
*/
|
|
has(param) {
|
|
this.init();
|
|
return this.map.has(param);
|
|
}
|
|
/**
|
|
* Retrieves the first value for a parameter.
|
|
* @param param The parameter name.
|
|
* @returns The first value of the given parameter,
|
|
* or `null` if the parameter is not present.
|
|
*/
|
|
get(param) {
|
|
this.init();
|
|
const res = this.map.get(param);
|
|
return !!res ? res[0] : null;
|
|
}
|
|
/**
|
|
* Retrieves all values for a parameter.
|
|
* @param param The parameter name.
|
|
* @returns All values in a string array,
|
|
* or `null` if the parameter not present.
|
|
*/
|
|
getAll(param) {
|
|
this.init();
|
|
return this.map.get(param) || null;
|
|
}
|
|
/**
|
|
* Retrieves all the parameters for this body.
|
|
* @returns The parameter names in a string array.
|
|
*/
|
|
keys() {
|
|
this.init();
|
|
return Array.from(this.map.keys());
|
|
}
|
|
/**
|
|
* Appends a new value to existing values for a parameter.
|
|
* @param param The parameter name.
|
|
* @param value The new value to add.
|
|
* @return A new body with the appended value.
|
|
*/
|
|
append(param, value) {
|
|
return this.clone({
|
|
param,
|
|
value,
|
|
op: "a"
|
|
});
|
|
}
|
|
/**
|
|
* Constructs a new body with appended values for the given parameter name.
|
|
* @param params parameters and values
|
|
* @return A new body with the new value.
|
|
*/
|
|
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,
|
|
op: "a"
|
|
});
|
|
}
|
|
});
|
|
return this.clone(updates);
|
|
}
|
|
/**
|
|
* Replaces the value for a parameter.
|
|
* @param param The parameter name.
|
|
* @param value The new value.
|
|
* @return A new body with the new value.
|
|
*/
|
|
set(param, value) {
|
|
return this.clone({
|
|
param,
|
|
value,
|
|
op: "s"
|
|
});
|
|
}
|
|
/**
|
|
* Removes a given value or all values from a parameter.
|
|
* @param param The parameter name.
|
|
* @param value The value to remove, if provided.
|
|
* @return A new body with the given value removed, or with all values
|
|
* removed if no value is specified.
|
|
*/
|
|
delete(param, value) {
|
|
return this.clone({
|
|
param,
|
|
value,
|
|
op: "d"
|
|
});
|
|
}
|
|
/**
|
|
* Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
|
|
* separated by `&`s.
|
|
*/
|
|
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 = /* @__PURE__ */ 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) : void 0) || [];
|
|
base.push(valueToString(update.value));
|
|
this.map.set(update.param, base);
|
|
break;
|
|
case "d":
|
|
if (update.value !== void 0) {
|
|
let base2 = this.map.get(update.param) || [];
|
|
const idx = base2.indexOf(valueToString(update.value));
|
|
if (idx !== -1) {
|
|
base2.splice(idx, 1);
|
|
}
|
|
if (base2.length > 0) {
|
|
this.map.set(update.param, base2);
|
|
} else {
|
|
this.map.delete(update.param);
|
|
}
|
|
} else {
|
|
this.map.delete(update.param);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
this.cloneFrom = this.updates = null;
|
|
}
|
|
}
|
|
};
|
|
var HttpContextToken = class {
|
|
defaultValue;
|
|
constructor(defaultValue) {
|
|
this.defaultValue = defaultValue;
|
|
}
|
|
};
|
|
var HttpContext = class {
|
|
map = /* @__PURE__ */ new Map();
|
|
/**
|
|
* Store a value in the context. If a value is already present it will be overwritten.
|
|
*
|
|
* @param token The reference to an instance of `HttpContextToken`.
|
|
* @param value The value to store.
|
|
*
|
|
* @returns A reference to itself for easy chaining.
|
|
*/
|
|
set(token, value) {
|
|
this.map.set(token, value);
|
|
return this;
|
|
}
|
|
/**
|
|
* Retrieve the value associated with the given token.
|
|
*
|
|
* @param token The reference to an instance of `HttpContextToken`.
|
|
*
|
|
* @returns The stored value or default if one is defined.
|
|
*/
|
|
get(token) {
|
|
if (!this.map.has(token)) {
|
|
this.map.set(token, token.defaultValue());
|
|
}
|
|
return this.map.get(token);
|
|
}
|
|
/**
|
|
* Delete the value associated with the given token.
|
|
*
|
|
* @param token The reference to an instance of `HttpContextToken`.
|
|
*
|
|
* @returns A reference to itself for easy chaining.
|
|
*/
|
|
delete(token) {
|
|
this.map.delete(token);
|
|
return this;
|
|
}
|
|
/**
|
|
* Checks for existence of a given token.
|
|
*
|
|
* @param token The reference to an instance of `HttpContextToken`.
|
|
*
|
|
* @returns True if the token exists, false otherwise.
|
|
*/
|
|
has(token) {
|
|
return this.map.has(token);
|
|
}
|
|
/**
|
|
* @returns a list of tokens currently stored in the context.
|
|
*/
|
|
keys() {
|
|
return this.map.keys();
|
|
}
|
|
};
|
|
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;
|
|
}
|
|
var CONTENT_TYPE_HEADER = "Content-Type";
|
|
var ACCEPT_HEADER = "Accept";
|
|
var X_REQUEST_URL_HEADER = "X-Request-URL";
|
|
var TEXT_CONTENT_TYPE = "text/plain";
|
|
var JSON_CONTENT_TYPE = "application/json";
|
|
var ACCEPT_HEADER_VALUE = `${JSON_CONTENT_TYPE}, ${TEXT_CONTENT_TYPE}, */*`;
|
|
var HttpRequest = class _HttpRequest {
|
|
url;
|
|
/**
|
|
* The request body, or `null` if one isn't set.
|
|
*
|
|
* Bodies are not enforced to be immutable, as they can include a reference to any
|
|
* user-defined data type. However, interceptors should take care to preserve
|
|
* idempotence by treating them as such.
|
|
*/
|
|
body = null;
|
|
/**
|
|
* Outgoing headers for this request.
|
|
*/
|
|
headers;
|
|
/**
|
|
* Shared and mutable context that can be used by interceptors
|
|
*/
|
|
context;
|
|
/**
|
|
* Whether this request should be made in a way that exposes progress events.
|
|
*
|
|
* Progress events are expensive (change detection runs on each event) and so
|
|
* they should only be requested if the consumer intends to monitor them.
|
|
*
|
|
* Note: The `FetchBackend` doesn't support progress report on uploads.
|
|
*/
|
|
reportProgress = false;
|
|
/**
|
|
* Whether this request should be sent with outgoing credentials (cookies).
|
|
*/
|
|
withCredentials = false;
|
|
/**
|
|
* The credentials mode of the request, which determines how cookies and HTTP authentication are handled.
|
|
* This can affect whether cookies are sent with the request, and how authentication is handled.
|
|
*/
|
|
credentials;
|
|
/**
|
|
* 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.
|
|
*/
|
|
keepalive = false;
|
|
/**
|
|
* Controls how the request will interact with the browser's HTTP cache.
|
|
* This affects whether a response is retrieved from the cache, how it is stored, or if it bypasses the cache altogether.
|
|
*/
|
|
cache;
|
|
/**
|
|
* Indicates the relative priority of the request. This may be used by the browser to decide the order in which requests are dispatched and resources fetched.
|
|
*/
|
|
priority;
|
|
/**
|
|
* The mode of the request, which determines how the request will interact with the browser's security model.
|
|
* This can affect things like CORS (Cross-Origin Resource Sharing) and same-origin policies.
|
|
*/
|
|
mode;
|
|
/**
|
|
* The redirect mode of the request, which determines how redirects are handled.
|
|
* This can affect whether the request follows redirects automatically, or if it fails when a redirect occurs.
|
|
*/
|
|
redirect;
|
|
/**
|
|
* The referrer of the request, which can be used to indicate the origin of the request.
|
|
* This is useful for security and analytics purposes.
|
|
* Value is a same-origin URL, "about:client", or the empty string, to set request's referrer.
|
|
*/
|
|
referrer;
|
|
/**
|
|
* The integrity metadata of the request, which can be used to ensure the request is made with the expected content.
|
|
* A cryptographic hash of the resource to be fetched by request
|
|
*/
|
|
integrity;
|
|
/**
|
|
* The expected response type of the server.
|
|
*
|
|
* This is used to parse the response appropriately before returning it to
|
|
* the requestee.
|
|
*/
|
|
responseType = "json";
|
|
/**
|
|
* The outgoing HTTP request method.
|
|
*/
|
|
method;
|
|
/**
|
|
* Outgoing URL parameters.
|
|
*
|
|
* To pass a string representation of HTTP parameters in the URL-query-string format,
|
|
* the `HttpParamsOptions`' `fromString` may be used. For example:
|
|
*
|
|
* ```ts
|
|
* new HttpParams({fromString: 'angular=awesome'})
|
|
* ```
|
|
*/
|
|
params;
|
|
/**
|
|
* The outgoing URL with all URL parameters set.
|
|
*/
|
|
urlWithParams;
|
|
/**
|
|
* The HttpTransferCache option for the request
|
|
*/
|
|
transferCache;
|
|
/**
|
|
* The timeout for the backend HTTP request in ms.
|
|
*/
|
|
timeout;
|
|
constructor(method, url, third, fourth) {
|
|
this.url = url;
|
|
this.method = method.toUpperCase();
|
|
let options;
|
|
if (mightHaveBody(this.method) || !!fourth) {
|
|
this.body = third !== void 0 ? 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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Transform the free-form body into a serialized format suitable for
|
|
* transmission to the server.
|
|
*/
|
|
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();
|
|
}
|
|
/**
|
|
* Examine the body and attempt to infer an appropriate MIME type
|
|
* for it.
|
|
*
|
|
* If no such type can be inferred, this method will return `null`.
|
|
*/
|
|
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 transferCache = update.transferCache ?? this.transferCache;
|
|
const timeout = update.timeout ?? this.timeout;
|
|
const body = update.body !== void 0 ? 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 !== void 0) {
|
|
headers = Object.keys(update.setHeaders).reduce((headers2, name) => headers2.set(name, update.setHeaders[name]), headers);
|
|
}
|
|
if (update.setParams) {
|
|
params = Object.keys(update.setParams).reduce((params2, param) => params2.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
|
|
});
|
|
}
|
|
};
|
|
var HttpEventType;
|
|
(function(HttpEventType2) {
|
|
HttpEventType2[HttpEventType2["Sent"] = 0] = "Sent";
|
|
HttpEventType2[HttpEventType2["UploadProgress"] = 1] = "UploadProgress";
|
|
HttpEventType2[HttpEventType2["ResponseHeader"] = 2] = "ResponseHeader";
|
|
HttpEventType2[HttpEventType2["DownloadProgress"] = 3] = "DownloadProgress";
|
|
HttpEventType2[HttpEventType2["Response"] = 4] = "Response";
|
|
HttpEventType2[HttpEventType2["User"] = 5] = "User";
|
|
})(HttpEventType || (HttpEventType = {}));
|
|
var HttpResponseBase = class {
|
|
/**
|
|
* All response headers.
|
|
*/
|
|
headers;
|
|
/**
|
|
* Response status code.
|
|
*/
|
|
status;
|
|
/**
|
|
* Textual description of response status code, defaults to OK.
|
|
*
|
|
* Do not depend on this.
|
|
*/
|
|
statusText;
|
|
/**
|
|
* URL of the resource retrieved, or null if not available.
|
|
*/
|
|
url;
|
|
/**
|
|
* Whether the status code falls in the 2xx range.
|
|
*/
|
|
ok;
|
|
/**
|
|
* Type of the response, narrowed to either the full response or the header.
|
|
*/
|
|
type;
|
|
/**
|
|
* Indicates whether the HTTP response was redirected during the request.
|
|
* This property is only available when using the Fetch API using `withFetch()`
|
|
* When using the default XHR Request this property will be `undefined`
|
|
*/
|
|
redirected;
|
|
/**
|
|
* Super-constructor for all responses.
|
|
*
|
|
* The single parameter accepted is an initialization hash. Any properties
|
|
* of the response passed there will override the default values.
|
|
*/
|
|
constructor(init, defaultStatus = 200, defaultStatusText = "OK") {
|
|
this.headers = init.headers || new HttpHeaders();
|
|
this.status = init.status !== void 0 ? init.status : defaultStatus;
|
|
this.statusText = init.statusText || defaultStatusText;
|
|
this.url = init.url || null;
|
|
this.redirected = init.redirected;
|
|
this.ok = this.status >= 200 && this.status < 300;
|
|
}
|
|
};
|
|
var HttpHeaderResponse = class _HttpHeaderResponse extends HttpResponseBase {
|
|
/**
|
|
* Create a new `HttpHeaderResponse` with the given parameters.
|
|
*/
|
|
constructor(init = {}) {
|
|
super(init);
|
|
}
|
|
type = HttpEventType.ResponseHeader;
|
|
/**
|
|
* Copy this `HttpHeaderResponse`, overriding its contents with the
|
|
* given parameter hash.
|
|
*/
|
|
clone(update = {}) {
|
|
return new _HttpHeaderResponse({
|
|
headers: update.headers || this.headers,
|
|
status: update.status !== void 0 ? update.status : this.status,
|
|
statusText: update.statusText || this.statusText,
|
|
url: update.url || this.url || void 0
|
|
});
|
|
}
|
|
};
|
|
var HttpResponse = class _HttpResponse extends HttpResponseBase {
|
|
/**
|
|
* The response body, or `null` if one was not returned.
|
|
*/
|
|
body;
|
|
/**
|
|
* Construct a new `HttpResponse`.
|
|
*/
|
|
constructor(init = {}) {
|
|
super(init);
|
|
this.body = init.body !== void 0 ? init.body : null;
|
|
}
|
|
type = HttpEventType.Response;
|
|
clone(update = {}) {
|
|
return new _HttpResponse({
|
|
body: update.body !== void 0 ? update.body : this.body,
|
|
headers: update.headers || this.headers,
|
|
status: update.status !== void 0 ? update.status : this.status,
|
|
statusText: update.statusText || this.statusText,
|
|
url: update.url || this.url || void 0,
|
|
redirected: update.redirected ?? this.redirected
|
|
});
|
|
}
|
|
};
|
|
var HttpErrorResponse = class extends HttpResponseBase {
|
|
name = "HttpErrorResponse";
|
|
message;
|
|
error;
|
|
/**
|
|
* Errors are never okay, even when the status code is in the 2xx success range.
|
|
*/
|
|
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;
|
|
}
|
|
};
|
|
var HTTP_STATUS_CODE_OK = 200;
|
|
var HTTP_STATUS_CODE_NO_CONTENT = 204;
|
|
var HttpStatusCode;
|
|
(function(HttpStatusCode2) {
|
|
HttpStatusCode2[HttpStatusCode2["Continue"] = 100] = "Continue";
|
|
HttpStatusCode2[HttpStatusCode2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
HttpStatusCode2[HttpStatusCode2["Processing"] = 102] = "Processing";
|
|
HttpStatusCode2[HttpStatusCode2["EarlyHints"] = 103] = "EarlyHints";
|
|
HttpStatusCode2[HttpStatusCode2["Ok"] = 200] = "Ok";
|
|
HttpStatusCode2[HttpStatusCode2["Created"] = 201] = "Created";
|
|
HttpStatusCode2[HttpStatusCode2["Accepted"] = 202] = "Accepted";
|
|
HttpStatusCode2[HttpStatusCode2["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
HttpStatusCode2[HttpStatusCode2["NoContent"] = 204] = "NoContent";
|
|
HttpStatusCode2[HttpStatusCode2["ResetContent"] = 205] = "ResetContent";
|
|
HttpStatusCode2[HttpStatusCode2["PartialContent"] = 206] = "PartialContent";
|
|
HttpStatusCode2[HttpStatusCode2["MultiStatus"] = 207] = "MultiStatus";
|
|
HttpStatusCode2[HttpStatusCode2["AlreadyReported"] = 208] = "AlreadyReported";
|
|
HttpStatusCode2[HttpStatusCode2["ImUsed"] = 226] = "ImUsed";
|
|
HttpStatusCode2[HttpStatusCode2["MultipleChoices"] = 300] = "MultipleChoices";
|
|
HttpStatusCode2[HttpStatusCode2["MovedPermanently"] = 301] = "MovedPermanently";
|
|
HttpStatusCode2[HttpStatusCode2["Found"] = 302] = "Found";
|
|
HttpStatusCode2[HttpStatusCode2["SeeOther"] = 303] = "SeeOther";
|
|
HttpStatusCode2[HttpStatusCode2["NotModified"] = 304] = "NotModified";
|
|
HttpStatusCode2[HttpStatusCode2["UseProxy"] = 305] = "UseProxy";
|
|
HttpStatusCode2[HttpStatusCode2["Unused"] = 306] = "Unused";
|
|
HttpStatusCode2[HttpStatusCode2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
HttpStatusCode2[HttpStatusCode2["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest";
|
|
HttpStatusCode2[HttpStatusCode2["Unauthorized"] = 401] = "Unauthorized";
|
|
HttpStatusCode2[HttpStatusCode2["PaymentRequired"] = 402] = "PaymentRequired";
|
|
HttpStatusCode2[HttpStatusCode2["Forbidden"] = 403] = "Forbidden";
|
|
HttpStatusCode2[HttpStatusCode2["NotFound"] = 404] = "NotFound";
|
|
HttpStatusCode2[HttpStatusCode2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
HttpStatusCode2[HttpStatusCode2["NotAcceptable"] = 406] = "NotAcceptable";
|
|
HttpStatusCode2[HttpStatusCode2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
HttpStatusCode2[HttpStatusCode2["RequestTimeout"] = 408] = "RequestTimeout";
|
|
HttpStatusCode2[HttpStatusCode2["Conflict"] = 409] = "Conflict";
|
|
HttpStatusCode2[HttpStatusCode2["Gone"] = 410] = "Gone";
|
|
HttpStatusCode2[HttpStatusCode2["LengthRequired"] = 411] = "LengthRequired";
|
|
HttpStatusCode2[HttpStatusCode2["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
HttpStatusCode2[HttpStatusCode2["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
HttpStatusCode2[HttpStatusCode2["UriTooLong"] = 414] = "UriTooLong";
|
|
HttpStatusCode2[HttpStatusCode2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
HttpStatusCode2[HttpStatusCode2["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
HttpStatusCode2[HttpStatusCode2["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
HttpStatusCode2[HttpStatusCode2["ImATeapot"] = 418] = "ImATeapot";
|
|
HttpStatusCode2[HttpStatusCode2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
HttpStatusCode2[HttpStatusCode2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
HttpStatusCode2[HttpStatusCode2["Locked"] = 423] = "Locked";
|
|
HttpStatusCode2[HttpStatusCode2["FailedDependency"] = 424] = "FailedDependency";
|
|
HttpStatusCode2[HttpStatusCode2["TooEarly"] = 425] = "TooEarly";
|
|
HttpStatusCode2[HttpStatusCode2["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
HttpStatusCode2[HttpStatusCode2["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
HttpStatusCode2[HttpStatusCode2["TooManyRequests"] = 429] = "TooManyRequests";
|
|
HttpStatusCode2[HttpStatusCode2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
HttpStatusCode2[HttpStatusCode2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
HttpStatusCode2[HttpStatusCode2["InternalServerError"] = 500] = "InternalServerError";
|
|
HttpStatusCode2[HttpStatusCode2["NotImplemented"] = 501] = "NotImplemented";
|
|
HttpStatusCode2[HttpStatusCode2["BadGateway"] = 502] = "BadGateway";
|
|
HttpStatusCode2[HttpStatusCode2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
HttpStatusCode2[HttpStatusCode2["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
HttpStatusCode2[HttpStatusCode2["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
|
|
HttpStatusCode2[HttpStatusCode2["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
HttpStatusCode2[HttpStatusCode2["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
HttpStatusCode2[HttpStatusCode2["LoopDetected"] = 508] = "LoopDetected";
|
|
HttpStatusCode2[HttpStatusCode2["NotExtended"] = 510] = "NotExtended";
|
|
HttpStatusCode2[HttpStatusCode2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
})(HttpStatusCode || (HttpStatusCode = {}));
|
|
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
|
|
};
|
|
}
|
|
var HttpClient = class _HttpClient {
|
|
handler;
|
|
constructor(handler) {
|
|
this.handler = handler;
|
|
}
|
|
/**
|
|
* Constructs an observable for a generic HTTP request that, when subscribed,
|
|
* fires the request through the chain of registered interceptors and on to the
|
|
* server.
|
|
*
|
|
* You can pass an `HttpRequest` directly as the only parameter. In this case,
|
|
* the call returns an observable of the raw `HttpEvent` stream.
|
|
*
|
|
* Alternatively you can pass an HTTP method as the first parameter,
|
|
* a URL string as the second, and an options hash containing the request body as the third.
|
|
* See `addBody()`. In this case, the specified `responseType` and `observe` options determine the
|
|
* type of returned observable.
|
|
* * The `responseType` value determines how a successful response body is parsed.
|
|
* * If `responseType` is the default `json`, you can pass a type interface for the resulting
|
|
* object as a type parameter to the call.
|
|
*
|
|
* The `observe` value determines the return type, according to what you are interested in
|
|
* observing.
|
|
* * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including
|
|
* progress events by default.
|
|
* * An `observe` value of response returns an observable of `HttpResponse<T>`,
|
|
* where the `T` parameter depends on the `responseType` and any optionally provided type
|
|
* parameter.
|
|
* * An `observe` value of body returns an observable of `<T>` with the same `T` body type.
|
|
*
|
|
*/
|
|
request(first, url, options = {}) {
|
|
let req;
|
|
if (first instanceof HttpRequest) {
|
|
req = first;
|
|
} else {
|
|
let headers = void 0;
|
|
if (options.headers instanceof HttpHeaders) {
|
|
headers = options.headers;
|
|
} else {
|
|
headers = new HttpHeaders(options.headers);
|
|
}
|
|
let params = void 0;
|
|
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 !== void 0 ? options.body : null, {
|
|
headers,
|
|
context: options.context,
|
|
params,
|
|
reportProgress: options.reportProgress,
|
|
// By default, JSON is assumed to be returned for all calls.
|
|
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,
|
|
integrity: options.integrity,
|
|
timeout: options.timeout
|
|
});
|
|
}
|
|
const events$ = of(req).pipe(concatMap((req2) => this.handler.handle(req2)));
|
|
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.");
|
|
}
|
|
return res.body;
|
|
}));
|
|
case "text":
|
|
return res$.pipe(map((res) => {
|
|
if (res.body !== null && typeof res.body !== "string") {
|
|
throw new RuntimeError(2808, ngDevMode && "Response is not a string.");
|
|
}
|
|
return res.body;
|
|
}));
|
|
case "json":
|
|
default:
|
|
return res$.pipe(map((res) => res.body));
|
|
}
|
|
case "response":
|
|
return res$;
|
|
default:
|
|
throw new RuntimeError(2809, ngDevMode && `Unreachable: unhandled observe type ${options.observe}}`);
|
|
}
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `DELETE` request to execute on the server. See the individual overloads for
|
|
* details on the return type.
|
|
*
|
|
* @param url The endpoint URL.
|
|
* @param options The HTTP options to send with the request.
|
|
*
|
|
*/
|
|
delete(url, options = {}) {
|
|
return this.request("DELETE", url, options);
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `GET` request to execute on the server. See the individual overloads for
|
|
* details on the return type.
|
|
*/
|
|
get(url, options = {}) {
|
|
return this.request("GET", url, options);
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `HEAD` request to execute on the server. The `HEAD` method returns
|
|
* meta information about the resource without transferring the
|
|
* resource itself. See the individual overloads for
|
|
* details on the return type.
|
|
*/
|
|
head(url, options = {}) {
|
|
return this.request("HEAD", url, options);
|
|
}
|
|
/**
|
|
* Constructs an `Observable` that, when subscribed, causes a request with the special method
|
|
* `JSONP` to be dispatched via the interceptor pipeline.
|
|
* The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain
|
|
* API endpoints that don't support newer,
|
|
* and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol.
|
|
* JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the
|
|
* requests even if the API endpoint is not located on the same domain (origin) as the client-side
|
|
* application making the request.
|
|
* The endpoint API must support JSONP callback for JSONP requests to work.
|
|
* The resource API returns the JSON response wrapped in a callback function.
|
|
* You can pass the callback function name as one of the query parameters.
|
|
* Note that JSONP requests can only be used with `GET` requests.
|
|
*
|
|
* @param url The resource URL.
|
|
* @param callbackParam The callback function name.
|
|
*
|
|
*/
|
|
jsonp(url, callbackParam) {
|
|
return this.request("JSONP", url, {
|
|
params: new HttpParams().append(callbackParam, "JSONP_CALLBACK"),
|
|
observe: "body",
|
|
responseType: "json"
|
|
});
|
|
}
|
|
/**
|
|
* Constructs an `Observable` that, when subscribed, causes the configured
|
|
* `OPTIONS` request to execute on the server. This method allows the client
|
|
* to determine the supported HTTP methods and other capabilities of an endpoint,
|
|
* without implying a resource action. See the individual overloads for
|
|
* details on the return type.
|
|
*/
|
|
options(url, options = {}) {
|
|
return this.request("OPTIONS", url, options);
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `PATCH` request to execute on the server. See the individual overloads for
|
|
* details on the return type.
|
|
*/
|
|
patch(url, body, options = {}) {
|
|
return this.request("PATCH", url, addBody(options, body));
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `POST` request to execute on the server. The server responds with the location of
|
|
* the replaced resource. See the individual overloads for
|
|
* details on the return type.
|
|
*/
|
|
post(url, body, options = {}) {
|
|
return this.request("POST", url, addBody(options, body));
|
|
}
|
|
/**
|
|
* Constructs an observable that, when subscribed, causes the configured
|
|
* `PUT` request to execute on the server. The `PUT` method replaces an existing resource
|
|
* with a new set of values.
|
|
* See the individual overloads for details on the return type.
|
|
*/
|
|
put(url, body, options = {}) {
|
|
return this.request("PUT", url, addBody(options, body));
|
|
}
|
|
static ɵfac = function HttpClient_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpClient)(ɵɵinject(HttpHandler));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _HttpClient,
|
|
factory: _HttpClient.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClient, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: HttpHandler
|
|
}], null);
|
|
})();
|
|
var XSSI_PREFIX$1 = /^\)\]\}',?\n/;
|
|
function getResponseUrl$1(response) {
|
|
if (response.url) {
|
|
return response.url;
|
|
}
|
|
const xRequestUrl = X_REQUEST_URL_HEADER.toLocaleLowerCase();
|
|
return response.headers.get(xRequestUrl);
|
|
}
|
|
var FETCH_BACKEND = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "FETCH_BACKEND" : "");
|
|
var FetchBackend = class _FetchBackend {
|
|
// We use an arrow function to always reference the current global implementation of `fetch`.
|
|
// This is helpful for cases when the global `fetch` implementation is modified by external code,
|
|
// see https://github.com/angular/angular/issues/57527.
|
|
fetchImpl = inject(FetchFactory, {
|
|
optional: true
|
|
})?.fetch ?? ((...args) => globalThis.fetch(...args));
|
|
ngZone = inject(NgZone);
|
|
destroyRef = inject(DestroyRef);
|
|
destroyed = false;
|
|
constructor() {
|
|
this.destroyRef.onDestroy(() => {
|
|
this.destroyed = true;
|
|
});
|
|
}
|
|
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 !== void 0) {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
aborter.abort();
|
|
};
|
|
});
|
|
}
|
|
async doRequest(request, signal2, observer) {
|
|
const init = this.createRequestInit(request);
|
|
let response;
|
|
try {
|
|
const fetchPromise = this.ngZone.runOutsideAngular(() => this.fetchImpl(request.urlWithParams, __spreadValues({
|
|
signal: signal2
|
|
}, 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 = getResponseUrl$1(response) ?? 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.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
|
|
}) : void 0;
|
|
const reportProgress = () => observer.next({
|
|
type: HttpEventType.DownloadProgress,
|
|
total: contentLength ? +contentLength : void 0,
|
|
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: getResponseUrl$1(response) ?? request.urlWithParams
|
|
}));
|
|
return;
|
|
}
|
|
}
|
|
if (status === 0) {
|
|
status = body ? HTTP_STATUS_CODE_OK : 0;
|
|
}
|
|
const ok = status >= 200 && status < 300;
|
|
const redirected = response.redirected;
|
|
if (ok) {
|
|
observer.next(new HttpResponse({
|
|
body,
|
|
headers,
|
|
status,
|
|
statusText,
|
|
url,
|
|
redirected
|
|
}));
|
|
observer.complete();
|
|
} else {
|
|
observer.error(new HttpErrorResponse({
|
|
error: body,
|
|
headers,
|
|
status,
|
|
statusText,
|
|
url,
|
|
redirected
|
|
}));
|
|
}
|
|
}
|
|
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
|
|
};
|
|
}
|
|
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 = function FetchBackend_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _FetchBackend)();
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _FetchBackend,
|
|
factory: _FetchBackend.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FetchBackend, [{
|
|
type: Injectable
|
|
}], () => [], null);
|
|
})();
|
|
var FetchFactory = class {
|
|
};
|
|
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);
|
|
}
|
|
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)));
|
|
}
|
|
var HTTP_INTERCEPTORS = new InjectionToken(ngDevMode ? "HTTP_INTERCEPTORS" : "");
|
|
var HTTP_INTERCEPTOR_FNS = new InjectionToken(ngDevMode ? "HTTP_INTERCEPTOR_FNS" : "");
|
|
var HTTP_ROOT_INTERCEPTOR_FNS = new InjectionToken(ngDevMode ? "HTTP_ROOT_INTERCEPTOR_FNS" : "");
|
|
var REQUESTS_CONTRIBUTE_TO_STABILITY = new InjectionToken(ngDevMode ? "REQUESTS_CONTRIBUTE_TO_STABILITY" : "", {
|
|
providedIn: "root",
|
|
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);
|
|
}
|
|
};
|
|
}
|
|
var fetchBackendWarningDisplayed = false;
|
|
var HttpInterceptorHandler = class _HttpInterceptorHandler extends HttpHandler {
|
|
backend;
|
|
injector;
|
|
chain = null;
|
|
pendingTasks = inject(PendingTasks);
|
|
contributeToStability = inject(REQUESTS_CONTRIBUTE_TO_STABILITY);
|
|
constructor(backend, injector) {
|
|
super();
|
|
this.backend = backend;
|
|
this.injector = injector;
|
|
if ((typeof ngDevMode === "undefined" || ngDevMode) && !fetchBackendWarningDisplayed) {
|
|
const isTestingBackend = this.backend.isTestingBackend;
|
|
if (false) {
|
|
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(/* @__PURE__ */ 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 = function HttpInterceptorHandler_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpInterceptorHandler)(ɵɵinject(HttpBackend), ɵɵinject(EnvironmentInjector));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _HttpInterceptorHandler,
|
|
factory: _HttpInterceptorHandler.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpInterceptorHandler, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: HttpBackend
|
|
}, {
|
|
type: EnvironmentInjector
|
|
}], null);
|
|
})();
|
|
var nextRequestId = 0;
|
|
var foreignDocument;
|
|
var JSONP_ERR_NO_CALLBACK = "JSONP injected script did not invoke callback.";
|
|
var JSONP_ERR_WRONG_METHOD = "JSONP requests must use JSONP request method.";
|
|
var JSONP_ERR_WRONG_RESPONSE_TYPE = "JSONP requests must use Json response type.";
|
|
var JSONP_ERR_HEADERS_NOT_SUPPORTED = "JSONP requests do not support headers.";
|
|
var JsonpCallbackContext = class {
|
|
};
|
|
function jsonpCallbackContext() {
|
|
if (typeof window === "object") {
|
|
return window;
|
|
}
|
|
return {};
|
|
}
|
|
var JsonpClientBackend = class _JsonpClientBackend {
|
|
callbackMap;
|
|
document;
|
|
/**
|
|
* A resolved promise that can be used to schedule microtasks in the event handlers.
|
|
*/
|
|
resolvedPromise = Promise.resolve();
|
|
constructor(callbackMap, document) {
|
|
this.callbackMap = callbackMap;
|
|
this.document = document;
|
|
}
|
|
/**
|
|
* Get the name of the next callback method, by incrementing the global `nextRequestId`.
|
|
*/
|
|
nextCallback() {
|
|
return `ng_jsonp_callback_${nextRequestId++}`;
|
|
}
|
|
/**
|
|
* Processes a JSONP request and returns an event stream of the results.
|
|
* @param req The request object.
|
|
* @returns An observable of the response events.
|
|
*
|
|
*/
|
|
handle(req) {
|
|
if (req.method !== "JSONP") {
|
|
throw new RuntimeError(2810, ngDevMode && JSONP_ERR_WRONG_METHOD);
|
|
} else if (req.responseType !== "json") {
|
|
throw new RuntimeError(2811, ngDevMode && JSONP_ERR_WRONG_RESPONSE_TYPE);
|
|
}
|
|
if (req.headers.keys().length > 0) {
|
|
throw new RuntimeError(2812, ngDevMode && JSONP_ERR_HEADERS_NOT_SUPPORTED);
|
|
}
|
|
return new Observable((observer) => {
|
|
const callback = this.nextCallback();
|
|
const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`);
|
|
const node = this.document.createElement("script");
|
|
node.src = url;
|
|
let body = null;
|
|
let finished = false;
|
|
this.callbackMap[callback] = (data) => {
|
|
delete this.callbackMap[callback];
|
|
body = data;
|
|
finished = true;
|
|
};
|
|
const cleanup = () => {
|
|
node.removeEventListener("load", onLoad);
|
|
node.removeEventListener("error", onError);
|
|
node.remove();
|
|
delete this.callbackMap[callback];
|
|
};
|
|
const onLoad = () => {
|
|
this.resolvedPromise.then(() => {
|
|
cleanup();
|
|
if (!finished) {
|
|
observer.error(new HttpErrorResponse({
|
|
url,
|
|
status: 0,
|
|
statusText: "JSONP Error",
|
|
error: new Error(JSONP_ERR_NO_CALLBACK)
|
|
}));
|
|
return;
|
|
}
|
|
observer.next(new HttpResponse({
|
|
body,
|
|
status: HTTP_STATUS_CODE_OK,
|
|
statusText: "OK",
|
|
url
|
|
}));
|
|
observer.complete();
|
|
});
|
|
};
|
|
const onError = (error) => {
|
|
cleanup();
|
|
observer.error(new HttpErrorResponse({
|
|
error,
|
|
status: 0,
|
|
statusText: "JSONP Error",
|
|
url
|
|
}));
|
|
};
|
|
node.addEventListener("load", onLoad);
|
|
node.addEventListener("error", onError);
|
|
this.document.body.appendChild(node);
|
|
observer.next({
|
|
type: HttpEventType.Sent
|
|
});
|
|
return () => {
|
|
if (!finished) {
|
|
this.removeListeners(node);
|
|
}
|
|
cleanup();
|
|
};
|
|
});
|
|
}
|
|
removeListeners(script) {
|
|
foreignDocument ??= this.document.implementation.createHTMLDocument();
|
|
foreignDocument.adoptNode(script);
|
|
}
|
|
static ɵfac = function JsonpClientBackend_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _JsonpClientBackend)(ɵɵinject(JsonpCallbackContext), ɵɵinject(DOCUMENT));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _JsonpClientBackend,
|
|
factory: _JsonpClientBackend.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(JsonpClientBackend, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: JsonpCallbackContext
|
|
}, {
|
|
type: void 0,
|
|
decorators: [{
|
|
type: Inject,
|
|
args: [DOCUMENT]
|
|
}]
|
|
}], null);
|
|
})();
|
|
function jsonpInterceptorFn(req, next) {
|
|
if (req.method === "JSONP") {
|
|
return inject(JsonpClientBackend).handle(req);
|
|
}
|
|
return next(req);
|
|
}
|
|
var JsonpInterceptor = class _JsonpInterceptor {
|
|
injector;
|
|
constructor(injector) {
|
|
this.injector = injector;
|
|
}
|
|
/**
|
|
* Identifies and handles a given JSONP request.
|
|
* @param initialRequest The outgoing request object to handle.
|
|
* @param next The next interceptor in the chain, or the backend
|
|
* if no interceptors remain in the chain.
|
|
* @returns An observable of the event stream.
|
|
*/
|
|
intercept(initialRequest, next) {
|
|
return runInInjectionContext(this.injector, () => jsonpInterceptorFn(initialRequest, (downstreamRequest) => next.handle(downstreamRequest)));
|
|
}
|
|
static ɵfac = function JsonpInterceptor_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _JsonpInterceptor)(ɵɵinject(EnvironmentInjector));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _JsonpInterceptor,
|
|
factory: _JsonpInterceptor.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(JsonpInterceptor, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: EnvironmentInjector
|
|
}], null);
|
|
})();
|
|
var XSSI_PREFIX = /^\)\]\}',?\n/;
|
|
var X_REQUEST_URL_REGEXP = RegExp(`^${X_REQUEST_URL_HEADER}:`, "m");
|
|
function getResponseUrl(xhr) {
|
|
if ("responseURL" in xhr && xhr.responseURL) {
|
|
return xhr.responseURL;
|
|
}
|
|
if (X_REQUEST_URL_REGEXP.test(xhr.getAllResponseHeaders())) {
|
|
return xhr.getResponseHeader(X_REQUEST_URL_HEADER);
|
|
}
|
|
return null;
|
|
}
|
|
function validateXhrCompatibility(req) {
|
|
const unsupportedOptions = [{
|
|
property: "keepalive",
|
|
errorCode: 2813
|
|
/* RuntimeErrorCode.KEEPALIVE_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "cache",
|
|
errorCode: 2814
|
|
/* RuntimeErrorCode.CACHE_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "priority",
|
|
errorCode: 2815
|
|
/* RuntimeErrorCode.PRIORITY_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "mode",
|
|
errorCode: 2816
|
|
/* RuntimeErrorCode.MODE_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "redirect",
|
|
errorCode: 2817
|
|
/* RuntimeErrorCode.REDIRECT_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "credentials",
|
|
errorCode: 2818
|
|
/* RuntimeErrorCode.CREDENTIALS_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "integrity",
|
|
errorCode: 2820
|
|
/* RuntimeErrorCode.INTEGRITY_NOT_SUPPORTED_WITH_XHR */
|
|
}, {
|
|
property: "referrer",
|
|
errorCode: 2821
|
|
/* RuntimeErrorCode.REFERRER_NOT_SUPPORTED_WITH_XHR */
|
|
}];
|
|
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()\`.`));
|
|
}
|
|
}
|
|
}
|
|
var HttpXhrBackend = class _HttpXhrBackend {
|
|
xhrFactory;
|
|
constructor(xhrFactory) {
|
|
this.xhrFactory = xhrFactory;
|
|
}
|
|
/**
|
|
* Processes a request and returns a stream of response events.
|
|
* @param req The request object.
|
|
* @returns An observable of the response events.
|
|
*/
|
|
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 = (
|
|
// Note that `ɵloadImpl` is never defined in client bundles and can be
|
|
// safely dropped whenever we're running in the browser.
|
|
// This branching is redundant.
|
|
// The `ngServerMode` guard also enables tree-shaking of the `from()`
|
|
// function from the common bundle, as it's only used in server code.
|
|
false ? 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 = getResponseUrl(xhr) || req.url;
|
|
headerResponse = new HttpHeaderResponse({
|
|
headers,
|
|
status: xhr.status,
|
|
statusText,
|
|
url
|
|
});
|
|
return headerResponse;
|
|
};
|
|
const onLoad = () => {
|
|
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 || void 0
|
|
}));
|
|
observer.complete();
|
|
} else {
|
|
observer.error(new HttpErrorResponse({
|
|
// The error in this case is the response body (error from the server).
|
|
error: body,
|
|
headers,
|
|
status,
|
|
statusText,
|
|
url: url || void 0
|
|
}));
|
|
}
|
|
};
|
|
const onError = (error) => {
|
|
const {
|
|
url
|
|
} = partialFromXhr();
|
|
const res = new HttpErrorResponse({
|
|
error,
|
|
status: xhr.status || 0,
|
|
statusText: xhr.statusText || "Unknown Error",
|
|
url: url || void 0
|
|
});
|
|
observer.error(res);
|
|
};
|
|
let onTimeout = onError;
|
|
if (req.timeout) {
|
|
onTimeout = (_) => {
|
|
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 || void 0
|
|
});
|
|
observer.error(res);
|
|
};
|
|
}
|
|
let sentHeaders = false;
|
|
const onDownProgress = (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 = (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 = function HttpXhrBackend_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpXhrBackend)(ɵɵinject(XhrFactory));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _HttpXhrBackend,
|
|
factory: _HttpXhrBackend.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXhrBackend, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: XhrFactory
|
|
}], null);
|
|
})();
|
|
var XSRF_ENABLED = new InjectionToken(ngDevMode ? "XSRF_ENABLED" : "");
|
|
var XSRF_DEFAULT_COOKIE_NAME = "XSRF-TOKEN";
|
|
var XSRF_COOKIE_NAME = new InjectionToken(ngDevMode ? "XSRF_COOKIE_NAME" : "", {
|
|
providedIn: "root",
|
|
factory: () => XSRF_DEFAULT_COOKIE_NAME
|
|
});
|
|
var XSRF_DEFAULT_HEADER_NAME = "X-XSRF-TOKEN";
|
|
var XSRF_HEADER_NAME = new InjectionToken(ngDevMode ? "XSRF_HEADER_NAME" : "", {
|
|
providedIn: "root",
|
|
factory: () => XSRF_DEFAULT_HEADER_NAME
|
|
});
|
|
var HttpXsrfTokenExtractor = class {
|
|
};
|
|
var HttpXsrfCookieExtractor = class _HttpXsrfCookieExtractor {
|
|
doc;
|
|
cookieName;
|
|
lastCookieString = "";
|
|
lastToken = null;
|
|
/**
|
|
* @internal for testing
|
|
*/
|
|
parseCount = 0;
|
|
constructor(doc, cookieName) {
|
|
this.doc = doc;
|
|
this.cookieName = cookieName;
|
|
}
|
|
getToken() {
|
|
if (false) {
|
|
return null;
|
|
}
|
|
const cookieString = this.doc.cookie || "";
|
|
if (cookieString !== this.lastCookieString) {
|
|
this.parseCount++;
|
|
this.lastToken = parseCookieValue(cookieString, this.cookieName);
|
|
this.lastCookieString = cookieString;
|
|
}
|
|
return this.lastToken;
|
|
}
|
|
static ɵfac = function HttpXsrfCookieExtractor_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpXsrfCookieExtractor)(ɵɵinject(DOCUMENT), ɵɵinject(XSRF_COOKIE_NAME));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _HttpXsrfCookieExtractor,
|
|
factory: _HttpXsrfCookieExtractor.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXsrfCookieExtractor, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: void 0,
|
|
decorators: [{
|
|
type: Inject,
|
|
args: [DOCUMENT]
|
|
}]
|
|
}, {
|
|
type: void 0,
|
|
decorators: [{
|
|
type: Inject,
|
|
args: [XSRF_COOKIE_NAME]
|
|
}]
|
|
}], null);
|
|
})();
|
|
function xsrfInterceptorFn(req, next) {
|
|
const lcUrl = req.url.toLowerCase();
|
|
if (!inject(XSRF_ENABLED) || req.method === "GET" || req.method === "HEAD" || lcUrl.startsWith("http://") || lcUrl.startsWith("https://")) {
|
|
return next(req);
|
|
}
|
|
const token = inject(HttpXsrfTokenExtractor).getToken();
|
|
const headerName = inject(XSRF_HEADER_NAME);
|
|
if (token != null && !req.headers.has(headerName)) {
|
|
req = req.clone({
|
|
headers: req.headers.set(headerName, token)
|
|
});
|
|
}
|
|
return next(req);
|
|
}
|
|
var HttpXsrfInterceptor = class _HttpXsrfInterceptor {
|
|
injector;
|
|
constructor(injector) {
|
|
this.injector = injector;
|
|
}
|
|
intercept(initialRequest, next) {
|
|
return runInInjectionContext(this.injector, () => xsrfInterceptorFn(initialRequest, (downstreamRequest) => next.handle(downstreamRequest)));
|
|
}
|
|
static ɵfac = function HttpXsrfInterceptor_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpXsrfInterceptor)(ɵɵinject(EnvironmentInjector));
|
|
};
|
|
static ɵprov = ɵɵdefineInjectable({
|
|
token: _HttpXsrfInterceptor,
|
|
factory: _HttpXsrfInterceptor.ɵfac
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXsrfInterceptor, [{
|
|
type: Injectable
|
|
}], () => [{
|
|
type: EnvironmentInjector
|
|
}], null);
|
|
})();
|
|
var HttpFeatureKind;
|
|
(function(HttpFeatureKind2) {
|
|
HttpFeatureKind2[HttpFeatureKind2["Interceptors"] = 0] = "Interceptors";
|
|
HttpFeatureKind2[HttpFeatureKind2["LegacyInterceptors"] = 1] = "LegacyInterceptors";
|
|
HttpFeatureKind2[HttpFeatureKind2["CustomXsrfConfiguration"] = 2] = "CustomXsrfConfiguration";
|
|
HttpFeatureKind2[HttpFeatureKind2["NoXsrfProtection"] = 3] = "NoXsrfProtection";
|
|
HttpFeatureKind2[HttpFeatureKind2["JsonpSupport"] = 4] = "JsonpSupport";
|
|
HttpFeatureKind2[HttpFeatureKind2["RequestsMadeViaParent"] = 5] = "RequestsMadeViaParent";
|
|
HttpFeatureKind2[HttpFeatureKind2["Fetch"] = 6] = "Fetch";
|
|
})(HttpFeatureKind || (HttpFeatureKind = {}));
|
|
function makeHttpFeature(kind, providers) {
|
|
return {
|
|
ɵkind: kind,
|
|
ɵproviders: providers
|
|
};
|
|
}
|
|
function provideHttpClient(...features) {
|
|
if (ngDevMode) {
|
|
const featureKinds = new Set(features.map((f) => f.ɵkind));
|
|
if (featureKinds.has(HttpFeatureKind.NoXsrfProtection) && featureKinds.has(HttpFeatureKind.CustomXsrfConfiguration)) {
|
|
throw new Error(ngDevMode ? `Configuration error: found both withXsrfConfiguration() and withNoXsrfProtection() in the same call to provideHttpClient(), which is a contradiction.` : "");
|
|
}
|
|
}
|
|
const providers = [HttpClient, HttpXhrBackend, HttpInterceptorHandler, {
|
|
provide: HttpHandler,
|
|
useExisting: HttpInterceptorHandler
|
|
}, {
|
|
provide: HttpBackend,
|
|
useFactory: () => {
|
|
return inject(FETCH_BACKEND, {
|
|
optional: true
|
|
}) ?? inject(HttpXhrBackend);
|
|
}
|
|
}, {
|
|
provide: HTTP_INTERCEPTOR_FNS,
|
|
useValue: xsrfInterceptorFn,
|
|
multi: true
|
|
}, {
|
|
provide: XSRF_ENABLED,
|
|
useValue: true
|
|
}, {
|
|
provide: HttpXsrfTokenExtractor,
|
|
useClass: HttpXsrfCookieExtractor
|
|
}];
|
|
for (const feature of features) {
|
|
providers.push(...feature.ɵproviders);
|
|
}
|
|
return makeEnvironmentProviders(providers);
|
|
}
|
|
function withInterceptors(interceptorFns) {
|
|
return makeHttpFeature(HttpFeatureKind.Interceptors, interceptorFns.map((interceptorFn) => {
|
|
return {
|
|
provide: HTTP_INTERCEPTOR_FNS,
|
|
useValue: interceptorFn,
|
|
multi: true
|
|
};
|
|
}));
|
|
}
|
|
var LEGACY_INTERCEPTOR_FN = new InjectionToken(ngDevMode ? "LEGACY_INTERCEPTOR_FN" : "");
|
|
function withInterceptorsFromDi() {
|
|
return makeHttpFeature(HttpFeatureKind.LegacyInterceptors, [{
|
|
provide: LEGACY_INTERCEPTOR_FN,
|
|
useFactory: legacyInterceptorFnFactory
|
|
}, {
|
|
provide: HTTP_INTERCEPTOR_FNS,
|
|
useExisting: LEGACY_INTERCEPTOR_FN,
|
|
multi: true
|
|
}]);
|
|
}
|
|
function withXsrfConfiguration({
|
|
cookieName,
|
|
headerName
|
|
}) {
|
|
const providers = [];
|
|
if (cookieName !== void 0) {
|
|
providers.push({
|
|
provide: XSRF_COOKIE_NAME,
|
|
useValue: cookieName
|
|
});
|
|
}
|
|
if (headerName !== void 0) {
|
|
providers.push({
|
|
provide: XSRF_HEADER_NAME,
|
|
useValue: headerName
|
|
});
|
|
}
|
|
return makeHttpFeature(HttpFeatureKind.CustomXsrfConfiguration, providers);
|
|
}
|
|
function withNoXsrfProtection() {
|
|
return makeHttpFeature(HttpFeatureKind.NoXsrfProtection, [{
|
|
provide: XSRF_ENABLED,
|
|
useValue: false
|
|
}]);
|
|
}
|
|
function withJsonpSupport() {
|
|
return makeHttpFeature(HttpFeatureKind.JsonpSupport, [JsonpClientBackend, {
|
|
provide: JsonpCallbackContext,
|
|
useFactory: jsonpCallbackContext
|
|
}, {
|
|
provide: HTTP_INTERCEPTOR_FNS,
|
|
useValue: jsonpInterceptorFn,
|
|
multi: true
|
|
}]);
|
|
}
|
|
function withRequestsMadeViaParent() {
|
|
return makeHttpFeature(HttpFeatureKind.RequestsMadeViaParent, [{
|
|
provide: HttpBackend,
|
|
useFactory: () => {
|
|
const handlerFromParent = inject(HttpHandler, {
|
|
skipSelf: true,
|
|
optional: true
|
|
});
|
|
if (ngDevMode && handlerFromParent === null) {
|
|
throw new Error("withRequestsMadeViaParent() can only be used when the parent injector also configures HttpClient");
|
|
}
|
|
return handlerFromParent;
|
|
}
|
|
}]);
|
|
}
|
|
function withFetch() {
|
|
return makeHttpFeature(HttpFeatureKind.Fetch, [FetchBackend, {
|
|
provide: FETCH_BACKEND,
|
|
useExisting: FetchBackend
|
|
}, {
|
|
provide: HttpBackend,
|
|
useExisting: FetchBackend
|
|
}]);
|
|
}
|
|
var HttpClientXsrfModule = class _HttpClientXsrfModule {
|
|
/**
|
|
* Disable the default XSRF protection.
|
|
*/
|
|
static disable() {
|
|
return {
|
|
ngModule: _HttpClientXsrfModule,
|
|
providers: [withNoXsrfProtection().ɵproviders]
|
|
};
|
|
}
|
|
/**
|
|
* Configure XSRF protection.
|
|
* @param options An object that can specify either or both
|
|
* cookie name or header name.
|
|
* - Cookie name default is `XSRF-TOKEN`.
|
|
* - Header name default is `X-XSRF-TOKEN`.
|
|
*
|
|
*/
|
|
static withOptions(options = {}) {
|
|
return {
|
|
ngModule: _HttpClientXsrfModule,
|
|
providers: withXsrfConfiguration(options).ɵproviders
|
|
};
|
|
}
|
|
static ɵfac = function HttpClientXsrfModule_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpClientXsrfModule)();
|
|
};
|
|
static ɵmod = ɵɵdefineNgModule({
|
|
type: _HttpClientXsrfModule
|
|
});
|
|
static ɵinj = ɵɵdefineInjector({
|
|
providers: [HttpXsrfInterceptor, {
|
|
provide: HTTP_INTERCEPTORS,
|
|
useExisting: HttpXsrfInterceptor,
|
|
multi: true
|
|
}, {
|
|
provide: HttpXsrfTokenExtractor,
|
|
useClass: HttpXsrfCookieExtractor
|
|
}, withXsrfConfiguration({
|
|
cookieName: XSRF_DEFAULT_COOKIE_NAME,
|
|
headerName: XSRF_DEFAULT_HEADER_NAME
|
|
}).ɵproviders, {
|
|
provide: XSRF_ENABLED,
|
|
useValue: true
|
|
}]
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientXsrfModule, [{
|
|
type: NgModule,
|
|
args: [{
|
|
providers: [HttpXsrfInterceptor, {
|
|
provide: HTTP_INTERCEPTORS,
|
|
useExisting: HttpXsrfInterceptor,
|
|
multi: true
|
|
}, {
|
|
provide: HttpXsrfTokenExtractor,
|
|
useClass: HttpXsrfCookieExtractor
|
|
}, withXsrfConfiguration({
|
|
cookieName: XSRF_DEFAULT_COOKIE_NAME,
|
|
headerName: XSRF_DEFAULT_HEADER_NAME
|
|
}).ɵproviders, {
|
|
provide: XSRF_ENABLED,
|
|
useValue: true
|
|
}]
|
|
}]
|
|
}], null, null);
|
|
})();
|
|
var HttpClientModule = class _HttpClientModule {
|
|
static ɵfac = function HttpClientModule_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpClientModule)();
|
|
};
|
|
static ɵmod = ɵɵdefineNgModule({
|
|
type: _HttpClientModule
|
|
});
|
|
static ɵinj = ɵɵdefineInjector({
|
|
providers: [provideHttpClient(withInterceptorsFromDi())]
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientModule, [{
|
|
type: NgModule,
|
|
args: [{
|
|
/**
|
|
* Configures the dependency injector where it is imported
|
|
* with supporting services for HTTP communications.
|
|
*/
|
|
providers: [provideHttpClient(withInterceptorsFromDi())]
|
|
}]
|
|
}], null, null);
|
|
})();
|
|
var HttpClientJsonpModule = class _HttpClientJsonpModule {
|
|
static ɵfac = function HttpClientJsonpModule_Factory(__ngFactoryType__) {
|
|
return new (__ngFactoryType__ || _HttpClientJsonpModule)();
|
|
};
|
|
static ɵmod = ɵɵdefineNgModule({
|
|
type: _HttpClientJsonpModule
|
|
});
|
|
static ɵinj = ɵɵdefineInjector({
|
|
providers: [withJsonpSupport().ɵproviders]
|
|
});
|
|
};
|
|
(() => {
|
|
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientJsonpModule, [{
|
|
type: NgModule,
|
|
args: [{
|
|
providers: [withJsonpSupport().ɵproviders]
|
|
}]
|
|
}], null, null);
|
|
})();
|
|
|
|
// node_modules/@angular/common/fesm2022/http.mjs
|
|
var httpResource = (() => {
|
|
const jsonFn = makeHttpResourceFn("json");
|
|
jsonFn.arrayBuffer = makeHttpResourceFn("arraybuffer");
|
|
jsonFn.blob = makeHttpResourceFn("blob");
|
|
jsonFn.text = makeHttpResourceFn("text");
|
|
return jsonFn;
|
|
})();
|
|
function makeHttpResourceFn(responseType) {
|
|
return function httpResource2(request, options) {
|
|
if (ngDevMode && !options?.injector) {
|
|
assertInInjectionContext(httpResource2);
|
|
}
|
|
const injector = options?.injector ?? inject(Injector);
|
|
return new HttpResourceImpl(injector, () => normalizeRequest(request, responseType), options?.defaultValue, options?.parse, options?.equal);
|
|
};
|
|
}
|
|
function normalizeRequest(request, responseType) {
|
|
let unwrappedRequest = typeof request === "function" ? request() : request;
|
|
if (unwrappedRequest === void 0) {
|
|
return void 0;
|
|
} else if (typeof unwrappedRequest === "string") {
|
|
unwrappedRequest = { url: unwrappedRequest };
|
|
}
|
|
const headers = unwrappedRequest.headers instanceof HttpHeaders ? unwrappedRequest.headers : new HttpHeaders(unwrappedRequest.headers);
|
|
const params = unwrappedRequest.params instanceof HttpParams ? unwrappedRequest.params : new HttpParams({ fromObject: unwrappedRequest.params });
|
|
return new HttpRequest(unwrappedRequest.method ?? "GET", unwrappedRequest.url, unwrappedRequest.body ?? null, {
|
|
headers,
|
|
params,
|
|
reportProgress: unwrappedRequest.reportProgress,
|
|
withCredentials: unwrappedRequest.withCredentials,
|
|
keepalive: unwrappedRequest.keepalive,
|
|
cache: unwrappedRequest.cache,
|
|
priority: unwrappedRequest.priority,
|
|
mode: unwrappedRequest.mode,
|
|
redirect: unwrappedRequest.redirect,
|
|
responseType,
|
|
context: unwrappedRequest.context,
|
|
transferCache: unwrappedRequest.transferCache,
|
|
credentials: unwrappedRequest.credentials,
|
|
referrer: unwrappedRequest.referrer,
|
|
integrity: unwrappedRequest.integrity,
|
|
timeout: unwrappedRequest.timeout
|
|
});
|
|
}
|
|
var HttpResourceImpl = class extends ResourceImpl {
|
|
client;
|
|
_headers = linkedSignal({
|
|
source: this.extRequest,
|
|
computation: () => void 0
|
|
});
|
|
_progress = linkedSignal({
|
|
source: this.extRequest,
|
|
computation: () => void 0
|
|
});
|
|
_statusCode = linkedSignal({
|
|
source: this.extRequest,
|
|
computation: () => void 0
|
|
});
|
|
headers = computed(() => this.status() === "resolved" || this.status() === "error" ? this._headers() : void 0, ...ngDevMode ? [{ debugName: "headers" }] : []);
|
|
progress = this._progress.asReadonly();
|
|
statusCode = this._statusCode.asReadonly();
|
|
constructor(injector, request, defaultValue, parse, equal) {
|
|
super(request, ({ params: request2, abortSignal }) => {
|
|
let sub;
|
|
const onAbort = () => sub.unsubscribe();
|
|
abortSignal.addEventListener("abort", onAbort);
|
|
const stream = signal({ value: void 0 }, ...ngDevMode ? [{ debugName: "stream" }] : []);
|
|
let resolve;
|
|
const promise = new Promise((r) => resolve = r);
|
|
const send = (value) => {
|
|
stream.set(value);
|
|
resolve?.(stream);
|
|
resolve = void 0;
|
|
};
|
|
sub = this.client.request(request2).subscribe({
|
|
next: (event) => {
|
|
switch (event.type) {
|
|
case HttpEventType.Response:
|
|
this._headers.set(event.headers);
|
|
this._statusCode.set(event.status);
|
|
try {
|
|
send({ value: parse ? parse(event.body) : event.body });
|
|
} catch (error) {
|
|
send({ error: encapsulateResourceError(error) });
|
|
}
|
|
break;
|
|
case HttpEventType.DownloadProgress:
|
|
this._progress.set(event);
|
|
break;
|
|
}
|
|
},
|
|
error: (error) => {
|
|
if (error instanceof HttpErrorResponse) {
|
|
this._headers.set(error.headers);
|
|
this._statusCode.set(error.status);
|
|
}
|
|
send({ error });
|
|
abortSignal.removeEventListener("abort", onAbort);
|
|
},
|
|
complete: () => {
|
|
if (resolve) {
|
|
send({
|
|
error: new RuntimeError(991, ngDevMode && "Resource completed before producing a value")
|
|
});
|
|
}
|
|
abortSignal.removeEventListener("abort", onAbort);
|
|
}
|
|
});
|
|
return promise;
|
|
}, defaultValue, equal, injector);
|
|
this.client = injector.get(HttpClient);
|
|
}
|
|
set(value) {
|
|
super.set(value);
|
|
this._headers.set(void 0);
|
|
this._progress.set(void 0);
|
|
this._statusCode.set(void 0);
|
|
}
|
|
};
|
|
var HTTP_TRANSFER_CACHE_ORIGIN_MAP = new InjectionToken(ngDevMode ? "HTTP_TRANSFER_CACHE_ORIGIN_MAP" : "");
|
|
var BODY = "b";
|
|
var HEADERS = "h";
|
|
var STATUS = "s";
|
|
var STATUS_TEXT = "st";
|
|
var REQ_URL = "u";
|
|
var RESPONSE_TYPE = "rt";
|
|
var CACHE_OPTIONS = new InjectionToken(ngDevMode ? "HTTP_TRANSFER_STATE_CACHE_OPTIONS" : "");
|
|
var ALLOWED_METHODS = ["GET", "HEAD"];
|
|
function transferCacheInterceptorFn(req, next) {
|
|
const _a = inject(CACHE_OPTIONS), { isCacheActive } = _a, globalOptions = __objRest(_a, ["isCacheActive"]);
|
|
const { transferCache: requestOptions, method: requestMethod } = req;
|
|
if (!isCacheActive || requestOptions === false || // POST requests are allowed either globally or at request level
|
|
requestMethod === "POST" && !globalOptions.includePostRequests && !requestOptions || requestMethod !== "POST" && !ALLOWED_METHODS.includes(requestMethod) || // Do not cache request that require authorization when includeRequestsWithAuthHeaders is falsey
|
|
!globalOptions.includeRequestsWithAuthHeaders && hasAuthHeaders(req) || globalOptions.filter?.(req) === false) {
|
|
return next(req);
|
|
}
|
|
const transferState = inject(TransferState);
|
|
const originMap = inject(HTTP_TRANSFER_CACHE_ORIGIN_MAP, {
|
|
optional: true
|
|
});
|
|
if (originMap) {
|
|
throw new RuntimeError(2803, ngDevMode && "Angular detected that the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token is configured and present in the client side code. Please ensure that this token is only provided in the server code of the application.");
|
|
}
|
|
const requestUrl = false ? mapRequestOriginUrl(req.url, originMap) : req.url;
|
|
const storeKey = makeCacheKey(req, requestUrl);
|
|
const response = transferState.get(storeKey, null);
|
|
let headersToInclude = globalOptions.includeHeaders;
|
|
if (typeof requestOptions === "object" && requestOptions.includeHeaders) {
|
|
headersToInclude = requestOptions.includeHeaders;
|
|
}
|
|
if (response) {
|
|
const { [BODY]: undecodedBody, [RESPONSE_TYPE]: responseType, [HEADERS]: httpHeaders, [STATUS]: status, [STATUS_TEXT]: statusText, [REQ_URL]: url } = response;
|
|
let body = undecodedBody;
|
|
switch (responseType) {
|
|
case "arraybuffer":
|
|
body = new TextEncoder().encode(undecodedBody).buffer;
|
|
break;
|
|
case "blob":
|
|
body = new Blob([undecodedBody]);
|
|
break;
|
|
}
|
|
let headers = new HttpHeaders(httpHeaders);
|
|
if (typeof ngDevMode === "undefined" || ngDevMode) {
|
|
headers = appendMissingHeadersDetection(req.url, headers, headersToInclude ?? []);
|
|
}
|
|
return of(new HttpResponse({
|
|
body,
|
|
headers,
|
|
status,
|
|
statusText,
|
|
url
|
|
}));
|
|
}
|
|
const event$ = next(req);
|
|
if (false) {
|
|
return event$.pipe(tap((event) => {
|
|
if (event instanceof HttpResponse) {
|
|
transferState.set(storeKey, {
|
|
[BODY]: event.body,
|
|
[HEADERS]: getFilteredHeaders(event.headers, headersToInclude),
|
|
[STATUS]: event.status,
|
|
[STATUS_TEXT]: event.statusText,
|
|
[REQ_URL]: requestUrl,
|
|
[RESPONSE_TYPE]: req.responseType
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
return event$;
|
|
}
|
|
function hasAuthHeaders(req) {
|
|
return req.headers.has("authorization") || req.headers.has("proxy-authorization");
|
|
}
|
|
function sortAndConcatParams(params) {
|
|
return [...params.keys()].sort().map((k) => `${k}=${params.getAll(k)}`).join("&");
|
|
}
|
|
function makeCacheKey(request, mappedRequestUrl) {
|
|
const { params, method, responseType } = request;
|
|
const encodedParams = sortAndConcatParams(params);
|
|
let serializedBody = request.serializeBody();
|
|
if (serializedBody instanceof URLSearchParams) {
|
|
serializedBody = sortAndConcatParams(serializedBody);
|
|
} else if (typeof serializedBody !== "string") {
|
|
serializedBody = "";
|
|
}
|
|
const key = [method, responseType, mappedRequestUrl, serializedBody, encodedParams].join("|");
|
|
const hash = generateHash(key);
|
|
return makeStateKey(hash);
|
|
}
|
|
function generateHash(value) {
|
|
let hash = 0;
|
|
for (const char of value) {
|
|
hash = Math.imul(31, hash) + char.charCodeAt(0) << 0;
|
|
}
|
|
hash += 2147483647 + 1;
|
|
return hash.toString();
|
|
}
|
|
function withHttpTransferCache(cacheOptions) {
|
|
return [
|
|
{
|
|
provide: CACHE_OPTIONS,
|
|
useFactory: () => {
|
|
performanceMarkFeature("NgHttpTransferCache");
|
|
return __spreadValues({ isCacheActive: true }, cacheOptions);
|
|
}
|
|
},
|
|
{
|
|
provide: HTTP_ROOT_INTERCEPTOR_FNS,
|
|
useValue: transferCacheInterceptorFn,
|
|
multi: true
|
|
},
|
|
{
|
|
provide: APP_BOOTSTRAP_LISTENER,
|
|
multi: true,
|
|
useFactory: () => {
|
|
const appRef = inject(ApplicationRef);
|
|
const cacheState = inject(CACHE_OPTIONS);
|
|
return () => {
|
|
appRef.whenStable().then(() => {
|
|
cacheState.isCacheActive = false;
|
|
});
|
|
};
|
|
}
|
|
}
|
|
];
|
|
}
|
|
function appendMissingHeadersDetection(url, headers, headersToInclude) {
|
|
const warningProduced = /* @__PURE__ */ new Set();
|
|
return new Proxy(headers, {
|
|
get(target, prop) {
|
|
const value = Reflect.get(target, prop);
|
|
const methods = /* @__PURE__ */ new Set(["get", "has", "getAll"]);
|
|
if (typeof value !== "function" || !methods.has(prop)) {
|
|
return value;
|
|
}
|
|
return (headerName) => {
|
|
const key = (prop + ":" + headerName).toLowerCase();
|
|
if (!headersToInclude.includes(headerName) && !warningProduced.has(key)) {
|
|
warningProduced.add(key);
|
|
const truncatedUrl = truncateMiddle(url);
|
|
console.warn(formatRuntimeError(2802, `Angular detected that the \`${headerName}\` header is accessed, but the value of the header was not transferred from the server to the client by the HttpTransferCache. To include the value of the \`${headerName}\` header for the \`${truncatedUrl}\` request, use the \`includeHeaders\` list. The \`includeHeaders\` can be defined either on a request level by adding the \`transferCache\` parameter, or on an application level by adding the \`httpCacheTransfer.includeHeaders\` argument to the \`provideClientHydration()\` call. `));
|
|
}
|
|
return value.apply(target, [headerName]);
|
|
};
|
|
}
|
|
});
|
|
}
|
|
|
|
export {
|
|
HttpHandler,
|
|
HttpBackend,
|
|
HttpHeaders,
|
|
HttpUrlEncodingCodec,
|
|
HttpParams,
|
|
HttpContextToken,
|
|
HttpContext,
|
|
HttpRequest,
|
|
HttpEventType,
|
|
HttpResponseBase,
|
|
HttpHeaderResponse,
|
|
HttpResponse,
|
|
HttpErrorResponse,
|
|
HttpStatusCode,
|
|
HttpClient,
|
|
FetchBackend,
|
|
HTTP_INTERCEPTORS,
|
|
HTTP_ROOT_INTERCEPTOR_FNS,
|
|
REQUESTS_CONTRIBUTE_TO_STABILITY,
|
|
HttpInterceptorHandler,
|
|
JsonpClientBackend,
|
|
JsonpInterceptor,
|
|
HttpXhrBackend,
|
|
HttpXsrfTokenExtractor,
|
|
HttpFeatureKind,
|
|
provideHttpClient,
|
|
withInterceptors,
|
|
withInterceptorsFromDi,
|
|
withXsrfConfiguration,
|
|
withNoXsrfProtection,
|
|
withJsonpSupport,
|
|
withRequestsMadeViaParent,
|
|
withFetch,
|
|
HttpClientXsrfModule,
|
|
HttpClientModule,
|
|
HttpClientJsonpModule,
|
|
httpResource,
|
|
HTTP_TRANSFER_CACHE_ORIGIN_MAP,
|
|
withHttpTransferCache
|
|
};
|
|
/*! Bundled license information:
|
|
|
|
@angular/common/fesm2022/module.mjs:
|
|
@angular/common/fesm2022/http.mjs:
|
|
(**
|
|
* @license Angular v20.2.4
|
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
* License: MIT
|
|
*)
|
|
*/
|
|
//# sourceMappingURL=chunk-5DRVFSXL.js.map
|