richiesta di origine Croce con SproutCore in IE9

voti
1

Sto cercando di costruire un'applicazione web basata su SproutCore 1.8. Per recuperare i dati da un server l'applicazione invia richieste CORS a un servizio Web REST in esecuzione su un dominio separato.

Il codice per questo appare come il seguente:

var request = SC.Request.getUrl('http://example.com/some/path');
request.set('attachIdentifyingHeaders', NO);    
request.json().notify(this, this.didFetchData).send();

Questa grande opera in Chrome, Safari e Firefox, ma non funziona in Internet Explorer 9. In realtà, IE9 si imbatte in un errore JavaScript Accesso negato per l'attuazione richiesta interna di SproutCore. L'errore viene generato in questa linea:

// initiate request.
rawRequest.open(this.get('type'), this.get('address'), async);

Dopo qualche breve indagine ho scoperto che Microsoft ha implementato un oggetto XDomainRequest dedicato per le richieste CORS in IE9. Questo non sembra essere supportata da SproutCore come deduco da queste linee (SproutCore selezione implementazione nativa richiesta):

return tryThese(
  function() { return new XMLHttpRequest(); },
  function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
  function() { return new ActiveXObject('Microsoft.XMLHTTP'); }
);

Si tratta di una lacuna di SproutCore o mi sto perdendo qualcosa? Se è così, avete qualche suggerimento su come avrei potuto risolvere il problema senza scrivere il mio richiesta astrazione?

Si noti che CORS è un requisito delle infrastrutture server esistente sto lavorando con. Posso né mettere il servizio nello stesso dominio del server consegna il Cliente nè posso risolvere il problema con una roba reverse proxy o simili infrastrutture.

È pubblicato 24/04/2012 alle 10:24
fonte dall'utente
In altre lingue...                            


2 risposte

voti
2

Sono disponibili due opzioni

1) Hack Sproutcore stessa. Si potrebbe provare ad aggiungere

function() {return new XDomainRequest(); }

a quella lista di mezzi di trasporto differenza XHR. Aggiungilo prima; se è disponibile sul browser verrà utilizzato, in caso contrario il codice ricade agli altri oggetti.

2) Se non si desidera modificare la fonte SC, è possibile creare la propria App.CorsResponseclasse che estende SC.XHRResponse. Nella tua implementazione, fornire il proprio createRequestmetodo e faccio quello che ho detto in 1). Ogni volta che si crea una richiesta, specificare l' responseClassessere l'implementazione personalizzata.

Risposto il 24/04/2012 a 11:10
fonte dall'utente

voti
1

Ho subito codificato una soluzione basata su suggerimento hvgotcodes'. Il seguente codice implementa una sottoclasse SC.XHRResponseche aggiunge la funzionalità necessaria per la gestione di IE-specifiche richieste XDomainRequest CORS. Si noti che questo non gestisce gli errori in IE quando si utilizza XDomainRequest ancora.

MyApp.CorsRequest = SC.XHRResponse.extend({
  createRequest: function() {
    function tryThese() {
      for (var i=0; i < arguments.length; i++) {
        try {
          var item = arguments[i]();
          return item;
        } catch (e) {}
      }
      return NO;
    }

    return tryThese(
      function() { return new XDomainRequest(); },
      function() { return new XMLHttpRequest(); },
      function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
      function() { return new ActiveXObject('Microsoft.XMLHTTP'); }
    );
  },

  invokeTransport: function() {
    var rawRequest, transport, handleReadyStateChange, async, headers;

    rawRequest = this.createRequest();
    this.set('rawRequest', rawRequest);

    // configure async callback - differs per browser...
    async = !!this.getPath('request.isAsynchronous');

    if (async) {
      if (!SC.browser.isIE && !SC.browser.isOpera) {
        SC.Event.add(rawRequest, 'readystatechange', this,
                     this.finishRequest, rawRequest);
      } else if(SC.browser.isIE) {
           transport = this;
        handleLoad = function() {
          if (!transport) { return null; }
          var ret = transport.finishRequest();
          if (ret) { transport = null; }
          return ret;
        };
        rawRequest.onload = handleLoad;          
      } else {
        transport = this;
        handleReadyStateChange = function() {
          if (!transport) { return null; }
          var ret = transport.finishRequest();
          if (ret) { transport = null; }
          return ret;
        };
        rawRequest.onreadystatechange = handleReadyStateChange;
      }
    }

    // initiate request.
    rawRequest.open(this.get('type'), this.get('address'), async);

    // now send the actual request body - for sync requests browser will
    // block here
    rawRequest.send(this.getPath('request.encodedBody')) ;
    if (!async) { this.finishRequest(); }

    return rawRequest;
  }, 

  finishRequest: function(evt) {
    var rawRequest = this.get('rawRequest'),
        readyState = rawRequest.readyState,
        error, status, msg;

       if (SC.browser.isIE) {
            readyState = 4;
            rawRequest.status = 200;
       }       

    if (readyState === 4 && !this.get('timedOut')) {
      this.receive(function(proceed) {
        if (!proceed) { return; }

        // collect the status and decide if we're in an error state or not
        status = -1;
        try {
          status = rawRequest.status || 0;
        } catch (e) {}

        // if there was an error - setup error and save it
        if ((status < 200) || (status >= 300)) {

          try {
            msg = rawRequest.statusText || '';
          } catch(e2) {
            msg = '';
          }

          error = SC.$error(msg || "HTTP Request failed", "Request", status);
          error.set("errorValue", this) ;
          this.set('isError', YES);
          this.set('errorObject', error);
        }

        // set the status - this will trigger changes on related properties
        this.set('status', status);
      }, this);

      // Avoid memory leaks
      if (!SC.browser.isIE && !SC.browser.isOpera) {
        SC.Event.remove(rawRequest, 'readystatechange', this, this.finishRequest);
      } else {
           if (window.XDomainRequest)
                rawRequest.onload = null;
           else
             rawRequest.onreadystatechange = null;
      }

      return YES;
    }
    return NO;
  } 
});
Risposto il 24/04/2012 a 13:43
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more