Start working on the soap protocol
This commit is contained in:
parent
732626c176
commit
5ca78e896f
@ -14,3 +14,8 @@ syntax: regexp
|
|||||||
^include
|
^include
|
||||||
^dist
|
^dist
|
||||||
|
|
||||||
|
^examples/.*/bin
|
||||||
|
^examples/.*/dist
|
||||||
|
^examples/.*/lib
|
||||||
|
^examples/.*/include
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from wsme import *
|
|||||||
|
|
||||||
import wsme.restjson
|
import wsme.restjson
|
||||||
import wsme.restxml
|
import wsme.restxml
|
||||||
|
import wsme.soap
|
||||||
|
|
||||||
|
|
||||||
class DemoRoot(WSRoot):
|
class DemoRoot(WSRoot):
|
||||||
|
2
examples/demo/setup.cfg
Normal file
2
examples/demo/setup.cfg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[easy_install]
|
||||||
|
find_links = http://www.owlfish.com/software/wsgiutils/download.html
|
@ -6,5 +6,6 @@ setup(name='demo',
|
|||||||
'PasteScript',
|
'PasteScript',
|
||||||
'PasteDeploy',
|
'PasteDeploy',
|
||||||
'WSGIUtils',
|
'WSGIUtils',
|
||||||
|
'Pygments',
|
||||||
],
|
],
|
||||||
package=['demo'])
|
package=['demo'])
|
||||||
|
@ -54,6 +54,8 @@ class FunctionDefinition(object):
|
|||||||
self.name = func.__name__
|
self.name = func.__name__
|
||||||
self.return_type = None
|
self.return_type = None
|
||||||
self.arguments = []
|
self.arguments = []
|
||||||
|
self.protocol_specific = False
|
||||||
|
self.contenttype = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, func):
|
def get(cls, func):
|
||||||
@ -80,6 +82,19 @@ class expose(object):
|
|||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
class pexpose(object):
|
||||||
|
def __init__(self, return_type=None, contenttype=None):
|
||||||
|
self.return_type = return_type
|
||||||
|
self.contenttype = contenttype
|
||||||
|
register_type(return_type)
|
||||||
|
|
||||||
|
def __call__(self, func):
|
||||||
|
fd = FunctionDefinition.get(func)
|
||||||
|
fd.return_type = self.return_type
|
||||||
|
fd.protocol_specific = True
|
||||||
|
fd.contenttype = self.contenttype
|
||||||
|
return func
|
||||||
|
|
||||||
class validate(object):
|
class validate(object):
|
||||||
def __init__(self, *args, **kw):
|
def __init__(self, *args, **kw):
|
||||||
self.param_types = args
|
self.param_types = args
|
||||||
@ -124,40 +139,47 @@ class WSRoot(object):
|
|||||||
|
|
||||||
def _handle_request(self, request):
|
def _handle_request(self, request):
|
||||||
res = webob.Response()
|
res = webob.Response()
|
||||||
|
res_content_type = None
|
||||||
try:
|
try:
|
||||||
protocol = self._select_protocol(request)
|
protocol = self._select_protocol(request)
|
||||||
if protocol is None:
|
if protocol is None:
|
||||||
msg = ("None of the following protocols can handle this "
|
msg = ("None of the following protocols can handle this "
|
||||||
"request : %s" % ','.join(self.protocols.keys()))
|
"request : %s" % ','.join(self.protocols.keys()))
|
||||||
res.status = 500
|
res.status = 500
|
||||||
res.text = msg
|
res.text = msg
|
||||||
log.error(msg)
|
log.error(msg)
|
||||||
return res
|
return res
|
||||||
path = protocol.extract_path(request)
|
path = protocol.extract_path(request)
|
||||||
func, funcdef = self._lookup_function(path)
|
func, funcdef = self._lookup_function(path)
|
||||||
kw = protocol.read_arguments(request, funcdef.arguments)
|
kw = protocol.read_arguments(request,
|
||||||
|
funcdef and funcdef.arguments or None)
|
||||||
|
|
||||||
result = func(**kw)
|
result = func(**kw)
|
||||||
|
|
||||||
# TODO make sure result type == a._wsme_definition.return_type
|
|
||||||
res.status = 200
|
res.status = 200
|
||||||
res.body = protocol.encode_result(result, funcdef.return_type)
|
|
||||||
|
if funcdef.protocol_specific and funcdef.return_type is None:
|
||||||
|
res.body = result
|
||||||
|
else:
|
||||||
|
# TODO make sure result type == a._wsme_definition.return_type
|
||||||
|
res.body = protocol.encode_result(result, funcdef.return_type)
|
||||||
|
res_content_type = funcdef.contenttype
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
infos = self._format_exception(sys.exc_info())
|
||||||
|
log.error(str(infos))
|
||||||
res.status = 500
|
res.status = 500
|
||||||
res.body = protocol.encode_error(
|
res.body = protocol.encode_error(infos)
|
||||||
self._format_exception(sys.exc_info()))
|
|
||||||
|
|
||||||
# Attempt to correctly guess what content-type we should return.
|
if res_content_type is None:
|
||||||
res_content_type = None
|
# Attempt to correctly guess what content-type we should return.
|
||||||
|
last_q = 0
|
||||||
last_q = 0
|
if hasattr(request.accept, '_parsed'):
|
||||||
if hasattr(request.accept, '_parsed'):
|
for mimetype, q in request.accept._parsed:
|
||||||
for mimetype, q in request.accept._parsed:
|
if mimetype in protocol.content_types and last_q < q:
|
||||||
if mimetype in protocol.content_types and last_q < q:
|
res_content_type = mimetype
|
||||||
res_content_type = mimetype
|
else:
|
||||||
else:
|
res_content_type = request.accept.best_match([
|
||||||
res_content_type = request.accept.best_match([
|
ct for ct in protocol.content_types if ct])
|
||||||
ct for ct in protocol.content_types if ct])
|
|
||||||
|
|
||||||
# If not we will attempt to convert the body to an accepted
|
# If not we will attempt to convert the body to an accepted
|
||||||
# output format.
|
# output format.
|
||||||
@ -175,15 +197,27 @@ class WSRoot(object):
|
|||||||
def _lookup_function(self, path):
|
def _lookup_function(self, path):
|
||||||
a = self
|
a = self
|
||||||
|
|
||||||
|
isprotocol_specific = path[0] == '_protocol'
|
||||||
|
|
||||||
|
if isprotocol_specific:
|
||||||
|
a = self.protocols[path[1]]
|
||||||
|
path = path[2:]
|
||||||
|
|
||||||
|
print path, a, a.api_wsdl
|
||||||
|
|
||||||
for name in path:
|
for name in path:
|
||||||
a = getattr(a, name, None)
|
a = getattr(a, name, None)
|
||||||
if a is None:
|
if a is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
print a
|
||||||
|
|
||||||
if not hasattr(a, '_wsme_definition'):
|
if not hasattr(a, '_wsme_definition'):
|
||||||
raise exc.UnknownFunction('/'.join(path))
|
raise exc.UnknownFunction('/'.join(path))
|
||||||
|
|
||||||
return a, a._wsme_definition
|
definition = a._wsme_definition
|
||||||
|
|
||||||
|
return a, definition
|
||||||
|
|
||||||
def _format_exception(self, excinfo):
|
def _format_exception(self, excinfo):
|
||||||
"""Extract informations that can be sent to the client."""
|
"""Extract informations that can be sent to the client."""
|
||||||
|
58
wsme/soap.py
58
wsme/soap.py
@ -1,9 +1,63 @@
|
|||||||
|
from wsme.controller import register_protocol, pexpose
|
||||||
|
|
||||||
|
from xml.etree import ElementTree as et
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SoapProtocol(object):
|
class SoapProtocol(object):
|
||||||
name = 'soap'
|
name = 'soap'
|
||||||
accept = ''
|
content_types = ['application/soap+xml']
|
||||||
|
|
||||||
|
ns = {
|
||||||
|
"soap": "http://www.w3.org/2001/12/soap-envelope"
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def accept(self, root, req):
|
||||||
|
if req.headers['Content-Type'] in self.content_types:
|
||||||
|
return True
|
||||||
|
if req.path.endswith('.wsdl'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
controller.register_protocol(SoapProtocol)
|
def extract_path(self, request):
|
||||||
|
if request.path.endswith('.wsdl'):
|
||||||
|
print "Here !!"
|
||||||
|
return ['_protocol', 'soap', 'api_wsdl']
|
||||||
|
|
||||||
|
def read_arguments(self, request, arguments):
|
||||||
|
if arguments is None:
|
||||||
|
return {}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def encode_result(self, result, return_type):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def make_header(self):
|
||||||
|
header = et.Element('{%(soap)s}Header' % self.ns)
|
||||||
|
return header
|
||||||
|
|
||||||
|
def make_body(self):
|
||||||
|
body = et.Element('{%(soap)s}Body' % self.ns)
|
||||||
|
return body
|
||||||
|
|
||||||
|
def make_envelope(self):
|
||||||
|
env = et.Element('{%(soap)s}Envelope' % self.ns)
|
||||||
|
env.append(self.make_header())
|
||||||
|
env.append(self.make_body())
|
||||||
|
return env
|
||||||
|
|
||||||
|
def encode_error(self, infos):
|
||||||
|
env = self.make_envelope()
|
||||||
|
fault = et.Element('{%(soap)s}Fault' % self.ns)
|
||||||
|
env.find('{%(soap)s}Body' % self.ns).append(fault)
|
||||||
|
return et.tostring(env)
|
||||||
|
|
||||||
|
@pexpose(contenttype="text/xml")
|
||||||
|
def api_wsdl(self):
|
||||||
|
return """<wsdl/>"""
|
||||||
|
|
||||||
|
|
||||||
|
register_protocol(SoapProtocol)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user