text: import { _SPFlight } from '@microsoft/sp-core-library';
  import GraphHttpClientContext from '../graphHttpClient/GraphHttpClientContext';
  import HttpClientHelper from '../httpClient/HttpClientHelper';
  import ODataVersion from './ODataVersion';
  import SPHttpClientResponse from './SPHttpClientResponse';
  import AadTokenProviders from '../oauthTokenProvider/AadTokenProviders';
  import SPConstants from './SPConstants';
  /**
   * Private - this class contains some internal code shared between SPHttpClient
   * and SPHttpClientBatch.
   */
  var SPHttpClientHelper = /** @class */ (function () {
      function SPHttpClientHelper() {
      }
      SPHttpClientHelper.cloneHeaders = function (options) {
          var clonedHeaders = new Headers();
          var temp = new Request('', { headers: options.headers || {} });
          temp.headers.forEach(function (value, name) {
              clonedHeaders.append(name, value); // note name/value are reversed
          });
          return clonedHeaders;
      };
      SPHttpClientHelper.applyDefaultHeaders = function (headers, configuration, options, oDataVersion) {
          // Add some default headers that people should specify for any REST query,
          // assuming it's not missing
          if (configuration.jsonRequest) {
              if (options.method && options.method.toUpperCase() !== 'GET') {
                  if (!headers.has('Content-Type')) {
                      // Assume our POST data is in JSON format unless otherwise specified.
                      // Also explicitly specify utf-8 (the default).
                      if (oDataVersion === ODataVersion.v3) {
                          headers.append('Content-Type', 'application/json;odata=verbose;charset=utf-8');
                      }
                      else if (oDataVersion === ODataVersion.v4) {
                          headers.append('Content-Type', 'application/json;charset=utf-8');
                      }
                      else {
                          // oDataVersion can also be undefined, if the version is unknown
                          throw new Error('ISPHttpClientConfiguration.jsonRequest is enabled, which requires'
                              + ' the "OData-Version" header to be 3.0 or 4.0');
                      }
                  }
              }
          }
          if (configuration.jsonResponse) {
              if (!headers.has('Accept')) {
                  if (oDataVersion === ODataVersion.v3) {
                      headers.append('Accept', 'application/json');
                  }
                  else if (oDataVersion === ODataVersion.v4) {
                      // Request for the OData response to be 'minimal' (the default).  The guidance:
                      // "If a client prefers a very small wire size and is intelligent enough to
                      // compute data using metadata expressions, the Accept header should include
                      // odata.metadata=minimal. If compute is more expensive than wire size or the
                      // client is incapable of computing control information, odata.metadata=full
                      // directs the service to inline the control information that normally would be
                      // computed from metadata expressions in the payload. odata.metadata=none is an
                      // option for clients that have out-of-band knowledge or don't require control
                      // information."
                      // http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html
                      headers.append('Accept', 'application/json;odata.metadata=minimal');
                  }
                  else {
                      // oDataVersion can also be undefined, if the version is unknown
                      throw new Error('ISPHttpClientConfiguration.jsonResponse is enabled, which requires'
                          + ' the "OData-Version" header to be 3.0 or 4.0');
                  }
              }
          }
      };
      /**
       * Use a heuristic to infer the base URL for authentication.
       *
       * @remarks
       * Attempts to infer the SPWeb URL associated with the provided REST URL, by looking
       * for common SharePoint path components such as "_api", "_layouts", or "_vit_bin".
       * This is necessary for operations such as the X-RequestDigest
       * and ODATA batching, which require POSTing to a separate REST endpoint
       * in order to complete a request.
       *
       * For example, if the requestUrl is "/sites/site/web/_api/service",
       * the returned URL would be "/sites/site/web".  Or if the requestUrl
       * is "http://example.com/_layouts/service", the returned URL would be
       * "http://example.com".
       *
       * If the URL cannot be determined, an exception is thrown.
       *
       * @param requestUrl - The URL for a SharePoint REST service
       * @returns the inferred SPWeb URL
       */
      SPHttpClientHelper.getWebUrlFromRequestUrl = function (requestUrl) {
          // First we need to guess the webUrl by looking for a reserved
          // segment such as "_api":
          var segmentIndex = -1;
          var upperCaseUrl = requestUrl.toUpperCase();
          for (var _i = 0, _a = SPConstants.RESERVED_URL_SEGMENTS; _i < _a.length; _i++) {
              var reservedUrlSegment = _a[_i];
              segmentIndex = upperCaseUrl.indexOf(reservedUrlSegment);
              if (segmentIndex >= 0) {
                  return requestUrl.substr(0, segmentIndex);
              }
          }
          throw new Error('Unable to determine web URL');
      };
      /**
       * All network requests are routed through this method, which calls the
       * underlying IFetchProvider.fetch().
       */
      SPHttpClientHelper.fetchCore = function (url, configuration, options, serviceScope, digestCache, fetchProvider, logSourceId) {
          return Promise.resolve().then(function () {
              if (!options) {
                  options = {};
              }
              var modifiedOptions = Object.assign({}, options);
              if (configuration.defaultSameOriginCredentials) {
                  // Set the default credentials
                  if (!options.credentials) {
                      modifiedOptions.credentials = 'same-origin';
                  }
              }
              // NOTE: RequestInit.cache is apparently currently unimplemented in Chrome
              // and our polyfill, so we don't specify it here.
              var headers = SPHttpClientHelper.cloneHeaders(options);
              modifiedOptions.headers = headers;
              if (configuration.defaultODataVersion) {
                  if (!headers.has('OData-Version')) {
                      headers.append('OData-Version', configuration.defaultODataVersion.toString());
                  }
              }
              // If the header is omitted, the SharePoint server defaults to version 3.0 in most cases
              // (but maybe not all cases?).  Rather than trying to guess, we will simply leave
              // oDataVersion as undefined, and report an error e.g. if ISPHttpClientConfiguration.jsonRequest
              // needs to know the OData version.
              var oDataVersion = ODataVersion.tryParseFromHeaders(headers);
              SPHttpClientHelper.applyDefaultHeaders(headers, configuration, options, oDataVersion);
              if (configuration.requestDigest) {
                  // NOTE: If options.method is missing, the default is GET
                  if (options.method) {
                      var method = options.method.toUpperCase();
                      if (method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS') {
                          // For writes, SharePoint requires an "X-RequestDigest" header.
                          if (!headers.has('X-RequestDigest')) {
                              var webUrl = options.webUrl || SPHttpClientHelper.getWebUrlFromRequestUrl(url);
                              // Now fetch the digest
                              var promise = digestCache.fetchDigest(webUrl)
                                  .then(function (digest) {
                                  headers.append('X-RequestDigest', digest);
                                  return SPHttpClientHelper._fetchWithInstrumentation(configuration, new Request(url, modifiedOptions), serviceScope, fetchProvider, logSourceId);
                              });
                              return SPHttpClientHelper.handleAuthenticationErrors(promise, webUrl, digestCache)
                                  .then(function (response) {
                                  return new SPHttpClientResponse(response);
                              });
                          }
                      }
                  }
              }
              // Otherwise, don't fetch a digest, don't handle authentication errors
              return SPHttpClientHelper._fetchWithInstrumentation(configuration, new Request(url, modifiedOptions), serviceScope, fetchProvider, logSourceId)
                  .then(function (response) {
                  return new SPHttpClientResponse(response);
              });
          });
      };
      /**
       * For both SPHttpClient and SPHttpClientBatch, we fetch a digest and then use it to
       * to make a REST call.  If the REST fails in a way that the digest is invalid,
       * we need to discard the bad digest.  This function is the common implementation
       * of that logic, in case we need to add special cases in the future.
       *
       * @param promise       - the promise returned by IFetchProvider.fetch()
       * @param webUrl        - the cache key to clear
       * @param digestCache   - the cache
       * @returns             - the promise after this logic is applied
       */
      SPHttpClientHelper.handleAuthenticationErrors = function (promise, webUrl, digestCache) {
          return promise.then(function (response) {
              // If the response is 403, this could be because our digest was invalidated
              // before its natural expiration time.  In this case, we should clear the
              // cache so that next time we will fetch a new digest.
              if (response.status === 403) {
                  digestCache.clearDigest(webUrl);
              }
              return response;
          });
      };
      SPHttpClientHelper.overrideHttpMethod = function (options, httpRequestMethod) {
          return HttpClientHelper.overrideHttpMethod(options, httpRequestMethod);
      };
      SPHttpClientHelper._fetchWithInstrumentation = function (configuration, request, serviceScope, fetchProvider, logSourceId) {
          return SPHttpClientHelper._handleFluidEnvironment(request, serviceScope)
              .then(function (modifiedRequest) {
              return HttpClientHelper.fetchCore(configuration, modifiedRequest, serviceScope, fetchProvider, SPConstants.SP_HTTP_CLIENT_CLASS_NAME_FETCH);
          });
      };
      SPHttpClientHelper._isFluid = function () {
          return SPConstants.FLUID_DOMAINS.indexOf(window.location.host) > -1;
      };
      SPHttpClientHelper._handleFluidEnvironment = function (request, serviceScope) {
          if (_SPFlight.isEnabled(SPConstants.SP_TOKEN_FOR_FLUID_ID) && SPHttpClientHelper._isFluid()) {
              var graphContext = serviceScope.consume(GraphHttpClientContext.serviceKey);
              return AadTokenProviders.configurable._getTokenInternal(new URL(graphContext.getWebAbsoluteUrl()).origin, AadTokenProviders.preAuthorizedConfiguration)
                  .then(function (token) {
                  request.headers.set('Authorization', 'Bearer ' + token);
                  return request;
              });
          }
          return Promise.resolve(request);
      };
      return SPHttpClientHelper;
  }());
  export default SPHttpClientHelper;
  //# sourceMappingURL=SPHttpClientHelper.js.map