|
-
- import http_server
- from SOAPpy.SOAP import *
- Fault = faultType
- import string, sys
-
- Config = SOAPConfig(debug=1)
-
- class soap_handler:
- def __init__(self, encoding='UTF-8', config=Config, namespace=None):
- self.namespace = namespace
- self.objmap = {}
- self.funcmap = {}
- self.config = config
- self.encoding = encoding
-
- def match (self, request):
- return 1
-
- def handle_request (self, request):
- [path, params, query, fragment] = request.split_uri()
- if request.command == 'post':
- request.collector = collector(self, request)
- else:
- request.error(400)
-
- def continue_request(self, data, request):
- # Everthing that follows is cripped from do_POST().
- if self.config.debug:
- print "\n***RECEIVING***\n", data, "*" * 13 + "\n"
- sys.stdout.flush()
-
- try:
- r, header, body = parseSOAPRPC(data, header=1, body=1)
-
- method = r._name
- args = r._aslist
- kw = r._asdict
-
- ns = r._ns
- resp = ""
- # For faults messages
- if ns:
- nsmethod = "%s:%s" % (ns, method)
- else:
- nsmethod = method
-
- try:
- # First look for registered functions
- if self.funcmap.has_key(ns) and \
- self.funcmap[ns].has_key(method):
- f = self.funcmap[ns][method]
- else: # Now look at registered objects
- # Check for nested attributes
- if method.find(".") != -1:
- t = self.objmap[ns]
- l = method.split(".")
- for i in l:
- t = getattr(t,i)
- f = t
- else:
- f = getattr(self.objmap[ns], method)
- except:
- if self.config.debug:
- import traceback
- traceback.print_exc ()
-
- resp = buildSOAP(Fault("%s:Client" % NS.ENV_T,
- "No method %s found" % nsmethod,
- "%s %s" % tuple(sys.exc_info()[0:2])),
- encoding = self.encoding, config = self.config)
- status = 500
- else:
- try:
- # If it's wrapped to indicate it takes keywords
- # send it keywords
- if header:
- x = HeaderHandler(header)
-
- if isinstance(f,MethodSig):
- c = None
- if f.context: # Build context object
- c = SOAPContext(header, body, d, self.connection, self.headers,
- self.headers["soapaction"])
-
- if f.keywords:
- tkw = {}
- # This is lame, but have to de-unicode keywords
- for (k,v) in kw.items():
- tkw[str(k)] = v
- if c:
- tkw["_SOAPContext"] = c
- fr = apply(f,(),tkw)
- else:
- if c:
- fr = apply(f,args,{'_SOAPContext':c})
- else:
- fr = apply(f,args,{})
- else:
- fr = apply(f,args,{})
- if type(fr) == type(self) and isinstance(fr, voidType):
- resp = buildSOAP(kw = {'%sResponse' % method:fr},
- encoding = self.encoding,
- config = self.config)
- else:
- resp = buildSOAP(kw =
- {'%sResponse' % method:{'Result':fr}},
- encoding = self.encoding,
- config = self.config)
- except Fault, e:
- resp = buildSOAP(e, config = self.config)
- status = 500
- except:
- if self.config.debug:
- import traceback
- traceback.print_exc ()
-
- resp = buildSOAP(Fault("%s:Server" % NS.ENV_T, \
- "Method %s failed." % nsmethod,
- "%s %s" % tuple(sys.exc_info()[0:2])),
- encoding = self.encoding,
- config = self.config)
- status = 500
- else:
- status = 200
- except Fault,e:
- resp = buildSOAP(e, encoding = self.encoding,
- config = self.config)
- status = 500
- except:
- # internal error, report as HTTP server error
- if self.config.debug:
- import traceback
- traceback.print_exc ()
- request.error(500)
- #self.send_response(500)
- #self.end_headers()
- else:
- request['Content-Type'] = 'text/xml; charset="%s"' % self.encoding
- request.push(resp)
- request.done()
- # got a valid SOAP response
- #self.send_response(status)
- #self.send_header("Content-type",
- # 'text/xml; charset="%s"' % self.encoding)
- #self.send_header("Content-length", str(len(resp)))
- #self.end_headers()
-
- if self.config.debug:
- print "\n***SENDING***\n", resp, "*" * 13 + "\n"
- sys.stdout.flush()
-
- """
- # We should be able to shut down both a regular and an SSL
- # connection, but under Python 2.1, calling shutdown on an
- # SSL connections drops the output, so this work-around.
- # This should be investigated more someday.
-
- if self.config.SSLserver and \
- isinstance(self.connection, SSL.Connection):
- self.connection.set_shutdown(SSL.SSL_SENT_SHUTDOWN |
- SSL.SSL_RECEIVED_SHUTDOWN)
- else:
- self.connection.shutdown(1)
- """
-
- def registerObject(self, object, namespace = ''):
- if namespace == '': namespace = self.namespace
- self.objmap[namespace] = object
-
- def registerFunction(self, function, namespace = '', funcName = None):
- if not funcName : funcName = function.__name__
- if namespace == '': namespace = self.namespace
- if self.funcmap.has_key(namespace):
- self.funcmap[namespace][funcName] = function
- else:
- self.funcmap[namespace] = {funcName : function}
-
-
-
- class collector:
- "gathers input for POST and PUT requests"
-
- def __init__ (self, handler, request):
-
- self.handler = handler
- self.request = request
- self.data = ''
-
- # make sure there's a content-length header
- cl = request.get_header ('content-length')
-
- if not cl:
- request.error (411)
- else:
- cl = string.atoi (cl)
- # using a 'numeric' terminator
- self.request.channel.set_terminator (cl)
-
- def collect_incoming_data (self, data):
- self.data = self.data + data
-
- def found_terminator (self):
- # set the terminator back to the default
- self.request.channel.set_terminator ('\r\n\r\n')
- self.handler.continue_request (self.data, self.request)
-
-
- if __name__ == '__main__':
-
- import asyncore
- import http_server
-
- class Thing:
-
- def badparam(self, param):
- if param == 'good param':
- return 1
- else:
- return Fault(faultstring='bad param')
-
- def dt(self, aDateTime):
- return aDateTime
-
- thing = Thing()
- soaph = soap_handler()
- soaph.registerObject(thing)
-
- hs = http_server.http_server('', 10080)
- hs.install_handler(soaph)
-
- asyncore.loop()
|