Where is the correct place to enable CORS?

僤鯓⒐⒋嵵緔 提交于 2019-12-31 04:20:08

问题


I'm using Spyne (the example "hello world" code) to make a webservice that produces some json data and then I'm trying to consume this data in javascript code in client's browser.

When I go to the address http://localhost:8000/say_hello?name=Dave&times=3 I get the following output:

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

That's why I think there is nothing to do with the server (it works as expected).

I use the following code to get the data from this webservice:

<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>

Then I get the "fail" popup.

As I searched the net, all I could find was a setting to be made on the server side as follows:

Add following header in the server: 

  Header set Access-Control-Allow-Origin *
  1. If any header setting must be changed on server side, how can I do that?
  2. If there is no need to change any server side settings, what should be the correct client side code?

EDIT

Here is the last version of both python and javascript code:

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()

回答1:


You need add this as the first line of your service implementation:

ctx.transport.resp_headers['Access-Control-Allow-Origin'] = '*'

However, that can get very annoying very fast, so here's a way to properly implement it:

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)

So instead of using ServiceBase, you can now use CorsService as parent class to your services to get the CORS header automatically.

Also note that it's more secure to set the header value only to the domain that hosts the Spyne service instead of using a wildcard.




回答2:


No need to add any client side code.

You simply need to add the following to the header of the response sent by the server:

Access-Control-Allow-Origin: *

See http://enable-cors.org/server.html for more info for the various server setups. Not familiar with Spyne but this may help

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



来源:https://stackoverflow.com/questions/24516280/where-is-the-correct-place-to-enable-cors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!