2017-07-07 51 views
0

我在使用model.save時遇到了問題,因爲我的跨域請求無法返回cookie,但Ext.Ajax.request沒有問題發回cookies。在我們的本地開發工作中,我們覆蓋了對所有Ajax請求(其中包括模型操作)的beforerequest,以設置withCredentials = trueuseDefaultXhrHeader = false,這有助於在正常的Ext.Ajax.request上使用CORS。Ext.Ajax.request vs model.save跨源數據庫

據我所知,ajax類型的代理類似於做Ext.Ajax.request,這很明顯,因爲model.save碰到beforerequest(你會在下面的例子中看到這個)。在這個例子中,你還會注意到model.save首先發送一個OPTIONS調用,然後永遠不會跟進POST(但這很可能是因爲服務器)......無論哪種方式,OPTIONS而不是POST似乎有點兒腥。

這裏的example

Ext.Ajax.on({ 
    beforerequest: function (conn, options, eOpts) { 
     console.log('here', conn, options) 
     options.useDefaultXhrHeader = false; 
     options.withCredentials = true; 
    } 
}); 
Ext.define('MyModel', { 
    extend: 'Ext.data.Model', 
    fields: ['test'], 
    proxy: { 
     type: 'ajax', 
     url: 'https://docs.sencha.com' 
    } 
}); 
var model = Ext.create('MyModel'); 
// This will fire off an OPTIONS call and not send the cookies 
model.save(); 
// This will fire off with the POST and send the cookies 
Ext.Ajax.request({ 
    url: 'https://docs.sencha.com', 
    method: 'POST' 
}); 

有沒有什麼辦法讓model.save到Cookies發送到跨域?

回答

2

不,您無法繞過OPTIONS請求。

一旦您向POST請求添加有效內容,瀏覽器就會開始發送OPTIONS請求,例如model.save()。這也正好,如果你改變你的Ext.Ajax.request操作稍有匹配model.save操作:

// This will fire off an OPTIONS request. 
Ext.Ajax.request({ 
    url: 'https://docs.sencha.com', 
    method: 'POST', 
    jsonData: {id: "MyModel-1"} 
}); 

OPTIONS請求是所謂的「預檢要求」,旨在從服務器獲取信息的服務器是否被允許實際的跨源請求。服務器必須積極回答,包括包含一組CORS標頭的Http Response Headers。 docs.sencha.com確實回答OPTIONS請求,但它不返回所需的頭,讓你在瀏覽器控制檯找到的錯誤消息:

的XMLHttpRequest無法加載https://docs.sencha.com/?_dc=1499412133932。請求的資源上沒有「Access-Control-Allow-Origin」標題。因此不允許訪問原產地'https://fiddle.sencha.com'。

作爲一個反例,我啓用了CORS,後端發送給客戶端以下標題:

Access-Control-Allow-Origin: * 
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS 
Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, X-Requested-With 
  • Origin包含從CORS請求所有域可以發送或*所有域。
  • Methods包含所有允許的方法,您至少需要OPTIONS, POST
  • Headers包含您的請求可能發送到服務器的所有標題。 Chrome控制檯會告訴您您是否缺少瀏覽器期望的內容;至少這就是我得到我的名單。

如果這些條件都滿足上OPTIONS請求,實際POST請求將被髮送;否則,您將在瀏覽器控制檯中找到所述錯誤消息。

+0

我不明白爲什麼我們不能讓這種行爲像一個正常的Ajax請求......它清楚地使用普通Ajax請求的部分,那麼到底是什麼使這個循規蹈矩不同?這是有效載荷的處理方式嗎?我們不能將模型的標題更改爲表單數據嗎? – incutonez

0

感謝Mitchell Simoens在Sencha Forums上,他幫我找出了問題的根源,這是代理的作者。我需要創建一個自定義作家來解決這個問題。

Fiddle

Ext.define('Ux.data.writer.Json', { 
    extend : 'Ext.data.writer.Json', 
    alias : 'writer.ux-json', 

    config : { 
     /** 
     * @cfg {Boolean} useJsonData 
     * If {@link #allowSingle} is `true` and only one model is being 
     * saved, this will control if the request will set the data using 
     * `params` or `jsonData`. 
     */ 
     useJsonData : false 
    }, 

    writeRecords: function(request, data) { 
     var me = this, 
      root = me.getRootProperty(), 
      transform = this.getTransform(), 
      json, single; 

     if (me.getExpandData()) { 
      data = me.getExpandedData(data); 
     } 

     if (me.getAllowSingle() && data.length === 1) { 
      // convert to single object format 
      data = data[0]; 
      single = true; 
     } 

     if (transform) { 
      data = transform(data, request); 
     } 

     if (me.getEncode()) { 
      if (root) { 
       // sending as a param, need to encode 
       request.setParam(root, Ext.encode(data)); 
      } else { 
       //<debug> 
       Ext.raise('Must specify a root when using encode'); 
       //</debug> 
      } 
     } else if (single && !me.getUseJsonData()) { 
      request.setParams(Ext.apply(request.getParams(), data)); 
     } else if (single || (data && data.length)) { 
      // send as jsonData 
      json = request.getJsonData() || {}; 

      if (root) { 
       json[root] = data; 
      } else { 
       json = data; 
      } 

      request.setJsonData(json); 
     } 

     return request; 
    } 
}); 

Ext.Ajax.on({ 
    beforerequest: function (conn, options, eOpts) { 
     console.log(options.url, options); 

     options.useDefaultXhrHeader = false; 
     options.withCredentials = true; 
    } 
}); 

Ext.define('MyModel', { 
    extend: 'Ext.data.Model', 
    fields: ['blah'], 
    proxy: { 
     type: 'ajax', 
     url: 'https://docs.sencha.com', 
     writer: { 
      type: 'ux-json' 
     } 
    } 
}); 

var model = Ext.create('MyModel', { 
    blah : 2 
}); 
model.save(); 

Ext.Ajax.request({ 
    url: 'https://docs.sencha.com', 
    method: 'POST', 
    params: { 
     blah: 1 
    } 
}); 
+0

我試圖重現,併發送一個OPTIONS請求:https://fiddle.sencha.com/#view/editor&fiddle/22ps https://i.imgur.com/mctp6JO.png – Alexander

+0

您沒有完全重現它......如果你添加'useDefaultXhrHeader = false'和'withCredentials = true',它會起作用,但這裏還有另一個問題,我試圖弄清楚......這一切都歸結爲模型的作者並修改它將確實解決整個問題......當我有更好的解決方案時,我會報告回來。 – incutonez