启用CORS的正确位置在哪里?

时间:2014-07-01 17:40:35

标签: javascript python web-services jsonp spyne

我正在使用Spyne(示例"hello world" code)制作一个产生一些json数据的网络服务,然后我试图在客户端浏览器的javascript代码中使用这些数据。

当我转到地址http://localhost:8000/say_hello?name=Dave&times=3时,我得到以下输出:

["Hello, Dave", "Hello, Dave", "Hello, Dave"]

这就是为什么我认为与服务器无关(它按预期工作)。

我使用以下代码从此Web服务获取数据:

<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&times=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 *
  1. 如果必须在服务器端更改任何标头设置,我该怎么办?
  2. 如果不需要更改任何服务器端设置,那么正确的客户端代码应该是什么?
  3. 修改

    这是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&times=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\&times=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 个答案:

答案 0 :(得分: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)

因此,您现在可以使用ServiceBase作为服务的父类来自动获取CORS标头,而不是使用CorsService

另请注意,将标头值仅设置为承载Spyne服务的域而不是使用通配符更安全。

答案 1 :(得分:1)

无需添加任何客户端代码。

您只需将以下内容添加到服务器发送的响应的标头中:

Access-Control-Allow-Origin:*

有关各种服务器设置的详细信息,请参阅http://enable-cors.org/server.html。不熟悉Spyne,但这可能会有所帮助

http://spyne.io/docs/2.10/manual/06_metadata.html#protocol-headers