Where is the correct place to enable CORS?
Question: I'm using [Spyne](http://spyne.io) (the example ["hello world"
code](https://github.com/arskom/spyne/blob/master/examples/helloworld_http.py))
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()
    


Answer: 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.

