@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 11.8 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import e from"./config.js";import{id as r}from"./kernel.js";import t from"./core/Error.js";import has from"./core/has.js";import{clone as s}from"./core/lang.js";import{getOrCreateMapValue as o}from"./core/MapUtils.js";import{onAbort as n,createAbortError as a,isAbortError as i,isAborted as l}from"./core/promiseUtils.js";import{queryToObject as u,isDataProtocol as c,isBlobProtocol as d,normalize as p,getInterceptor as m,isTrustedServer as h,getOrigin as f,toHTTPS as y,objectToQuery as w,getProxyRule as g,getProxyUrl as q,addQueryParameters as b,hasSameOrigin as S,addProxyRule as T,getAppUrl as k}from"./core/urlUtils.js";import{isHostedAgolService as O}from"./layers/support/arcgisLayerUrl.js";import{isSecureProxyService as v}from"./portal/support/urlUtils.js";import{getApiKey as C}from"./support/apiKeyUtils.js";import{registerNoCorsDomains as x,setPreferredHost as L,getPreferredUrl as j,isNoCorsRequestRequired as E,sendNoCorsRequest as U,createTimeoutError as P,loadImageAsync as A}from"./support/requestUtils.js";async function H(e,r){e instanceof URL&&(e=e.toString()),r?.query instanceof URLSearchParams&&(r.query=u(r.query.toString().replaceAll("+"," ")));const t=c(e),s=d(e);s||t||(e=p(e));const o={url:e,requestOptions:{...r}},a=e=>({data:e,getAllHeaders:B,getHeader:B,httpStatus:200,requestOptions:o.requestOptions,url:o.url}),i=m(e,_.internalInterceptors);if(i){const e=await Y(i,o);if(null!=e)return a(e)}let l=m(e);if(l){const e=await Y(l,o);if(null!=e)return a(e);l.after||l.error||(l=null)}if(e=o.url,"image"===(r=o.requestOptions).responseType&&(has("host-webworker")||has("host-node")))throw W("request:invalid-parameters",new Error("responseType 'image' is not supported in Web Workers or Node environment"),o);if("head"===r.method){if(r.body)throw W("request:invalid-parameters",new Error("body parameter cannot be set when method is 'head'"),o);if(t||s)throw W("request:invalid-parameters",new Error("data and blob URLs are not supported for method 'head'"),o)}if(await G(),M)return M.execute(e,r);const h=new AbortController,f=n(r,(()=>h.abort())),y={controller:h,credential:void 0,credentialToken:void 0,fetchOptions:void 0,hasToken:!1,interceptor:l,params:o,redoRequest:!1,useIdentity:_.useIdentity,useProxy:!1,useSSL:!1,withCredentials:!1},w=r.useRequestQueue?te(y):se(y),g=await w.finally((()=>f?.remove()));return l?.after?.(g),g}let M,R=!1;const _=e.request,D="FormData"in globalThis,F=new Set([499,498,403,401]),I=new Set(["COM_0056","COM_0057","SB_0008"]),N=[/\/arcgis\/tokens/i,/\/sharing(\/rest)?\/generatetoken/i,/\/rest\/info/i],B=()=>null,$=Symbol();function z(e){const r=f(e);r&&!H._corsServers.includes(r)&&H._corsServers.push(r)}function Q(e){const r=f(e);return!r||r.endsWith(".arcgis.com")||H._corsServers.includes(r)||h(r)}function W(e,r,o,n){let l;const u={url:o.url,requestOptions:o.requestOptions,getAllHeaders:B,getHeader:B,ssl:!1};if(r instanceof t)return r.details?(r.details=s(r.details),r.details.url=o.url,r.details.requestOptions=o.requestOptions):r.details=u,r;if(r){const e=n&&(()=>Array.from(n.headers)),t=n&&(e=>n.headers.get(e)),s=n?.status,o=r.message;o&&(l=o),e&&t&&(u.getAllHeaders=e,u.getHeader=t),u.httpStatus=(null!=r.httpCode?r.httpCode:r.code)||s||0,u.subCode=r.subcode,u.messageCode=r.messageCode,"string"==typeof r.details?(u.messages=[r.details],l??=r.details):(u.messages=r.details,l??=u.messages?.[0]),u.raw=$ in r?r[$]:r}return l??="Error",i(r)?a():new t(e,l,u)}async function G(){has("host-webworker")&&(!M&&globalThis.invokeStaticMessage?M=await import("./core/workers/request.js"):R=!0)}async function J(){r||await import("./identity/IdentityManager.js")}async function K(e){const t=e.params.url,s=e.params.requestOptions,o=e.controller.signal,n=s.body;let a=null,i=null;if(D&&"HTMLFormElement"in globalThis&&(n instanceof FormData?a=n:n instanceof HTMLFormElement&&(a=new FormData(n))),"string"==typeof n&&(i=n),e.fetchOptions={cache:s.cacheBust?"no-cache":"default",credentials:"same-origin",headers:s.headers||{},method:"head"===s.method?"HEAD":"GET",mode:"cors",priority:_.priority,redirect:"follow",signal:o},(a||i)&&(e.fetchOptions.body=a||i),(R||"anonymous"===s.authMode)&&(e.useIdentity=!1),e.hasToken=!!(/token=/i.test(t)||s.query?.token||a?.get("token")),!e.hasToken){const r=C(t);r&&(s.query??={},s.query.token=r,e.hasToken=!0)}if(e.useIdentity&&!e.hasToken&&!e.credential&&!e.credentialToken&&!X(t)&&!l(o)){let n;"immediate"===s.authMode?(await J(),n=await r.getCredential(t,{signal:o})):"no-prompt"===s.authMode?(await J(),n=await r.getCredential(t,{prompt:!1,signal:o}).catch((()=>{}))):r&&(n=r.findCredential(t)),n&&(e.credential=n,e.credentialToken=n.token,e.useSSL=!!n.ssl)}}function X(e){return N.some((r=>r.test(e)))}async function V(e){let t=e.params.url,s=j(t);const o=e.params.requestOptions,n=e.fetchOptions??{},i=d(t)||c(t),l=o.responseType||"json",u=i?0:null!=o.timeout?o.timeout:_.timeout;let p=!1;if(!i){e.useSSL&&(t=y(t));let a={...o.query};e.credentialToken&&(a.token=e.credentialToken);let i=w(a);has("esri-url-encodes-apostrophe")&&(i=i.replaceAll("'","%27"));const l=s.length+1+i.length;let u;p="delete"===o.method||"post"===o.method||"put"===o.method||!!o.body||l>_.maxUrlLength;const c=o.useProxy||!!g(t);if(c){const e=q(t);u=e.path,!p&&u.length+1+l>_.maxUrlLength&&(p=!0),e.query&&(a={...e.query,...a})}if("HEAD"===n.method&&(p||c)){if(p){if(l>_.maxUrlLength)throw W("request:invalid-parameters",new Error("URL exceeds maximum length"),e.params);throw W("request:invalid-parameters",new Error("cannot use POST request when method is 'head'"),e.params)}if(c)throw W("request:invalid-parameters",new Error("cannot use proxy when method is 'head'"),e.params)}if(p?(n.method="delete"===o.method?"DELETE":"put"===o.method?"PUT":"POST",o.body?t=b(t,a):(n.body=w(a),n.headers||(n.headers={}),n.headers["Content-Type"]="application/x-www-form-urlencoded")):t=b(t,a),c&&(e.useProxy=!0,t=`${u}?${t}`),a.token&&D&&n.body instanceof FormData&&!v(t)&&n.body.set("token",a.token),o.hasOwnProperty("withCredentials"))e.withCredentials=o.withCredentials;else if(!S(t,k()))if(h(t))e.withCredentials=!0;else if(r){const s=r.findServerInfo(t);s?.webTierAuth&&(e.withCredentials=!0)}e.withCredentials&&(n.credentials="include",E(t)&&await U(p?b(t,a):t)),s=j(t)}let m,O,C=0,x=!1;u>0&&(C=setTimeout((()=>{x=!0,e.controller.abort()}),u));try{if("native-request-init"===o.responseType)O=n,O.url=s,o.signal?O.signal=o.signal:delete O.signal;else if("image"!==o.responseType||"default"!==n.cache||"GET"!==n.method||p||Z(o.headers)||!i&&!e.useProxy&&_.proxyUrl&&!Q(t)){if(H._beforeFetch&&await H._beforeFetch(t,n),m=await fetch(s,n),H._afterFetch&&await H._afterFetch(m),e.useProxy||z(t),"native"===o.responseType)O=m;else if("HEAD"!==n.method)if(m.ok){switch(l){case"array-buffer":O=await m.arrayBuffer();break;case"blob":case"image":O=await m.blob();break;default:O=await m.text()}if(C&&(clearTimeout(C),C=0),"json"===l||"xml"===l||"document"===l)if(O)switch(l){case"json":O=JSON.parse(O);break;case"xml":O=ee(O,"application/xml");break;case"document":O=ee(O,"text/html")}else O=null;if(O){if("array-buffer"===l||"blob"===l){const e=m.headers.get("Content-Type");if(e&&/application\/json|text\/plain/i.test(e)&&O["blob"===l?"size":"byteLength"]<=750)try{const e=await new Response(O).json();e.error&&(O=e)}catch{}}"image"===l&&O instanceof Blob&&(O=await ne(URL.createObjectURL(O),e,!0))}}else{O=await m.text();try{O=JSON.parse(O)}catch{}}}else O=await ne(s,e)}catch(L){if("AbortError"===L.name){if(x)throw P();throw a("Request canceled")}if(!(!m&&L instanceof TypeError&&_.proxyUrl)||o.body||"delete"===o.method||"head"===o.method||"post"===o.method||"put"===o.method||e.useProxy||Q(t))throw L;e.redoRequest=!0,T({proxyUrl:_.proxyUrl,urlPrefix:f(t)??""})}finally{C&&clearTimeout(C)}return[m,O]}async function Y(e,r){if(null!=e.responseData)return e.responseData;if(e.headers&&(r.requestOptions.headers={...r.requestOptions.headers,...e.headers}),e.query&&(r.requestOptions.query={...r.requestOptions.query,...e.query}),e.before){let o,n;try{n=await e.before(r)}catch(s){o=W("request:interceptor",s,r)}if((n instanceof Error||n instanceof t)&&(o=W("request:interceptor",n,r)),o)throw e.error&&e.error(o),o;return n}}function Z(e){if(e)for(const r of Object.getOwnPropertyNames(e))if(e[r])return!0;return!1}function ee(e,r){let t;try{t=(new DOMParser).parseFromString(e,r)}catch{}if(!t||t.getElementsByTagName("parsererror").length)throw new SyntaxError("XML Parse error");return t}H._corsServers=["https://server.arcgisonline.com","https://services.arcgisonline.com"],H._beforeFetch=void 0,H._afterFetch=void 0;const re=new Map;async function te(e){const r=ae(e.params.url);if(!r)return se(e);const{QueueProcessor:t}=await import("./core/QueueProcessor.js"),s=o(re,r.origin,(()=>{const e=r.isHosted?has("request-queue-concurrency-hosted"):has("request-queue-concurrency-non-hosted");return new t({concurrency:e,process:e=>{if(l(e.params.requestOptions))throw W("",a("Request canceled"),e.params);return se(e)}})}));return s.push(e)}async function se(e){let t,s;await K(e);try{do{[t,s]=await V(e)}while(!await oe(e,t,s))}catch(a){const r=W("request:server",a,e.params,t);throw r.details.ssl=e.useSSL,e.interceptor?.error&&e.interceptor.error(r),r}const o=e.params.url;if(s)if(/\/sharing\/rest\/(accounts|portals)\/self/i.test(o)){if(!e.hasToken&&!e.credentialToken&&s.user?.username&&!h(o)){const e=f(o,!0);e&&_.trustedServers.push(e)}Array.isArray(s.authorizedCrossOriginNoCorsDomains)&&x(s.authorizedCrossOriginNoCorsDomains)}else{"json"===(e.params.requestOptions.responseType||"json")&&L(o,s)}const n=e.credential;if(n&&r){const e=r.findServerInfo(n.server);let t=e?.owningSystemUrl;if(t){t=t.replace(/\/?$/,"/sharing");const e=r.findCredential(t,n.userId);e&&-1===r._getIdenticalSvcIdx(t,e)&&e.resources.unshift(t)}}return{data:s,getAllHeaders:t?()=>Array.from(t.headers):B,getHeader:t?e=>t.headers.get(e):B,httpStatus:t?.status??200,requestOptions:e.params.requestOptions,ssl:e.useSSL,url:e.params.url}}async function oe(e,t,s){if(e.redoRequest)return e.redoRequest=!1,!1;const o=e.params.requestOptions;if(!t||"native"===o.responseType||"native-request-init"===o.responseType)return!0;let n,a;if(s&&(s.error&&"object"==typeof s.error?n=s.error:"error"===s.status&&Array.isArray(s.messages)&&(n={...s},n[$]=s,n.details=s.messages)),!n&&!t.ok)throw n=new Error(`Unable to load ${t.url} status: ${t.status}`),n[$]=s,n;let i,l=null;n&&(a=Number(n.code),l=n.hasOwnProperty("subcode")?Number(n.subcode):null,i=n.messageCode,i=i?.toUpperCase());const u=o.authMode;if(403===a&&(4===l||n.message?.toLowerCase().includes("ssl")&&!n.message.toLowerCase().includes("permission"))){if(!e.useSSL)return e.useSSL=!0,!1}else if(!e.hasToken&&e.useIdentity&&("no-prompt"!==u||498===a)&&void 0!==a&&F.has(a)&&!X(e.params.url)&&(403!==a||(!i||!I.has(i))&&(null==l||2===l&&e.credentialToken))){await J();try{const t=await r.getCredential(e.params.url,{error:W("request:server",n,e.params),credential:e.credential,prompt:"no-prompt"!==u,signal:e.controller.signal,token:e.credentialToken});return e.credential=t,e.credentialToken=t.token,e.useSSL=e.useSSL||t.ssl,!1}catch(c){if("no-prompt"===u)return e.credential=void 0,e.credentialToken=void 0,!1;n=c}}if(n)throw n;return!0}function ne(e,r,t=!1){const s=r.controller.signal,o=new Image;return r.withCredentials?o.crossOrigin="use-credentials":o.crossOrigin="anonymous",o.alt="",o.fetchPriority=_.priority,o.src=e,A(o,e,t,s)}function ae(e){let r,t;return"string"==typeof e?(r=f(e,!0),t=O(e)):(r=e.origin,t=O(e.toString())),null==r?null:{origin:r,isHosted:t}}export{H as default};