@@ -9,11 +9,18 @@ import {
9
9
IRequestOptions ,
10
10
InternalRequestOptions
11
11
} from "./utils/IRequestOptions.js" ;
12
+ import {
13
+ isNoCorsDomain ,
14
+ isNoCorsRequestRequired ,
15
+ registerNoCorsDomains ,
16
+ sendNoCorsRequest
17
+ } from "./utils/sendNoCorsRequest.js" ;
12
18
import { IParams } from "./utils/IParams.js" ;
13
19
import { warn } from "./utils/warn.js" ;
14
20
import { IRetryAuthError } from "./utils/retryAuthError.js" ;
15
21
import { getFetch } from "@esri/arcgis-rest-fetch" ;
16
22
import { IAuthenticationManager } from "./index.js" ;
23
+ import { isSameOrigin } from "./utils/isSameOrigin.js" ;
17
24
18
25
export const NODEJS_DEFAULT_REFERER_HEADER = `@esri/arcgis-rest-js` ;
19
26
@@ -250,6 +257,11 @@ export function internalRequest(
250
257
credentials : options . credentials || "same-origin"
251
258
} ;
252
259
260
+ // Is this a no-cors domain? if so we need to set credentials to include
261
+ if ( isNoCorsDomain ( url ) ) {
262
+ fetchOptions . credentials = "include" ;
263
+ }
264
+
253
265
// the /oauth2/platformSelf route will add X-Esri-Auth-Client-Id header
254
266
// and that request needs to send cookies cross domain
255
267
// so we need to set the credentials to "include"
@@ -296,26 +308,55 @@ export function internalRequest(
296
308
// query params are applied.
297
309
const originalUrl = url ;
298
310
299
- return (
300
- authentication
301
- ? authentication . getToken ( url ) . catch ( ( err ) => {
302
- /**
303
- * append original request url and requestOptions
304
- * to the error thrown by getToken()
305
- * to assist with retrying
306
- */
307
- err . url = url ;
308
- err . options = options ;
309
- /**
310
- * if an attempt is made to talk to an unfederated server
311
- * first try the request anonymously. if a 'token required'
312
- * error is thrown, throw the UNFEDERATED error then.
313
- */
314
- originalAuthError = err ;
315
- return Promise . resolve ( "" ) ;
316
- } )
317
- : Promise . resolve ( "" )
318
- )
311
+ // default to false, for nodejs
312
+ let sameOrigin = false ;
313
+ // if we are in a browser, check if the url is same origin
314
+ /* istanbul ignore else */
315
+ if ( typeof window !== "undefined" ) {
316
+ sameOrigin = isSameOrigin ( url ) ;
317
+ }
318
+ const requiresNoCors = ! sameOrigin && isNoCorsRequestRequired ( url ) ;
319
+
320
+ // the /oauth2/platformSelf route will add X-Esri-Auth-Client-Id header
321
+ // and that request needs to send cookies cross domain
322
+ // so we need to set the credentials to "include"
323
+ if (
324
+ options . headers &&
325
+ options . headers [ "X-Esri-Auth-Client-Id" ] &&
326
+ url . indexOf ( "/oauth2/platformSelf" ) > - 1
327
+ ) {
328
+ fetchOptions . credentials = "include" ;
329
+ }
330
+
331
+ // Simple first promise that we may turn into the no-cors request
332
+ let firstPromise = Promise . resolve ( ) ;
333
+ if ( requiresNoCors ) {
334
+ // ensure we send cookies on the request after
335
+ fetchOptions . credentials = "include" ;
336
+ firstPromise = sendNoCorsRequest ( url ) ;
337
+ }
338
+
339
+ return firstPromise
340
+ . then ( ( ) =>
341
+ authentication
342
+ ? authentication . getToken ( url ) . catch ( ( err ) => {
343
+ /**
344
+ * append original request url and requestOptions
345
+ * to the error thrown by getToken()
346
+ * to assist with retrying
347
+ */
348
+ err . url = url ;
349
+ err . options = options ;
350
+ /**
351
+ * if an attempt is made to talk to an unfederated server
352
+ * first try the request anonymously. if a 'token required'
353
+ * error is thrown, throw the UNFEDERATED error then.
354
+ */
355
+ originalAuthError = err ;
356
+ return Promise . resolve ( "" ) ;
357
+ } )
358
+ : Promise . resolve ( "" )
359
+ )
319
360
. then ( ( token ) => {
320
361
if ( token . length ) {
321
362
params . token = token ;
@@ -350,7 +391,8 @@ export function internalRequest(
350
391
351
392
if (
352
393
// This would exceed the maximum length for URLs by 2000 as default or as specified by the consumer and requires POST
353
- ( options . maxUrlLength && urlWithQueryString . length > options . maxUrlLength ) ||
394
+ ( options . maxUrlLength &&
395
+ urlWithQueryString . length > options . maxUrlLength ) ||
354
396
( ! options . maxUrlLength && urlWithQueryString . length > 2000 ) ||
355
397
// Or if the customer requires the token to be hidden and it has not already been hidden in the header (for browsers)
356
398
( params . token && options . hideToken )
@@ -484,6 +526,15 @@ export function internalRequest(
484
526
originalAuthError
485
527
) ;
486
528
529
+ // If this was a portal/self call, and we got authorizedNoCorsDomains back
530
+ // register them
531
+ if ( data && / \/ s h a r i n g \/ r e s t \/ ( a c c o u n t s | p o r t a l s ) \/ s e l f / i. test ( url ) ) {
532
+ // if we have a list of no-cors domains, register them
533
+ if ( Array . isArray ( data . authorizedCrossOriginNoCorsDomains ) ) {
534
+ registerNoCorsDomains ( data . authorizedCrossOriginNoCorsDomains ) ;
535
+ }
536
+ }
537
+
487
538
if ( originalAuthError ) {
488
539
/* If the request was made to an unfederated service that
489
540
didn't require authentication, add the base url and a dummy token
0 commit comments