2017-04-18 149 views
2

在制作CORS请求时出现以下错误。有趣的是,这是在safari中工作,但不是在谷歌浏览器和Firefox。我一直在浏览所有内容,但没有在网络上找到任何解决方案。

我想发送json到服务器,但据我所知我需要将它发送到服务器之前,因此我使用JSON.stringify字符串,但最终我期待json结果从服务器。

这就是我正在卷曲的电话。 (我只是去尝试看看头)

HTTP/1.1 200 OK 
Date: Tue, 18 Apr 2017 15:13:04 GMT 
Server: Apache 
Access-Control-Allow-Origin: * 
Access-Control-Allow-Headers: Content-Type 
Access-Control-Allow-Methods: POST, OPTIONS 
Access-Control-Max-Age: 21600 
Content-Length: 213 
Content-Type: application/json 

,这就是我在Chrome中获得网络选项卡上

network tab

和最后一部分我的代码

function foo(api_key, url, query, pdata, callback) { 
     var result = 'none'; 
     if (typeof pdata != "undefined"){ 
      var mydata = {"api_key": api_key, "query": query, "data": pdata }; 
     } 
     else { 
      var mydata = {"api_key": api_key, "query": query}; 
     } 
     $.ajax({ 
       method : "POST", 
       url : url, 
       data: JSON.stringify(mydata), 
       contentType: "application/json;charset=UTF-8", 
       cache: false, 
       dataType: "json", 
       success : function(data) { 
       console.log("API call is working successfully!") 
       callback(data); 
       result = data 
     }, 
     error: function(data, status, error) { 
       console.log("API call failed!") 
     } 
    }); 
    return result; 
    } 

这是我得到的错误。

XMLHttpRequest cannot load https://my_url. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. 
api.js:29 API call failed!` 

我应该怎么做,更改或添加它使其在Chrome和Firefox中工作?

+0

如果你的后端是不挑剔的要求'内容Type'头,你总是可以将其设置为'文/ plain'这使得它成为* *简单的要求,因此,避免了飞行前'OPTIONS'请求 – Phil

+0

尝试使用'crossDomain:true'更新您的选项。这应该是自动的,但也许会失败? –

+1

可能对未来的参考很有用,但请包括文本内容,而不是简单地发布代码的截图/图像。 – Terry

回答

0

问题解决了!在客户端一切正常

开始使用CORS LIB服务器

from flask_cors import CORS 

上,并作为@WitVault说,与这些设置来配置服务器解决我的问题!

cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) 
app.config['CORS_HEADERS'] = 'Content-Type' 
5

您的ajax请求似乎是正确的,但问题出现在服务器端。每cors请求浏览器发送预检请求。只有在预检请求通过服务器端得到验证后,才可以发送cors ajax请求。

因此,根据您使用的服务器的类型预检请求您需要向浏览器发送适当的响应。

正确响应意味着在预检请求的响应上设置合适的标头并将其发送回客户端,即浏览器。

对于curl请求,您不需要这样做,因为curl请求不会经过服务器端的预检请求验证。

它仅在浏览器出于安全原因的情况下才需要。

一个例子可以是这样的 -

HttpResponse response = new HttpResponse(request.getProtocolVersion(), NO_CONTENT); 
    HttpHeaders headers = response.headers(); 

    headers.set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); 
    headers.set(CONTENT_TYPE, "text/plain; charset=UTF-8"); 
    headers.set(CACHE_CONTROL, "max-age=31536000, public"); 
    headers.set(ACCESS_CONTROL_ALLOW_ORIGIN, request.headers().get("Origin")); 
    headers.set(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); 
    headers.set(ACCESS_CONTROL_MAX_AGE, "31536000"); 
    headers.set(ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, OPTIONS"); 
    headers.set(ACCESS_CONTROL_ALLOW_HEADERS, request.headers().get("Access-Control-Request-Headers")); 
    headers.set(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); 
    send(response); 

这只是一个例子,但你将如何做到这一点在你的身边,完全取决于你的服务器端和您正在使用的服务器架构。

+0

我意识到,当我比较safari和chrome中的响应头。内容类型在safari中是作为'application/json'来的(正如预期的那样),但是在chrome内容类型中是'text/html; charset = utf-8'所以你有任何想法如何防止铬这样做? – enterbutton

0

实际上,您的preflight请求失败,因为您正在设置content-type但在响应中没有Content-Type标头。

所以,要么不设置content-typejson改用text/plain, form-data绕过预检要求,并直接发送Ajax请求跨域服务器。

或在服务器上设置Access-Control-Allow-Headers:Content-Type标头。

要在Apache

Header set Access-Control-Allow-Headers "Content-Type"

将工作组头。

enter image description here

+0

当我通过curl进行API调用时,我在响应中看到了'Access-Control-Allow-Headers:Content-Type'。这意味着它已被设置为“访问控制 - 允许 - 标题:内容类型”的权利? – enterbutton

+0

是的,如果它的回应。这将只是他们的请求..如果没有设置在服务器..IN上传的图像..头只在请求..不存在作为回应。 –

+0

这是一个烧瓶项目,我检查了服务器端,选项已经设置为'response.headers.add(“Access-Control-Allow-Origin”,“*”) response.headers.add(“Access -Control-Allow-Headers“,”Content-Type“)',但我还是得到了'Request header字段Content-Type在预检响应中不被Access-Control-Allow-Headers所允许。' – enterbutton

相关问题