正确的CORS启用位置在哪里?
我正在使用Spyne(这个“你好,世界”示例代码)来创建一个网络服务,这个服务会生成一些json
数据,然后我想在客户端的浏览器中用JavaScript来获取这些数据。
当我访问这个地址http://localhost:8000/say_hello?name=Dave×=3
时,我得到了以下输出:
["Hello, Dave", "Hello, Dave", "Hello, Dave"]
所以我认为服务器没有问题(它按预期工作)。
我使用以下代码来从这个网络服务获取数据:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="jquery-1.11.1.min.js" ></script>
<script>
var request_url = 'http://localhost:8000/say_hello?name=Dave×=3';
$.ajax( {
type:'Get',
url:request_url,
dataType: "jsonp",
crossDomain : true,
success:function(data) {
alert(data);
},
error: function()
{
alert("fail");
},
});
</script>
</body>
</html>
然后我收到了“失败”的弹窗。
我在网上搜索时,找到的都是关于在服务器端需要进行的设置:
Add following header in the server:
Header set Access-Control-Allow-Origin *
- 如果需要更改服务器端的任何头部设置,我该怎么做?
- 如果不需要更改任何服务器端设置,客户端的正确代码应该是什么?
编辑
这是Python和JavaScript代码的最新版本:
HTML:
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="jquery-1.11.1.min.js" ></script>
<script>
var request_url = 'http://localhost:8000/say_hello?name=Dave×=3';
var jdata = 'none'
$.ajax( {
type:'Get',
url:request_url,
dataType: "html",
crossDomain : true,
success:function(data) {
alert(data);
},
error: function()
{
alert("fail");
},
});
</script>
</body>
</html>
Python:
#!/usr/bin/env python
# encoding: utf8
'''
This is a simple HelloWorld example to show the basics of writing a Http api
using Spyne. Here's a sample:
$ curl http://localhost:8000/say_hello?name=Dave\×=3
["Hello, Dave", "Hello, Dave", "Hello, Dave"]
'''
import logging
from spyne.application import Application
from spyne.decorator import srpc
from spyne.protocol.json import JsonDocument
from spyne.protocol.http import HttpRpc
from spyne.service import ServiceBase
from spyne.model.complex import Iterable
from spyne.model.primitive import UnsignedInteger
from spyne.model.primitive import String
from spyne.server.wsgi import WsgiApplication
class CorsService(ServiceBase):
origin = '*'
def _on_method_return_object(ctx):
ctx.transport.resp_headers['Access-Control-Allow-Origin'] = \
ctx.descriptor.service_class.origin
CorsService.event_manager.add_listener('method_return_object',
_on_method_return_object)
class HelloWorldService(CorsService):
@srpc(String, UnsignedInteger, _returns=Iterable(String))
def say_hello(name, times):
for i in range(times):
#yield '%s("Hello, %s")' % (callback, name)
yield {"name": 'Hello (%d): %s' % (i, name), "address": "%d + %d" % (i, i)}
if __name__=='__main__':
from wsgiref.simple_server import make_server
logging.basicConfig(level=logging.DEBUG)
application = Application([HelloWorldService], 'spyne.examples.hello.http',
in_protocol=HttpRpc(validator='soft'),
out_protocol=JsonDocument(ignore_wrappers=True),
)
wsgi_application = WsgiApplication(application)
server = make_server('0.0.0.0', 8000, wsgi_application)
logging.info("listening to http://127.0.0.1:8000")
logging.info("wsdl is at: http://localhost:8000/?wsdl")
server.serve_forever()
2 个回答
1
不需要添加任何客户端的代码。
你只需要在服务器发送的响应头中添加以下内容:
Access-Control-Allow-Origin: *
想了解更多不同服务器设置的信息,可以查看 http://enable-cors.org/server.html。虽然我对Spyne不太熟悉,但这可能会对你有帮助。
你可以访问 http://spyne.io/docs/2.10/manual/06_metadata.html#protocol-headers 来获取更多信息。
4
你需要在你的服务实现的第一行加上这个:
ctx.transport.resp_headers['Access-Control-Allow-Origin'] = '*'
不过,这样做很快就会让人觉得烦,所以这里有个更好的实现方法:
class CorsService(ServiceBase):
origin = '*'
def _on_method_return_object(ctx):
ctx.transport.resp_headers['Access-Control-Allow-Origin'] = \
ctx.descriptor.service_class.origin
CorsService.event_manager.add_listener('method_return_object',
_on_method_return_object)
所以,现在你可以用 CorsService
作为你服务的父类,这样就能自动获取 CORS 头了,而不是使用 ServiceBase
。
另外,注意把头的值设置为只允许托管 Spyne 服务的域名,这样会更安全,而不是使用通配符。