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]
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.