A fork of https://github.com/Synerty/SOAPpy-py3 This is a working tree till fixes get imported upstream.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

234 lines
7.9 KiB

  1. import http_server
  2. from SOAPpy.SOAP import *
  3. Fault = faultType
  4. import string, sys
  5. Config = SOAPConfig(debug=1)
  6. class soap_handler:
  7. def __init__(self, encoding='UTF-8', config=Config, namespace=None):
  8. self.namespace = namespace
  9. self.objmap = {}
  10. self.funcmap = {}
  11. self.config = config
  12. self.encoding = encoding
  13. def match (self, request):
  14. return 1
  15. def handle_request (self, request):
  16. [path, params, query, fragment] = request.split_uri()
  17. if request.command == 'post':
  18. request.collector = collector(self, request)
  19. else:
  20. request.error(400)
  21. def continue_request(self, data, request):
  22. # Everthing that follows is cripped from do_POST().
  23. if self.config.debug:
  24. print "\n***RECEIVING***\n", data, "*" * 13 + "\n"
  25. sys.stdout.flush()
  26. try:
  27. r, header, body = parseSOAPRPC(data, header=1, body=1)
  28. method = r._name
  29. args = r._aslist
  30. kw = r._asdict
  31. ns = r._ns
  32. resp = ""
  33. # For faults messages
  34. if ns:
  35. nsmethod = "%s:%s" % (ns, method)
  36. else:
  37. nsmethod = method
  38. try:
  39. # First look for registered functions
  40. if self.funcmap.has_key(ns) and \
  41. self.funcmap[ns].has_key(method):
  42. f = self.funcmap[ns][method]
  43. else: # Now look at registered objects
  44. # Check for nested attributes
  45. if method.find(".") != -1:
  46. t = self.objmap[ns]
  47. l = method.split(".")
  48. for i in l:
  49. t = getattr(t,i)
  50. f = t
  51. else:
  52. f = getattr(self.objmap[ns], method)
  53. except:
  54. if self.config.debug:
  55. import traceback
  56. traceback.print_exc ()
  57. resp = buildSOAP(Fault("%s:Client" % NS.ENV_T,
  58. "No method %s found" % nsmethod,
  59. "%s %s" % tuple(sys.exc_info()[0:2])),
  60. encoding = self.encoding, config = self.config)
  61. status = 500
  62. else:
  63. try:
  64. # If it's wrapped to indicate it takes keywords
  65. # send it keywords
  66. if header:
  67. x = HeaderHandler(header)
  68. if isinstance(f,MethodSig):
  69. c = None
  70. if f.context: # Build context object
  71. c = SOAPContext(header, body, d, self.connection, self.headers,
  72. self.headers["soapaction"])
  73. if f.keywords:
  74. tkw = {}
  75. # This is lame, but have to de-unicode keywords
  76. for (k,v) in kw.items():
  77. tkw[str(k)] = v
  78. if c:
  79. tkw["_SOAPContext"] = c
  80. fr = apply(f,(),tkw)
  81. else:
  82. if c:
  83. fr = apply(f,args,{'_SOAPContext':c})
  84. else:
  85. fr = apply(f,args,{})
  86. else:
  87. fr = apply(f,args,{})
  88. if type(fr) == type(self) and isinstance(fr, voidType):
  89. resp = buildSOAP(kw = {'%sResponse' % method:fr},
  90. encoding = self.encoding,
  91. config = self.config)
  92. else:
  93. resp = buildSOAP(kw =
  94. {'%sResponse' % method:{'Result':fr}},
  95. encoding = self.encoding,
  96. config = self.config)
  97. except Fault, e:
  98. resp = buildSOAP(e, config = self.config)
  99. status = 500
  100. except:
  101. if self.config.debug:
  102. import traceback
  103. traceback.print_exc ()
  104. resp = buildSOAP(Fault("%s:Server" % NS.ENV_T, \
  105. "Method %s failed." % nsmethod,
  106. "%s %s" % tuple(sys.exc_info()[0:2])),
  107. encoding = self.encoding,
  108. config = self.config)
  109. status = 500
  110. else:
  111. status = 200
  112. except Fault,e:
  113. resp = buildSOAP(e, encoding = self.encoding,
  114. config = self.config)
  115. status = 500
  116. except:
  117. # internal error, report as HTTP server error
  118. if self.config.debug:
  119. import traceback
  120. traceback.print_exc ()
  121. request.error(500)
  122. #self.send_response(500)
  123. #self.end_headers()
  124. else:
  125. request['Content-Type'] = 'text/xml; charset="%s"' % self.encoding
  126. request.push(resp)
  127. request.done()
  128. # got a valid SOAP response
  129. #self.send_response(status)
  130. #self.send_header("Content-type",
  131. # 'text/xml; charset="%s"' % self.encoding)
  132. #self.send_header("Content-length", str(len(resp)))
  133. #self.end_headers()
  134. if self.config.debug:
  135. print "\n***SENDING***\n", resp, "*" * 13 + "\n"
  136. sys.stdout.flush()
  137. """
  138. # We should be able to shut down both a regular and an SSL
  139. # connection, but under Python 2.1, calling shutdown on an
  140. # SSL connections drops the output, so this work-around.
  141. # This should be investigated more someday.
  142. if self.config.SSLserver and \
  143. isinstance(self.connection, SSL.Connection):
  144. self.connection.set_shutdown(SSL.SSL_SENT_SHUTDOWN |
  145. SSL.SSL_RECEIVED_SHUTDOWN)
  146. else:
  147. self.connection.shutdown(1)
  148. """
  149. def registerObject(self, object, namespace = ''):
  150. if namespace == '': namespace = self.namespace
  151. self.objmap[namespace] = object
  152. def registerFunction(self, function, namespace = '', funcName = None):
  153. if not funcName : funcName = function.__name__
  154. if namespace == '': namespace = self.namespace
  155. if self.funcmap.has_key(namespace):
  156. self.funcmap[namespace][funcName] = function
  157. else:
  158. self.funcmap[namespace] = {funcName : function}
  159. class collector:
  160. "gathers input for POST and PUT requests"
  161. def __init__ (self, handler, request):
  162. self.handler = handler
  163. self.request = request
  164. self.data = ''
  165. # make sure there's a content-length header
  166. cl = request.get_header ('content-length')
  167. if not cl:
  168. request.error (411)
  169. else:
  170. cl = string.atoi (cl)
  171. # using a 'numeric' terminator
  172. self.request.channel.set_terminator (cl)
  173. def collect_incoming_data (self, data):
  174. self.data = self.data + data
  175. def found_terminator (self):
  176. # set the terminator back to the default
  177. self.request.channel.set_terminator ('\r\n\r\n')
  178. self.handler.continue_request (self.data, self.request)
  179. if __name__ == '__main__':
  180. import asyncore
  181. import http_server
  182. class Thing:
  183. def badparam(self, param):
  184. if param == 'good param':
  185. return 1
  186. else:
  187. return Fault(faultstring='bad param')
  188. def dt(self, aDateTime):
  189. return aDateTime
  190. thing = Thing()
  191. soaph = soap_handler()
  192. soaph.registerObject(thing)
  193. hs = http_server.http_server('', 10080)
  194. hs.install_handler(soaph)
  195. asyncore.loop()