@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 9.55 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import e from"../config.js";import{id as t}from"../kernel.js";import r from"../core/Error.js";import has from"../core/has.js";import{clone as s}from"../core/lang.js";import{isAbortError as o,createAbortError as a,isAborted as n}from"../core/promiseUtils.js";import{isTrustedServer as i,getOrigin as l,isBlobProtocol as u,isDataProtocol as c,toHTTPS as d,objectToQuery as m,getProxyRule as p,getProxyUrl as f,addQueryParameters as h,hasSameOrigin as y,addProxyRule as g,getAppUrl as w}from"../core/urlUtils.js";import{isSecureProxyService as b}from"../portal/support/urlUtils.js";import{requestConfig as T}from"./config.js";import{registerNoCorsDomains as k,isNoCorsRequestRequired as q,sendNoCorsRequest as S}from"./cors.js";import{getImageType as O,ImageWithType as C}from"./ImageWithType.js";import{loadImage as x}from"./loadImage.js";import{setPreferredHost as j,getPreferredUrl as v}from"./preferredHosts.js";const L="FormData"in globalThis,E=new Set([499,498,403,401]),U=new Set(["COM_0056","COM_0057","SB_0008"]),A=[/\/arcgis\/tokens/i,/\/sharing(\/rest)?\/generatetoken/i,/\/rest\/info/i];async function P(r){let s,o;await H(r);try{do{[s,o]=await I(r)}while(!await W(r,s,o))}catch(u){const e=_("request:server",u,r.parameters,s);throw e.details.ssl=r.useSSL,r.interceptor?.error?.(e),e}const a=r.parameters.url;if(o)if(/\/sharing\/rest\/(accounts|portals)\/self/i.test(a)){if(!r.hasToken&&!r.credentialToken&&o.user?.username&&!i(a)){const t=l(a,!0);t&&e.request.trustedServers.push(t)}Array.isArray(o.authorizedCrossOriginNoCorsDomains)&&k(o.authorizedCrossOriginNoCorsDomains)}else{"json"===(r.parameters.requestOptions.responseType||"json")&&j(a,o)}const n=r.credential;if(n&&t){const e=t.findServerInfo(n.server);let r=e?.owningSystemUrl;if(r){r=r.replace(/\/?$/,"/sharing");const e=t.findCredential(r,n.userId);e&&-1===t._getIdenticalSvcIdx(r,e)&&e.resources.unshift(r)}}return{data:o,getAllHeaders:s?()=>Array.from(s.headers):G,getHeader:s?e=>s.headers.get(e):G,httpStatus:s?.status??200,requestOptions:r.parameters.requestOptions,ssl:r.useSSL,url:r.parameters.url}}async function H(r){const s=r.parameters.url,o=r.parameters.requestOptions,a=r.controller.signal,i=o.body;let l=null,u=null;if(L&&"HTMLFormElement"in globalThis&&(i instanceof FormData?l=i:i instanceof HTMLFormElement&&(l=new FormData(i))),"string"==typeof i&&(u=i),r.fetchOptions={cache:o.cacheMode??(o.cacheBust?"no-cache":"default"),credentials:"same-origin",headers:o.headers||{},keepalive:o.keepAlive??!1,method:"head"===o.method?"HEAD":"GET",mode:"cors",priority:o.priority??e.request.priority,redirect:"follow",signal:a},(l||u)&&(r.fetchOptions.body=l||u),(T.isForeignWorker||"anonymous"===o.authMode)&&(r.useIdentity=!1),r.hasToken=!!(/token=/i.test(s)||o.query?.token||l?.get("token")),!r.hasToken){const{getApiKey:e,getSessionToken:t}=await import("../support/apiKeyUtils.js"),a=await t(s)??e(s);a&&(o.query??={},o.query.token=a,r.hasToken=!0)}if(r.useIdentity&&!r.hasToken&&!r.credential&&!r.credentialToken&&!N(s)&&!n(a)){let e;"immediate"===o.authMode?(await R(),e=await t.getCredential(s,{signal:a})):"no-prompt"===o.authMode?(await R(),e=await t.getCredential(s,{prompt:!1,signal:a}).catch(()=>{})):t&&(e=t.findCredential(s)),e&&(r.credential=e,r.credentialToken=e.token,r.useSSL=!!e.ssl)}}async function I(r){let s=r.parameters.url,o=v(s);const n=r.parameters.requestOptions,k=r.fetchOptions??{},x=u(s)||c(s),j=n.responseType??"json",E="image"===j&&n.imageWithType,U=x?0:null!=n.timeout?n.timeout:e.request.timeout;let A=!1;if(!x){r.useSSL&&(s=d(s));let a={...n.query};r.credentialToken&&(a.token=r.credentialToken);let l=m(a);has("esri-url-encodes-apostrophe")&&(l=l.replaceAll("'","%27"));const u=o.length+1+l.length;let c;A="delete"===n.method||"post"===n.method||"put"===n.method||!!n.body||u>e.request.maxUrlLength;const g=n.useProxy||!!p(s);if(g){const t=f(s);c=t.path,!A&&c.length+1+u>e.request.maxUrlLength&&(A=!0),t.query&&(a={...t.query,...a})}if("HEAD"===k.method&&(A||g)){if(A){if(u>e.request.maxUrlLength)throw _("request:invalid-parameters",new Error("URL exceeds maximum length"),r.parameters);throw _("request:invalid-parameters",new Error("cannot use POST request when method is 'head'"),r.parameters)}if(g)throw _("request:invalid-parameters",new Error("cannot use proxy when method is 'head'"),r.parameters)}if(A?(k.method="delete"===n.method?"DELETE":"put"===n.method?"PUT":"POST",n.body?s=h(s,a):(k.body=m(a),k.headers||(k.headers={}),k.headers["Content-Type"]="application/x-www-form-urlencoded")):s=h(s,a),g&&(r.useProxy=!0,s=`${c}?${s}`),a.token&&L&&k.body instanceof FormData&&!b(s)&&k.body.set("token",a.token),n.hasOwnProperty("withCredentials"))r.withCredentials=n.withCredentials;else if(!y(s,w()))if(i(s))r.withCredentials=!0;else if(t){const e=t.findServerInfo(s);e?.webTierAuth&&(r.withCredentials=!0)}r.withCredentials&&(k.credentials="include",q(s)&&await S(A?h(s,a):s)),o=v(s)}let P,H,R=0,N=!1;U>0&&(R=setTimeout(()=>{N=!0,r.controller.abort()},U));try{if("native-request-init"===n.responseType)H=k,H.url=o,n.signal?H.signal=n.signal:delete H.signal;else if("image"!==n.responseType||"default"!==k.cache||k.keepalive||"GET"!==k.method||A||B(n.headers)||!x&&!r.useProxy&&e.request.proxyUrl&&!F(s)){if(await(T.beforeFetch?.(s,k)),P=await fetch(o,k),await(T.afterFetch?.(P)),r.useProxy||D(s),"native"===n.responseType)H=P;else if("HEAD"!==k.method)if(P.ok){switch(j){case"array-buffer":H=await P.arrayBuffer();break;case"blob":H=await P.blob();break;case"image":H=await(E?P.arrayBuffer():P.blob());break;default:H=await P.text()}if(R&&(clearTimeout(R),R=0),"json"===j||"xml"===j||"document"===j)if(H)switch(j){case"json":H=JSON.parse(H);break;case"xml":H=$(H,"application/xml");break;case"document":H=$(H,"text/html")}else H=null;if(H){if(("array-buffer"===j||"blob"===j)&&H["blob"===j?"size":"byteLength"]<=750)try{const e=await new Response(H).json();e.error&&(H=e)}catch{}if(E&&H instanceof ArrayBuffer){const e=O(H);if("unknown"===e)return n.responseType="image",await I(r);H=await P.blob(),H=await M(URL.createObjectURL(H),r,!0),H=new C(H,e)}"image"===j&&H instanceof Blob&&(H=await M(URL.createObjectURL(H),r,!0))}}else{H=await P.text();try{H=JSON.parse(H)}catch{}}}else H=await M(o,r)}catch(W){if("AbortError"===W.name){if(N)throw K();throw a("Request canceled")}if(!(!P&&W instanceof TypeError&&e.request.proxyUrl)||n.body||"delete"===n.method||"head"===n.method||"post"===n.method||"put"===n.method||r.useProxy||F(s))throw W;r.redoRequest=!0,g({proxyUrl:e.request.proxyUrl,urlPrefix:l(s)??""})}finally{R&&clearTimeout(R)}return[P,H]}function M(t,r,s=!1){const o=r.controller.signal,a=new Image;return r.withCredentials?a.crossOrigin="use-credentials":a.crossOrigin="anonymous",a.alt="",a.fetchPriority=e.request.priority,a.src=t,x(a,t,s,o)}function D(e){const t=l(e);t&&!T.corsServers.includes(t)&&T.corsServers.push(t)}function F(e){const t=l(e);return!t||t.endsWith(".arcgis.com")||T.corsServers.includes(t)||i(t)}async function R(){t||await import("../identity/IdentityManager.js")}function N(e){return A.some(t=>t.test(e))}function B(e){if(e)for(const t of Object.getOwnPropertyNames(e))if(e[t])return!0;return!1}function $(e,t){let r;try{r=(new DOMParser).parseFromString(e,t)}catch{}if(!r||r.getElementsByTagName("parsererror").length)throw new SyntaxError("XML Parse error");return r}async function W(e,r,s){if(e.redoRequest)return e.redoRequest=!1,!1;const o=e.parameters.requestOptions;if(!r||"native"===o.responseType||"native-request-init"===o.responseType)return!0;let a,n;if(s&&(s.error&&"object"==typeof s.error?a=s.error:"error"===s.status&&Array.isArray(s.messages)&&(a={...s},a[z]=s,a.details=s.messages)),!a&&!r.ok)throw a=new Error(`Unable to load ${r.url} status: ${r.status}`),a[z]=s,a;let i,l=null;a&&(n=Number(a.code),l=a.hasOwnProperty("subcode")?Number(a.subcode):null,i=a.messageCode,i=i?.toUpperCase());const u=o.authMode;if(403===n&&(4===l||a.message?.toLowerCase().includes("ssl")&&!a.message.toLowerCase().includes("permission"))){if(!e.useSSL)return e.useSSL=!0,!1}else if(!e.hasToken&&e.useIdentity&&("no-prompt"!==u||498===n)&&void 0!==n&&E.has(n)&&!N(e.parameters.url)&&(403!==n||(!i||!U.has(i))&&(null==l||2===l&&e.credentialToken))){await R();try{const r=await t.getCredential(e.parameters.url,{error:_("request:server",a,e.parameters),credential:e.credential,prompt:"no-prompt"!==u,signal:e.controller.signal,token:e.credentialToken});return e.credential=r,e.credentialToken=r.token,e.useSSL=e.useSSL||r.ssl,!1}catch(c){if("no-prompt"===u)return e.credential=void 0,e.credentialToken=void 0,!1;a=c}}if(a)throw a;return!0}function _(e,t,n,i){let l;const u={url:n.url,requestOptions:n.requestOptions,getAllHeaders:G,getHeader:G,ssl:!1};if(t instanceof r)return t.details?(t.details=s(t.details),t.details.url=n.url,t.details.requestOptions=n.requestOptions):t.details=u,t;if(t){const e=i&&(()=>Array.from(i.headers)),r=i&&(e=>i.headers.get(e)),s=i?.status,o=t.message;o&&(l=o),e&&r&&(u.getAllHeaders=e,u.getHeader=r),u.httpStatus=(null!=t.httpCode?t.httpCode:t.code)||s||0,u.subCode=t.subcode,u.messageCode=t.messageCode,"string"==typeof t.details?(u.messages=[t.details],l??=t.details):(u.messages=t.details,l??=u.messages?.[0]),u.raw=z in t?t[z]:t}return l??="Error",o(t)?a():new r(e,l,u)}const z=Symbol(),G=()=>null,J="Timeout exceeded";function K(){return new Error(J)}function X(e){return"object"==typeof e&&!!e&&"message"in e&&e.message===J}export{_ as createRequestError,X as isTimeoutError,P as processRequest};