def _from_soap(in_envelope_xml, xmlids=None): ''' Parses the xml string into the header and payload ''' if xmlids: resolve_hrefs(in_envelope_xml, xmlids) if in_envelope_xml.tag != '{%s}Envelope' % rpclib.ns_soap_env: raise Fault('Client.SoapError', 'No {%s}Envelope element was found!' % rpclib.ns_soap_env) header_envelope = in_envelope_xml.xpath( 'e:Header', namespaces={'e': rpclib.ns_soap_env}) body_envelope = in_envelope_xml.xpath('e:Body', namespaces={'e': rpclib.ns_soap_env}) if len(header_envelope) == 0 and len(body_envelope) == 0: raise Fault('Client.SoapError', 'Soap envelope is empty!' % rpclib.ns_soap_env) header = None if len(header_envelope) > 0 and len(header_envelope[0]) > 0: header = header_envelope[0].getchildren()[0] body = None if len(body_envelope) > 0 and len(body_envelope[0]) > 0: body = body_envelope[0].getchildren()[0] return header, body
def deserialize(self, ctx): """Takes a MethodContext instance and a string containing ONE soap message. Returns the corresponding native python object Not meant to be overridden. """ if ctx.in_body_doc.tag == "{%s}Fault" % ns.soap_env: ctx.in_object = None ctx.in_error = Fault.from_xml(ctx.in_body_doc) else: # retrieve the method descriptor if ctx.method_name is None: raise Exception("Could not extract method name from the request!") if ctx.descriptor is None: ctx.descriptor = ctx.service_class.get_method(ctx.method_name) if self.in_wrapper is self.IN_WRAPPER: header_class = ctx.descriptor.in_header body_class = ctx.descriptor.in_message elif self.in_wrapper is self.OUT_WRAPPER: header_class = ctx.descriptor.out_header body_class = ctx.descriptor.out_message # decode header objects if (ctx.in_header_doc is not None and header_class is not None): if isinstance(header_class, (list, tuple)): headers = [None] * len(header_class) for i, (header_doc, head_class) in enumerate(zip(ctx.in_header_doc, header_class)): if len(header_doc) > 0: headers[i] = head_class.from_xml(header_doc) ctx.in_header = tuple(headers) else: header_doc = ctx.in_header_doc[0] if len(header_doc) > 0: ctx.in_header = header_class.from_xml(header_doc) # decode method arguments if ctx.in_body_doc is not None and len(ctx.in_body_doc) > 0: ctx.in_object = body_class.from_xml(ctx.in_body_doc) else: ctx.in_object = [None] * len(body_class._type_info) self.event_manager.fire_event('deserialize', ctx)
def deserialize(self, ctx, doc_struct): """Takes a MethodContext instance and a string containing ONE soap message. Returns the corresponding native python object Not meant to be overridden. """ # this sets the ctx.in_body_doc and ctx.in_header_doc properties self.decompose_incoming_envelope(ctx, doc_struct) if ctx.in_body_doc.tag == "{%s}Fault" % rpclib.ns_soap_env: in_body = Fault.from_xml(ctx.in_body_doc) else: # retrieve the method descriptor if ctx.method_name is None: raise Exception( "Could not extract method name from the request!") else: if ctx.descriptor is None: descriptor = ctx.descriptor = ctx.service.get_method( ctx.method_name) else: descriptor = ctx.descriptor if self.in_wrapper is self.IN_WRAPPER: header_class = descriptor.in_header body_class = descriptor.in_message elif self.in_wrapper is self.OUT_WRAPPER: header_class = descriptor.out_header body_class = descriptor.out_message # decode header object if ctx.in_header_doc is not None and len(ctx.in_header_doc) > 0: ctx.service.in_header = header_class.from_xml( ctx.in_header_doc) # decode method arguments if ctx.in_body_doc is not None and len(ctx.in_body_doc) > 0: in_body = body_class.from_xml(ctx.in_body_doc) else: in_body = [None] * len(body_class._type_info) return in_body
def deserialize(self, ctx, doc_struct): """Takes a MethodContext instance and a string containing ONE soap message. Returns the corresponding native python object Not meant to be overridden. """ # this sets the ctx.in_body_doc and ctx.in_header_doc properties self.decompose_incoming_envelope(ctx, doc_struct) if ctx.in_body_doc.tag == "{%s}Fault" % rpclib.ns_soap_env: in_body = Fault.from_xml(ctx.in_body_doc) else: # retrieve the method descriptor if ctx.method_name is None: raise Exception("Could not extract method name from the request!") else: if ctx.descriptor is None: descriptor = ctx.descriptor = ctx.service.get_method( ctx.method_name) else: descriptor = ctx.descriptor if self.in_wrapper is self.IN_WRAPPER: header_class = descriptor.in_header body_class = descriptor.in_message elif self.in_wrapper is self.OUT_WRAPPER: header_class = descriptor.out_header body_class = descriptor.out_message # decode header object if ctx.in_header_doc is not None and len(ctx.in_header_doc) > 0: ctx.service.in_header = header_class.from_xml(ctx.in_header_doc) # decode method arguments if ctx.in_body_doc is not None and len(ctx.in_body_doc) > 0: in_body = body_class.from_xml(ctx.in_body_doc) else: in_body = [None] * len(body_class._type_info) return in_body
def decompose_incoming_envelope(self, ctx, envelope_doc): envelope_xml, xmlids = envelope_doc header, body = _from_soap(envelope_xml, xmlids) # FIXME: find a way to include soap env schema with rpclib package and # properly validate the whole request. if len(body) > 0 and body.tag == '{%s}Fault' % rpclib.ns_soap_env: ctx.in_body_doc = body elif not (body is None): try: self.parent.interface.validate(body) if (not (body is None)) and (ctx.method_name is None): ctx.method_name = body.tag logger.debug("\033[92mMethod name: %r\033[0m" % ctx.method_name) finally: # for performance reasons, we don't want the following to run # in production even though we won't see the results. if logger.level == logging.DEBUG: try: logger.debug( etree.tostring(envelope_xml, pretty_print=True)) except etree.XMLSyntaxError, e: logger.debug(body) raise Fault( 'Client.Xml', 'Error at line: %d, ' 'col: %d' % e.position) try: if ctx.service_class is None: # i.e. if it's a server ctx.service_class = self.parent.get_service_class( ctx.method_name) except Exception, e: logger.debug(traceback.format_exc()) raise ValidationError('Client', 'Method not found: %r' % ctx.method_name)
def soap_exception(self): raise Fault("Plausible", "A plausible fault", 'Fault actor', detail=etree.Element('something'))
class Application(object): transport = None def __init__(self, services, interface_class, in_protocol_class, out_protocol_class=None, *args, **kwargs): '''Constructor. @param An iterable of ServiceBase subclasses that define the exposed services. @param The targetNamespace attribute of the exposed service. @param The name attribute of the exposed service. ''' if out_protocol_class is None: out_protocol_class = in_protocol_class self.interface = interface_class(self, services, *args, **kwargs) self.in_protocol = in_protocol_class(self) self.out_protocol = out_protocol_class(self) self.services = services self.__public_methods = {} self.__classes = {} def get_class(self, key): return self.interface.get_class(key) def get_class_instance(self, key): return self.interface.get_class_instance(key) def process_request(self, ctx, req_obj): """Takes a MethodContext instance and the native request object. Returns the response to the request as a native python object. Not meant to be overridden. """ try: # implementation hook ctx.service.on_method_call(ctx.method_name, req_obj, ctx.in_body_doc) # retrieve the method func = getattr(ctx.service, ctx.descriptor.name) # call the method retval = ctx.service.call_wrapper(func, req_obj) except Fault, e: stacktrace = traceback.format_exc() logger.error(stacktrace) retval = e except Exception, e: stacktrace = traceback.format_exc() logger.error(stacktrace) retval = Fault('Server', str(e))