Пример #1
0
    def __handle_wsdl_request(self, req_env, start_response, url):
        http_resp_headers = {'Content-Type': 'text/xml'}

        try:
            self.get_wsdl(url)
            self.on_wsdl(req_env, self.__wsdl) # implementation hook

            http_resp_headers['Content-Length'] = str(len(self.__wsdl))
            start_response(HTTP_200, http_resp_headers.items())

            return [self.__wsdl]

        except Exception, e:
            # implementation hook
            logger.error(traceback.format_exc())

            tns = self.get_tns()
            fault_xml = Fault.to_xml(Fault(str(e)), tns)
            fault_str = etree.tostring(fault_xml,
                   xml_declaration=True, encoding=string_encoding)
            if logger.level == logging.DEBUG:
                logger.debug(etree.tostring(etree.fromstring(fault_str),pretty_print=True))

            self.on_wsdl_exception(req_env, e, fault_xml)

            http_resp_headers['Content-length'] = str(len(fault_str))
            start_response(HTTP_500, http_resp_headers.items())

            return [fault_str]
Пример #2
0
    def test_soap_fault(self):
        ns_test = "test_namespace"

        fault = Fault("code", 'something happened', 'detail')
        fault_str = etree.tostring(make_soap_envelope(Fault.to_xml(fault,ns_test)), pretty_print=True)
        print fault_str
        fault = etree.fromstring(fault_str)

        self.assertTrue(fault.getchildren()[0].tag.endswith, 'Body')
        self.assertTrue(
            fault.getchildren()[0].getchildren()[0].tag.endswith('Fault'))
        f = fault.getchildren()[0].getchildren()[0]

        print etree.tostring(f,pretty_print=True)

        self.assertEquals(f.find('{%s}faultstring' % ns_test).text, 'something happened')
        self.assertEquals(f.find('{%s}faultcode' % ns_test).text, 'code')
        self.assertEquals(f.find('{%s}detail' % ns_test).text, 'detail')
Пример #3
0
    def __handle_soap_request(self, req_env, start_response, url):
        """
        This function is too big.
        """

        http_resp_headers = {
            'Content-Type': 'text/xml',
            'Content-Length': '0',
        }
        method_name = None

        try:
            # implementation hook
            self.on_call(req_env)

            if req_env['REQUEST_METHOD'].lower() != 'post':
                http_resp_headers['Allow'] = 'POST'
                start_response(HTTP_405, http_resp_headers.items())
                return ['']

            input = req_env.get('wsgi.input')
            length = req_env.get("CONTENT_LENGTH")
            body = input.read(int(length))

            try:
                service = None
                soap_req_header, soap_req_payload = self.__decode_soap_request(
                                                                req_env, body)
                if not (soap_req_payload is None):
                    self.validate_request(soap_req_payload)

                method_name = self.__get_method_name(req_env, soap_req_payload)
                if method_name is None:
                    resp = "Could not extract method name from the request!"
                    http_resp_headers['Content-Length'] = str(len(resp))
                    start_response(HTTP_500, http_resp_headers.items())
                    return [resp]

                service_class = self.get_service_class(method_name)
                service = self.get_service(service_class, req_env)

            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(etree.fromstring(body),
                                                             pretty_print=True))
                    except etree.XMLSyntaxError,e:
                        logger.debug(body)
                        raise Fault('Client.XMLSyntax', 'Error at line: %d, col: %d'
                                                                    % e.position)

            # retrieve the method descriptor
            descriptor = service.get_method(method_name)
            func = getattr(service, descriptor.name)

            # decode header object
            if soap_req_header is not None and len(soap_req_header) > 0:
                in_header = descriptor.in_header
                service.soap_in_header = in_header.from_xml(soap_req_header)

            # decode method arguments
            if soap_req_payload is not None and len(soap_req_payload) > 0:
                params = descriptor.in_message.from_xml(soap_req_payload)
            else:
                params = [None] * len(descriptor.in_message._type_info)

            # implementation hook
            service.on_method_call(req_env, method_name, params,
                                                               soap_req_payload)

            # call the method
            result_raw = service.call_wrapper(func, params)

            # construct the soap response, and serialize it
            envelope = etree.Element('{%s}Envelope' % soaplib.ns_soap_env,
                                                            nsmap=soaplib.nsmap)

            #
            # header
            #
            soap_header_elt = etree.SubElement(envelope,
                                             '{%s}Header' % soaplib.ns_soap_env)

            if service.soap_out_header != None:
                if descriptor.out_header is None:
                    logger.warning("Skipping soap response header as %r method "
                                   "is not published to have a soap response "
                                   "header" % method_name)
                else:
                    descriptor.out_header.to_xml(
                        service.soap_out_header,
                        self.get_tns(),
                        soap_header_elt,
                        descriptor.out_header.get_type_name()
                    )

            if len(soap_header_elt) > 0:
                envelope.append(soap_header_elt)

            #
            # body
            #
            soap_body = etree.SubElement(envelope,
                                               '{%s}Body' % soaplib.ns_soap_env)

            # instantiate the result message
            result_message = descriptor.out_message()

            # assign raw result to its wrapper, result_message
            out_type = descriptor.out_message._type_info

            if len(out_type) > 0:
                if len(out_type) == 1:
                    attr_name = descriptor.out_message._type_info.keys()[0]
                    setattr(result_message, attr_name, result_raw)
                else:
                    for i in range(len(out_type)):
                        attr_name = descriptor.out_message._type_info.keys()[i]
                        setattr(result_message, attr_name, result_raw[i])

            # transform the results into an element
            descriptor.out_message.to_xml(result_message, self.get_tns(),
                                                                      soap_body)

            # implementation hook
            service.on_method_return(req_env, result_raw, soap_body,
                                                              http_resp_headers)

            #
            # misc
            #
            results_str = etree.tostring(envelope, xml_declaration=True,
                                                       encoding=string_encoding)

            if descriptor.mtom:
                http_resp_headers, results_str = apply_mtom(http_resp_headers,
                    results_str, descriptor.out_message._type_info,[result_raw])

            # implementation hook
            self.on_return(req_env, http_resp_headers, results_str)

            # initiate the response
            http_resp_headers['Content-Length'] = str(len(results_str))
            start_response(HTTP_200, http_resp_headers.items())

            if logger.level == logging.DEBUG:
                logger.debug('\033[91m'+ "Response" + '\033[0m')
                logger.debug(etree.tostring(envelope, xml_declaration=True,
                                                             pretty_print=True))

            # return the serialized results
            return [results_str]
Пример #4
0
            if logger.level == logging.DEBUG:
                logger.debug('\033[91m'+ "Response" + '\033[0m')
                logger.debug(etree.tostring(envelope, xml_declaration=True,
                                                             pretty_print=True))

            # return the serialized results
            return [results_str]

        # The user issued a Fault, so handle it just like an exception!
        except Fault, e:
            return self.__handle_fault(req_env, start_response,
                                                http_resp_headers, service, e)

        except Exception, e:
            fault = Fault('Server', str(e))

            return self.__handle_fault(req_env, start_response,
                                              http_resp_headers, service, fault)

    def __handle_fault(self, req_env, start_response, http_resp_headers,
                                                                  service, exc):
        stacktrace=traceback.format_exc()
        logger.error(stacktrace)

        # implementation hook
        if not (service is None):
            service.on_method_exception_object(req_env, exc)
        self.on_exception_object(req_env, exc)

        # FIXME: There's no way to alter soap response headers for the user.
Пример #5
0
    def __handle_soap_request(self, req_env, start_response, url):
        http_resp_headers = {
            'Content-Type': 'text/xml',
            'Content-Length': '0',
        }
        method_name = None

        try:
            # implementation hook
            self.on_call(req_env)

            if req_env['REQUEST_METHOD'].lower() != 'post':
                http_resp_headers['Allow'] = 'POST'
                start_response(HTTP_405, http_resp_headers.items())
                return ['']

            input = req_env.get('wsgi.input')
            length = req_env.get("CONTENT_LENGTH")
            body = input.read(int(length))

            try:
                service = None
                soap_req_header, soap_req_payload = self.__decode_soap_request(
                                                                req_env, body)
                self.validate_request(soap_req_payload)

                method_name = self.__get_method_name(req_env, soap_req_payload)
                if method_name is None:
                    resp = "Could not get method name!"
                    http_resp_headers['Content-Length'] = str(len(resp))
                    start_response(HTTP_500, http_resp_headers.items())
                    return [resp]

                service_class = self.get_service_class(method_name)
                service = self.get_service(service_class, req_env)

            finally:
                # for performance reasons, we don't want the following to run
                # in production even if we don't see the results.
                if logger.level == logging.DEBUG:
                    try:
                        logger.debug(etree.tostring(etree.fromstring(body),
                                                             pretty_print=True))
                    except:
                        logger.debug(body)
                        raise

            # retrieve the method descriptor
            descriptor = service.get_method(method_name)
            func = getattr(service, descriptor.name)

            # decode header object
            if soap_req_header is not None and len(soap_req_header) > 0:
                service.soap_in_header = descriptor.in_header.from_xml(soap_req_header)

            # decode method arguments
            if soap_req_payload is not None and len(soap_req_payload) > 0:
                params = descriptor.in_message.from_xml(soap_req_payload)
            else:
                params = [None] * len(descriptor.in_message._type_info)

            # implementation hook
            service.on_method_call(req_env, method_name, params, soap_req_payload)

            # call the method
            result_raw = service.call_wrapper(func, params)

            # create result message
            result_message = descriptor.out_message()

            # assign raw result to its wrapper, result_message
            out_type = descriptor.out_message._type_info

            if len(out_type) > 0:
                assert len(out_type) == 1
                
                attr_name = descriptor.out_message._type_info.keys()[0]
                setattr(result_message, attr_name, result_raw)

            # transform the results into an element
            # only expect a single element
            soap_resp_body = None
            if not (descriptor.is_async or descriptor.is_callback):
                soap_resp_body = descriptor.out_message.to_xml(result_message,
                                                              self.get_tns())
            soap_resp_header = None
            if not (descriptor.out_header is None or service.soap_out_header is None):
                soap_resp_header = descriptor.out_header.to_xml(
                                        service.soap_out_header, self.get_tns(),
                                        descriptor.out_header.get_type_name())

            # implementation hook
            service.on_method_return(req_env, result_raw, soap_resp_body,
                                                            http_resp_headers)

            # construct the soap response, and serialize it
            envelope = make_soap_envelope(soap_resp_header, soap_resp_body)
            results_str = etree.tostring(envelope, xml_declaration=True,
                                                       encoding=string_encoding)

            if descriptor.mtom:
                http_resp_headers, results_str = apply_mtom(http_resp_headers,
                    results_str,descriptor.out_message._type_info,[result_raw])

            # implementation hook
            self.on_return(req_env, http_resp_headers, results_str)

            # initiate the response
            http_resp_headers['Content-Length'] = str(len(results_str))
            start_response(HTTP_200, http_resp_headers.items())

            if logger.level == logging.DEBUG:
                logger.debug('\033[91m'+ "Response" + '\033[0m')
                logger.debug(etree.tostring(envelope, xml_declaration=True,
                                                             pretty_print=True))

            # return the serialized results
            return [results_str]

        # The user issued a Fault, so handle it just like an exception!
        except Fault, e:
            stacktrace=traceback.format_exc()
            logger.error(stacktrace)
            
            # FIXME: There's no way to alter soap response headers for the user.

            soap_resp_header = None
            soap_resp_body = Fault.to_xml(e, self.get_tns())

            fault_xml = make_soap_envelope(soap_resp_header, soap_resp_body)
            fault_str = etree.tostring(fault_xml, xml_declaration=True,
                                                    encoding=string_encoding)
            if logger.level == logging.DEBUG:
                logger.debug(etree.tostring(etree.fromstring(fault_str),
                                                            pretty_print=True))

            # implementation hook
            if not (service is None):
                service.on_method_exception(req_env, e, fault_xml, fault_str)
            self.on_exception(req_env,e,fault_str)

            # initiate the response
            http_resp_headers['Content-Length'] = str(len(fault_str))
            start_response(HTTP_500, http_resp_headers.items())

            return [fault_str]
Пример #6
0
                e.params={}

            faultstring = str(e)

            if method_name:
                faultcode = '%sFault' % method_name
            else:
                faultcode = 'Server'

            detail = ' '
            logger.error(stacktrace)

            fault = Fault(faultcode, faultstring, detail)

            soap_resp_header = None
            soap_resp_body = Fault.to_xml(fault, self.get_tns())

            fault_xml = make_soap_envelope(soap_resp_header, soap_resp_body)
            fault_str = etree.tostring(fault_xml, xml_declaration=True,
                                                       encoding=string_encoding)
            if logger.level == logging.DEBUG:
                logger.debug(etree.tostring(etree.fromstring(fault_str),
                                                            pretty_print=True))

            # implementation hook
            if not (service is None):
                service.on_method_exception(req_env, e, fault_xml, fault_str)
            self.on_exception(req_env,e,fault_str)

            # initiate the response
            http_resp_headers['Content-Length'] = str(len(fault_str))