Server IP : 127.0.0.2 / Your IP : 18.217.65.73 Web Server : Apache/2.4.18 (Ubuntu) System : User : www-data ( ) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/lib/python2.7/dist-packages/ZSI/ |
Upload File : |
'''Simple Service Container -- use with wsdl2py generated modules. ''' import urlparse, types, os, sys, cStringIO as StringIO, thread,re from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from ZSI import ParseException, FaultFromException, FaultFromZSIException, Fault from ZSI import _copyright, _seqtypes, _get_element_nsuri_name, resolvers from ZSI import _get_idstr from ZSI.address import Address from ZSI.parse import ParsedSoap from ZSI.writer import SoapWriter from ZSI.dispatch import _ModPythonSendXML, _ModPythonSendFault, _CGISendXML, _CGISendFault from ZSI.dispatch import SOAPRequestHandler as BaseSOAPRequestHandler """ Functions: _Dispatch AsServer GetSOAPContext Classes: SOAPContext NoSuchService PostNotSpecified SOAPActionNotSpecified ServiceSOAPBinding WSAResource SimpleWSResource SOAPRequestHandler ServiceContainer """ class NoSuchService(Exception): pass class UnknownRequestException(Exception): pass class PostNotSpecified(Exception): pass class SOAPActionNotSpecified(Exception): pass class WSActionException(Exception): pass class WSActionNotSpecified(WSActionException): pass class NotAuthorized(Exception): pass class ServiceAlreadyPresent(Exception): pass class SOAPContext: def __init__(self, container, xmldata, ps, connection, httpheaders, soapaction): self.container = container self.xmldata = xmldata self.parsedsoap = ps self.connection = connection self.httpheaders= httpheaders self.soapaction = soapaction _contexts = dict() def GetSOAPContext(): global _contexts return _contexts[thread.get_ident()] def _Dispatch(ps, server, SendResponse, SendFault, post, action, nsdict={}, **kw): '''Send ParsedSoap instance to ServiceContainer, which dispatches to appropriate service via post, and method via action. Response is a self-describing pyobj, which is passed to a SoapWriter. Call SendResponse or SendFault to send the reply back, appropriately. server -- ServiceContainer instance ''' localURL = 'http://%s:%d%s' %(server.server_name,server.server_port,post) address = action service = server.getNode(post) isWSResource = False if isinstance(service, WSAResource): isWSResource = True service.setServiceURL(localURL) address = Address() try: address.parse(ps) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if action and action != address.getAction(): e = WSActionException('SOAP Action("%s") must match WS-Action("%s") if specified.' \ %(action,address.getAction())) return SendFault(FaultFromException(e, 0, None), **kw) action = address.getAction() if isinstance(service, ServiceInterface) is False: e = NoSuchService('no service at POST(%s) in container: %s' %(post,server)) return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if not service.authorize(None, post, action): return SendFault(Fault(Fault.Server, "Not authorized"), code=401) #try: # raise NotAuthorized() #except Exception, e: #return SendFault(FaultFromException(e, 0, None), code=401, **kw) ##return SendFault(FaultFromException(NotAuthorized(), 0, None), code=401, **kw) try: method = service.getOperation(ps, address) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) try: if isWSResource is True: request,result = method(ps, address) else: request,result = method(ps) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Verify if Signed service.verify(ps) # If No response just return. if result is None: return SendResponse('', **kw) sw = SoapWriter(nsdict=nsdict) try: sw.serialize(result) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) if isWSResource is True: action = service.getResponseAction(ps, action) addressRsp = Address(action=action) try: addressRsp.setResponseFromWSAddress(address, localURL) addressRsp.serialize(sw) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) # Create Signatures service.sign(sw) try: soapdata = str(sw) return SendResponse(soapdata, **kw) except Exception, e: return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw) def AsServer(port=80, services=()): '''port -- services -- list of service instances ''' address = ('', port) sc = ServiceContainer(address, services) sc.serve_forever() class ServiceInterface: '''Defines the interface for use with ServiceContainer Handlers. class variables: soapAction -- dictionary of soapAction keys, and operation name values. These are specified in the WSDL soap bindings. There must be a class method matching the operation name value. If WS-Action is used the keys are WS-Action request values, according to the spec if soapAction and WS-Action is specified they must be equal. wsAction -- dictionary of operation name keys and WS-Action response values. These values are specified by the portType. root -- dictionary of root element keys, and operation name values. ''' soapAction = {} wsAction = {} root = {} def __init__(self, post): self.post = post def authorize(self, auth_info, post, action): return 1 def __str__(self): return '%s(%s) POST(%s)' %(self.__class__.__name__, _get_idstr(self), self.post) def sign(self, sw): return def verify(self, ps): return def getPost(self): return self.post def getOperation(self, ps, action): '''Returns a method of class. action -- soapAction value ''' opName = self.getOperationName(ps, action) return getattr(self, opName) def getOperationName(self, ps, action): '''Returns operation name. action -- soapAction value ''' method = self.root.get(_get_element_nsuri_name(ps.body_root)) or \ self.soapAction.get(action) if method is None: raise UnknownRequestException, \ 'failed to map request to a method: action(%s), root%s' %(action,_get_element_nsuri_name(ps.body_root)) return method class ServiceSOAPBinding(ServiceInterface): '''Binding defines the set of wsdl:binding operations, it takes as input a ParsedSoap instance and parses it into a pyobj. It returns a response pyobj. ''' def __init__(self, post): ServiceInterface.__init__(self, post) def __call___(self, action, ps): return self.getOperation(ps, action)(ps) class WSAResource(ServiceSOAPBinding): '''Simple WSRF service, performs method resolutions based on WS-Action values rather than SOAP Action. class variables: encoding wsAction -- Must override to set output Action values. soapAction -- Must override to set input Action values. ''' encoding = "UTF-8" def __init__(self, post): ''' post -- POST value ''' assert isinstance(self.soapAction, dict), "soapAction must be a dict" assert isinstance(self.wsAction, dict), "wsAction must be a dict" ServiceSOAPBinding.__init__(self, post) def __call___(self, action, ps, address): return self.getOperation(ps, action)(ps, address) def getServiceURL(self): return self._url def setServiceURL(self, url): self._url = url def getOperation(self, ps, address): '''Returns a method of class. address -- ws-address ''' action = address.getAction() opName = self.getOperationName(ps, action) return getattr(self, opName) def getResponseAction(self, ps, action): '''Returns response WS-Action if available action -- request WS-Action value. ''' opName = self.getOperationName(ps, action) if self.wsAction.has_key(opName) is False: raise WSActionNotSpecified, 'wsAction dictionary missing key(%s)' %opName return self.wsAction[opName] def do_POST(self): '''The POST command. This is called by HTTPServer, not twisted. action -- SOAPAction(HTTP header) or wsa:Action(SOAP:Header) ''' global _contexts soapAction = self.headers.getheader('SOAPAction') post = self.path if not post: raise PostNotSpecified, 'HTTP POST not specified in request' if soapAction: soapAction = soapAction.strip('\'"') post = post.strip('\'"') try: ct = self.headers['content-type'] if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, self.rfile) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve, readerclass=DomletteReader) else: length = int(self.headers['content-length']) ps = ParsedSoap(self.rfile.read(length), readerclass=DomletteReader) except ParseException, e: self.send_fault(FaultFromZSIException(e)) except Exception, e: # Faulted while processing; assume it's in the header. self.send_fault(FaultFromException(e, 1, sys.exc_info()[2])) else: # Keep track of calls thread_id = thread.get_ident() _contexts[thread_id] = SOAPContext(self.server, xml, ps, self.connection, self.headers, soapAction) try: _Dispatch(ps, self.server, self.send_xml, self.send_fault, post=post, action=soapAction) except Exception, e: self.send_fault(FaultFromException(e, 0, sys.exc_info()[2])) # Clean up after the call if _contexts.has_key(thread_id): del _contexts[thread_id] class SOAPRequestHandler(BaseSOAPRequestHandler): '''SOAP handler. ''' def do_POST(self): '''The POST command. action -- SOAPAction(HTTP header) or wsa:Action(SOAP:Header) ''' soapAction = self.headers.getheader('SOAPAction') post = self.path if not post: raise PostNotSpecified, 'HTTP POST not specified in request' if soapAction: soapAction = soapAction.strip('\'"') post = post.strip('\'"') try: ct = self.headers['content-type'] if ct.startswith('multipart/'): cid = resolvers.MIMEResolver(ct, self.rfile) xml = cid.GetSOAPPart() ps = ParsedSoap(xml, resolver=cid.Resolve) else: length = int(self.headers['content-length']) xml = self.rfile.read(length) ps = ParsedSoap(xml) except ParseException, e: self.send_fault(FaultFromZSIException(e)) except Exception, e: # Faulted while processing; assume it's in the header. self.send_fault(FaultFromException(e, 1, sys.exc_info()[2])) else: # Keep track of calls thread_id = thread.get_ident() _contexts[thread_id] = SOAPContext(self.server, xml, ps, self.connection, self.headers, soapAction) try: _Dispatch(ps, self.server, self.send_xml, self.send_fault, post=post, action=soapAction) except Exception, e: self.send_fault(FaultFromException(e, 0, sys.exc_info()[2])) # Clean up after the call if _contexts.has_key(thread_id): del _contexts[thread_id] def do_GET(self): '''The GET command. ''' if self.path.lower().endswith("?wsdl"): service_path = self.path[:-5] service = self.server.getNode(service_path) if hasattr(service, "_wsdl"): wsdl = service._wsdl # update the soap:location tag in the wsdl to the actual server # location # - default to 'http' as protocol, or use server-specified protocol proto = 'http' if hasattr(self.server,'proto'): proto = self.server.proto serviceUrl = '%s://%s:%d%s' % (proto, self.server.server_name, self.server.server_port, service_path) soapAddress = '<soap:address location="%s"/>' % serviceUrl wsdlre = re.compile('\<soap:address[^\>]*>',re.IGNORECASE) wsdl = re.sub(wsdlre,soapAddress,wsdl) self.send_xml(wsdl) else: self.send_error(404, "WSDL not available for that service [%s]." % self.path) else: self.send_error(404, "Service not found [%s]." % self.path) class ServiceContainer(HTTPServer): '''HTTPServer that stores service instances according to POST values. An action value is instance specific, and specifies an operation (function) of an instance. ''' class NodeTree: '''Simple dictionary implementation of a node tree ''' def __init__(self): self.__dict = {} def __str__(self): return str(self.__dict) def listNodes(self): print self.__dict.keys() def getNode(self, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if self.__dict.has_key(path): return self.__dict[path] else: raise NoSuchService, 'No service(%s) in ServiceContainer' %path def setNode(self, service, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if not isinstance(service, ServiceSOAPBinding): raise TypeError, 'A Service must implement class ServiceSOAPBinding' if self.__dict.has_key(path): raise ServiceAlreadyPresent, 'Service(%s) already in ServiceContainer' % path else: self.__dict[path] = service def removeNode(self, url): path = urlparse.urlsplit(url)[2] if path.startswith("/"): path = path[1:] if self.__dict.has_key(path): node = self.__dict[path] del self.__dict[path] return node else: raise NoSuchService, 'No service(%s) in ServiceContainer' %path def __init__(self, server_address, services=[], RequestHandlerClass=SOAPRequestHandler): '''server_address -- RequestHandlerClass -- ''' HTTPServer.__init__(self, server_address, RequestHandlerClass) self._nodes = self.NodeTree() map(lambda s: self.setNode(s), services) def __str__(self): return '%s(%s) nodes( %s )' %(self.__class__, _get_idstr(self), str(self._nodes)) def __call__(self, ps, post, action, address=None): '''ps -- ParsedSoap representing the request post -- HTTP POST --> instance action -- Soap Action header --> method address -- Address instance representing WS-Address ''' method = self.getCallBack(ps, post, action) if (isinstance(method.im_self, WSAResource) or isinstance(method.im_self, SimpleWSResource)): return method(ps, address) return method(ps) def setNode(self, service, url=None): if url is None: url = service.getPost() self._nodes.setNode(service, url) def getNode(self, url): return self._nodes.getNode(url) def removeNode(self, url): self._nodes.removeNode(url) class SimpleWSResource(ServiceSOAPBinding): def getNode(self, post): '''post -- POST HTTP value ''' return self._nodes.getNode(post) def setNode(self, service, post): '''service -- service instance post -- POST HTTP value ''' self._nodes.setNode(service, post) def getCallBack(self, ps, post, action): '''post -- POST HTTP value action -- SOAP Action value ''' node = self.getNode(post) if node is None: raise NoSuchFunction if node.authorize(None, post, action): return node.getOperation(ps, action) else: raise NotAuthorized, "Authorization failed for method %s" % action if __name__ == '__main__': print _copyright