Ticket #552: soap.py

File soap.py, 11.9 KB (added by upadhyay@…, 19 years ago)

soap.py, put it in django/contrib

Line 
1""" SOAP View for Django
2
3 This module contains blah....
4"""
5from __future__ import nested_scopes
6
7import re
8import sys
9import thread
10from types import *
11
12# SOAPpy modules
13from SOAPpy.version import __version__
14from SOAPpy.Parser import parseSOAPRPC
15from SOAPpy.Config import Config
16from SOAPpy.Types import faultType, voidType, simplify
17from SOAPpy.NS import NS
18from SOAPpy.SOAPBuilder import buildSOAP
19from SOAPpy.Utilities import debugHeader, debugFooter
20from SOAPpy.Server import SOAPServerBase, HeaderHandler, SOAPContext, MethodSig
21
22try: from M2Crypto import SSL
23except: pass
24
25from django.utils.httpwrappers import HttpResponseServerError, HttpResponse
26
27_contexts = dict()
28
29class SimpleSOAPView(SOAPServerBase):
30 def __init__(self, encoding = 'UTF-8', config = Config, namespace = None):
31
32 # Test the encoding, raising an exception if it's not known
33 if encoding != None:
34 ''.encode(encoding)
35
36 self.namespace = namespace
37 self.objmap = {}
38 self.funcmap = {}
39 self.encoding = encoding
40 self.config = config
41
42 self.allow_reuse_address = 1
43
44
45 def dispatch(self, data):
46 global _contexts
47 try:
48 (r, header, body, attrs) = \
49 parseSOAPRPC(data, header = 1, body = 1, attrs = 1)
50 print (r, header, body, attrs)
51 method = r._name
52 args = r._aslist()
53 kw = r._asdict()
54
55 if self.config.simplify_objects:
56 args = simplify(args)
57 kw = simplify(kw)
58
59 if self.config.specialArgs:
60 ordered_args = {}
61 named_args = {}
62
63 for (k,v) in kw.items():
64 if k[0]=="v":
65 try:
66 i = int(k[1:])
67 ordered_args[i] = v
68 except ValueError:
69 named_args[str(k)] = v
70
71 else:
72 named_args[str(k)] = v
73
74 ns = r._ns
75
76 if len(self.path) > 1 and not ns:
77 ns = self.path.replace("/", ":")
78 if ns[0] == ":": ns = ns[1:]
79
80 # authorization method
81 a = None
82
83 keylist = ordered_args.keys()
84 keylist.sort()
85
86 # create list in proper order w/o names
87 tmp = map( lambda x: ordered_args[x], keylist)
88 ordered_args = tmp
89
90 resp = ""
91
92 # For fault messages
93 if ns:
94 nsmethod = "%s:%s" % (ns, method)
95 else:
96 nsmethod = method
97
98 try:
99 # First look for registered functions
100 if self.funcmap.has_key(ns) and \
101 self.funcmap[ns].has_key(method):
102 f = self.funcmap[ns][method]
103
104 # look for the authorization method
105 if self.config.authMethod != None:
106 authmethod = self.config.authMethod
107 if self.funcmap.has_key(ns) and \
108 self.funcmap[ns].has_key(authmethod):
109 a = self.funcmap[ns][authmethod]
110 else:
111 # Now look at registered objects
112 # Check for nested attributes. This works even if
113 # there are none, because the split will return
114 # [method]
115 f = self.objmap[ns]
116
117 # Look for the authorization method
118 if self.config.authMethod != None:
119 authmethod = self.config.authMethod
120 if hasattr(f, authmethod):
121 a = getattr(f, authmethod)
122
123 # then continue looking for the method
124 l = method.split(".")
125 for i in l:
126 f = getattr(f, i)
127 except Exception, e:
128 info = sys.exc_info()
129 resp = buildSOAP(faultType("%s:Client" % NS.ENV_T,
130 "Method Not Found",
131 "%s : %s %s %s" % (nsmethod,
132 info[0],
133 info[1],
134 info[2])),
135 encoding = self.encoding,
136 config = self.config)
137 del info
138 #print e
139 return resp
140 else:
141 try:
142 if header:
143 x = HeaderHandler(header, attrs)
144
145 fr = 1
146
147 # call context book keeping
148 # We're stuffing the method into the soapaction if there
149 # isn't one, someday, we'll set that on the client
150 # and it won't be necessary here
151 # for now we're doing both
152
153 if "SOAPAction".lower() not in self.headers.keys() or \
154 self.headers["SOAPAction"] == "\"\"":
155 self.headers["SOAPAction"] = method
156
157 thread_id = thread.get_ident()
158 _contexts[thread_id] = SOAPContext(header, body,
159 attrs, data,
160 None,
161 self.headers,
162 self.headers["SOAPAction"])
163
164 # Do an authorization check
165 if a != None:
166 if not apply(a, (), {"_SOAPContext" :
167 _contexts[thread_id] }):
168 raise faultType("%s:Server" % NS.ENV_T,
169 "Authorization failed.",
170 "%s" % nsmethod)
171
172 # If it's wrapped, some special action may be needed
173 if isinstance(f, MethodSig):
174 c = None
175
176 if f.context: # retrieve context object
177 c = _contexts[thread_id]
178
179 if self.config.specialArgs:
180 if c:
181 named_args["_SOAPContext"] = c
182 fr = apply(f, ordered_args, named_args)
183 elif f.keywords:
184 # This is lame, but have to de-unicode
185 # keywords
186
187 strkw = {}
188
189 for (k, v) in kw.items():
190 strkw[str(k)] = v
191 if c:
192 strkw["_SOAPContext"] = c
193 fr = apply(f, (), strkw)
194 elif c:
195 fr = apply(f, args, {'_SOAPContext':c})
196 else:
197 fr = apply(f, args, {})
198
199 else:
200 if self.config.specialArgs:
201 fr = apply(f, ordered_args, named_args)
202 else:
203 fr = apply(f, args, {})
204
205
206 if type(fr) == type(self) and \
207 isinstance(fr, voidType):
208 resp = buildSOAP(kw = {'%sResponse' % method: fr},
209 encoding = self.encoding,
210 config = self.config)
211 else:
212 resp = buildSOAP(kw =
213 {'%sResponse' % method: {'Result': fr}},
214 encoding = self.encoding,
215 config = self.config)
216
217 # Clean up _contexts
218 if _contexts.has_key(thread_id):
219 del _contexts[thread_id]
220
221 except Exception, e:
222 import traceback
223 info = sys.exc_info()
224
225 if isinstance(e, faultType):
226 f = e
227 else:
228 f = faultType("%s:Server" % NS.ENV_T,
229 "Method Failed",
230 "%s" % nsmethod)
231
232 if self.config.returnFaultInfo:
233 f._setDetail("".join(traceback.format_exception(
234 info[0], info[1], info[2])))
235 elif not hasattr(f, 'detail'):
236 f._setDetail("%s %s" % (info[0], info[1]))
237 del info
238 print e
239 resp = buildSOAP(f, encoding = self.encoding,
240 config = self.config)
241 return resp
242 else:
243 return resp
244 except faultType, e:
245 import traceback
246 info = sys.exc_info()
247 if self.config.returnFaultInfo:
248 e._setDetail("".join(traceback.format_exception(
249 info[0], info[1], info[2])))
250 elif not hasattr(e, 'detail'):
251 e._setDetail("%s %s" % (info[0], info[1]))
252 del info
253
254 resp = buildSOAP(e, encoding = self.encoding,
255 config = self.config)
256
257 def wsdl(self):
258 method = 'wsdl'
259 function = namespace = None
260 if self.funcmap.has_key(namespace) and self.funcmap[namespace].has_key(method):
261 function = self.funcmap[namespace][method]
262 else:
263 if namespace in self.objmap.keys():
264 function = self.objmap[namespace]
265 l = method.split(".")
266 for i in l:
267 function = getattr(function, i)
268
269 if function:
270 response = apply(function, ())
271 return str(response)
272 else:
273 return 'WSDL could not be generated!'
274
275 def __call__(self, request, path=''):
276 """ SimpleXMLRPCView is callable so it can be installed as a view.
277
278 Django calls it with 'request', which is a HttpRequest
279 """
280 self.path = path
281 self.headers = request.META # compatible?
282
283 if request.META['REQUEST_METHOD'] == 'GET':
284 if request.META['QUERY_STRING'] == 'wsdl':
285 wsdl = self.wsdl()
286 return HttpResoponse(wsdl, mimetype='text/xml')
287 else:
288 return HttpResponseServerError('Use /?wsdl to get WSDL.')
289 elif request.META['REQUEST_METHOD'] != 'POST':
290 return HttpResponseServerError('Non POST methods not allowed.')
291
292 try:
293 response = self.dispatch(request.raw_post_data)
294 print response
295 print self.objmap, self.funcmap
296 except Exception, e:
297 # internal error, report as HTTP server error
298 return HttpResponseServerError('internal error')
299 else:
300 # got a valid XML RPC response
301 return HttpResponse(response, mimetype="text/xml")
302
Back to Top