Django

Code

Ticket #552: soap.py

File soap.py, 11.9 kB (added by upadhyay@gmail.com, 4 years ago)

soap.py, put it in django/contrib

Line 
1 """ SOAP View for Django
2
3     This module contains blah....   
4 """
5 from __future__ import nested_scopes
6
7 import re
8 import sys
9 import thread
10 from types import *
11
12 # SOAPpy modules
13 from SOAPpy.version     import __version__
14 from SOAPpy.Parser      import parseSOAPRPC
15 from SOAPpy.Config      import Config
16 from SOAPpy.Types       import faultType, voidType, simplify
17 from SOAPpy.NS          import NS
18 from SOAPpy.SOAPBuilder import buildSOAP
19 from SOAPpy.Utilities   import debugHeader, debugFooter
20 from SOAPpy.Server      import SOAPServerBase, HeaderHandler, SOAPContext, MethodSig
21
22 try: from M2Crypto import SSL
23 except: pass
24
25 from django.utils.httpwrappers import HttpResponseServerError, HttpResponse
26
27 _contexts = dict()
28
29 class 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")