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×=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×=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 *
- If any header setting must be changed on server side, how can I do that?
- 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×=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()
You need add this as the first line of your service implementation:
However, that can get very annoying very fast, so here's a way to properly implement it:
So instead of using
ServiceBase
, you can now useCorsService
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.
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