JsonDocument作为输入协议,但方法名称取自URL

时间:2013-09-20 12:53:02

标签: python spyne

来自spyne.io的示例:

class HelloWorldService(ServiceBase):
    @srpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(name, times):
        for i in range(times):
            yield 'Hello, %s' % name

application = Application([HelloWorldService],
    tns='spyne.examples.hello',
    in_protocol=JsonDocument(validator='soft'),
    out_protocol=JsonDocument()
)

这意味着被调用的方法名称必须是JSON正文的唯一键:

$ curl -s http://localhost:8000/ -d '{"say_hello": {"name": "World", "times": 5}}'

我希望正文不包含方法名称,但是要从URL中获取方法名称,就像使用HttpRpc一样:

$ curl -s http://localhost:8000/say_hello -d '{"name": "World", "times": 5}'

如何定义服务以处理此类请求?

1 个答案:

答案 0 :(得分:1)

您可以从JsonDocument派生新的协议类型。您只需要重写一个方法:

# Tested with spyne.__version__=='2.10.9'
class warwarukDocument(JsonDocument):
    """An implementation of the json protocol
       with the method name stored in the URL,
       not the document."""

    def create_in_document(self, ctx, in_string_encoding=None):
        """ Sets ``ctx.in_document`` using ``ctx.in_string``."""
        assert ctx.transport.type.endswith('http'), \
               "This protocol requires an http transport, not %r (in %r)" \
                   % (ctx.transport.type, ctx.transport)

        super(warwarukDocument, self).create_in_document(ctx, in_string_encoding)
        # Not 100% sure where to find the URL path
        try:
            # Works for twisted
            uri = ctx.transport.req.uri
        except AttributeError:
            # Works for WSGI
            uri = ctx.transport.req['PATH_INFO']
        uri = re.sub(r'.*/', '', uri)
        ctx.in_document = { uri : ctx.in_document }


application = Application([HelloWorldService],
    tns='spyne.examples.hello',
    in_protocol=warwarukDocument(validator='soft'),
    out_protocol=JsonDocument()
)

用法:

$ curl -s http://localhost:8000/say_hello \
      -d '{"name": "World", "times": 1}' | python -m json.tool
[
    "Hello, World"
]
$ curl -s http://localhost:8000/say_goodbye \
      -d '{"name": "World", "times": 1}' | python -m json.tool
{
    "detail": null, 
    "faultcode": "Client.ResourceNotFound", 
    "faultstring": "Requested resource \"Method u'{spyne.examples.hello}say_goodbye' not found.\" not found"
}