2012-03-08 24 views
5

我想设置简单的跨源资源共享使用jQuery(1.7.1)在客户端和apache服务的python(Django)服务器上启动ajax。根据所有的指示,我看了我的头设置正确,但我不断收到以下错误:CORS访问控制 - 允许来源尽管正确的标题

XMLHttpRequest cannot load http://myexternaldomain.com/get_data . Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin.

是我想(我不知道它甚至让过去的浏览器)的标头中发送是:

Request URL:http://myexternaldomain.com/get_data 
Accept:application/json, text/javascript, */*; q=0.01 
Origin:http://localhost:8080 
Referer:http://localhost:8080/static/js/test-zetta.html 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.66 Safari/535.11 

的JavaScript代码是

var request = $.ajax({ 
     url : "http://myexternaldomain.com/get_data", 
     type : "POST", 
     dataType : "json", 
     crossDomain : true 
    }); 

注意origin设置正确。服务器使用下面的Python代码

def process_response(self, response): 
    if response.has_header('Access-Control-Allow-Origin'): 
      return response 

    response['Access-Control-Allow-Origin'] = '*' 
    return response 

def get_orders(request): 
    """ Tell worker what to do """ 
    response_data = {} 
    response_data['action'] = 'probe' 
    response = process_response(HttpResponse(json.dumps(response_data), mimetype="application/json")) 
    return response 

如果我直接访问该地址,这似乎证实了头被设置正确

Access-Control-Allow-Origin:* 
Content-Type:application/json 
Date:Thu, 08 Mar 2012 05:06:25 GMT 
Server:Apache/2.2.20 (Ubuntu) 
Transfer-Encoding:chunked 

然而在跨域设置它添加页眉Access-Control-Allow-Origin = *总是失败(同时尝试Chrome和Firefox)。我试过正是因为每所选择的答案执行代码this的问题,但得到了同样的错误

更新

我敢肯定,问题是服务器端,因为我设法得到我的ajax调用与不同的公共CORS服务器一起工作。当我比较从这个公共服务器返回的头文件和从我的返回头文件(当我从同一个域中测试时)时,我看不到任何可能导致差异的主要差异(见下文)。

我排除的一个微妙之处,可能或可能很重要的是,实际域是多个子域的亚马逊域。 实际地址http://ec2-23-20-27-108.compute-1.amazonaws.com/get_orders,随时探讨它,看看我做错了什么。

从公共服务器

Access-Control-Allow-Origin:* 
Connection:Keep-Alive 
Content-Encoding:gzip 
Content-Length:622 
Content-Type:text/html 
Date:Thu, 08 Mar 2012 15:33:20 GMT 
Keep-Alive:timeout=15, max=99 
Server:Apache/2.2.14 (Ubuntu) 
Vary:Accept-Encoding 
X-Powered-By:Perl/5.8.7, PHP/4.4.0 

从我的服务器 - (不工作跨域)

Access-Control-Allow-Origin:* 
Content-Encoding:gzip 
Content-Type:text/plain 
Date:Thu, 08 Mar 2012 15:32:24 GMT 
Server:Apache/2.2.20 (Ubuntu) 
Transfer-Encoding:chunked 
Vary:Accept-Encoding 
+1

我已经尝试过,为Json数据启用CORS并从未成功过。 CORS可以像这样片状。只要返回JSON-P就会好得多。 – xbonez 2012-03-08 06:36:29

+0

您只在远程服务器和本地客户端之间发布_final_交换头。如果您查看完整的交换,我相信您会看到一个OPTIONS请求以及一个包含Access-Control-Allow-Methods和Access-Control-Allow-Headers标题的响应。 – 2012-03-10 16:40:31

回答

5

所以我被误导了去URL的响应,其实问题是,当做ajax请求时,我得到一个403(只显示在Firefox中不铬)错误由于csrf保护。

+1

哦,男人,非常感谢。我在我的'csrf_exempt'包装器上有我的'enable_cors'包装器,需要将它们反转。我很喜欢,WTF ... – orokusaki 2013-04-12 01:56:55

5

你必须实行 “预排期的” 请求和响应,因为您的情况算作“not so simple”请求。基本的CORS,只需要Origin头文件,只能具有“application/x-www-form-urlencoded”,“multipart/form-data”和“text/plain”的内容类型。既然你返回“application/json”,你就不符合这个要求。

我对Django一无所知,但我发现通过使用Tomcat filter可以更容易地在我的应用程序之外实现CORS支持。它看起来像你可以用Django do the same thing

2013-08-11:它看起来像GitHub回购已不再与我们同在。但Django包仍然可以在https://pypi.python.org/pypi/django-cors/0.1

+0

很确定浏览器应该照顾预检请求......至少Chrome会这样做。 – 2012-03-08 06:26:01

+0

但服务器必须识别它。他的脚本仅通过将Origin头添加到每个请求来响应基本请求。 – 2012-03-08 06:30:06

+0

我试图使请求变得简单,通过使我的数据成为一个简单的字符串,期望$ .ajax调用中的纯文本并在python中返回mimetype ='text/plain',但仍然会得到相同的错误。 – zenna 2012-03-08 14:43:27

2

我在使用优秀的django-cors-headers库,也遇到了这个问题。对我来说,解决方案是将'accept-encoding'添加到默认的CORS_ALLOW_HEADERS元组中。

相关问题