Где правильно включить CORS?

Я использую Spyne (пример код "hello world"), чтобы создать веб-сервис, который производит некоторые json данные, а затем я пытаюсь использовать эти данные в коде javascript в браузере клиента.

Когда я иду по адресу http://localhost:8000/say_hello?name=Dave&times=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&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. Если нет необходимости изменять какие-либо настройки на стороне сервера, каким должен быть правильный код на стороне клиента?

ИЗМЕНИТЬ

Вот последняя версия кода 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>

Питон:

#!/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()

person ceremcem    schedule 01.07.2014    source источник


Ответы (2)


Вам нужно добавить это как первую строку реализации вашей службы:

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 теперь вы можете использовать CorsService в качестве родительского класса для своих служб, чтобы автоматически получать заголовок CORS.

Также обратите внимание, что более безопасно установить значение заголовка только для домена, на котором размещена служба Spyne, вместо использования подстановочного знака.

person Burak Arslan    schedule 02.07.2014

Нет необходимости добавлять код на стороне клиента.

Вам просто нужно добавить следующее в заголовок ответа, отправленного сервером:

Доступ-Контроль-Разрешить-Происхождение: *

См. http://enable-cors.org/server.html для получения дополнительной информации о различных серверах. настройки. Не знаком со Spyne, но это может помочь

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

person drjimmie1976    schedule 01.07.2014
comment
Я не могу добавить этот заголовок в ответ сервера, но я работаю над этим. Но я должен сказать, что я не верю (да, верю), что это проблема на стороне сервера. Это похоже на проблему с клиентом. Если это связано с настройкой на стороне сервера, почему и как я могу получить доступ к этим данным через веб-браузер или консоль (curl localhost...)? Они говорят, что это связано с безопасностью, но как это вообще помогает безопасности? Я попробую настроить заголовок, но затем попробую вручную загрузить и проанализировать страницу. - person ceremcem; 02.07.2014
comment
@ceremcem Какие сообщения появляются в консоли браузера, когда появляется предупреждение о сбое? Если это действительно проблема CORS, это будет что-то вроде заголовка No Access-Control-Allow-Origin в запрошенном ресурсе. - person drjimmie1976; 02.07.2014
comment
Если я устанавливаю dataType='html', появляется предупреждение, связанное с cors: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/say_hello?name=Dave&times=3. This can be fixed by moving the resource to the same domain or enabling CORS. Если я устанавливаю dataType='jsonp', в firebug нет такого сообщения об ошибке, и вкладка JSON отображается под данными заголовка firebug-›Net-›, на этой вкладке я могу получить данные Hello, Dave (3 элемента). Но все равно выскакивает предупреждение о сбое. - person ceremcem; 02.07.2014
comment
Я не смог найти способ попробовать это, но, похоже, попробовать стоит. - person ceremcem; 02.07.2014