Package gavo :: Package web :: Module soaprender
[frames] | no frames]

Source Code for Module gavo.web.soaprender

  1  """ 
  2  SOAP rendering and related classes. 
  3  """ 
  4   
  5  #c Copyright 2008-2019, the GAVO project 
  6  #c 
  7  #c This program is free software, covered by the GNU GPL.  See the 
  8  #c COPYING file in the source distribution. 
  9   
 10   
 11  from nevow import inevow 
 12   
 13  from twisted.web import soap 
 14   
 15  from gavo import base 
 16  from gavo import svcs 
 17  from gavo.web import grend 
 18  from gavo.web import wsdl 
19 20 21 -class SOAPProcessor(soap.SOAPPublisher):
22 """A helper to the SOAP renderer. 23 24 It's actually a nevow resource ("page"), so whatever really has 25 to do with SOAP (as opposed to returning WSDL) is done by this. 26 """
27 - def __init__(self, ctx, service, runServiceFromArgs):
28 self.ctx, self.service = ctx, service 29 self.runServiceFromArgs = runServiceFromArgs 30 soap.SOAPPublisher.__init__(self)
31
32 - def _gotResult(self, result, request, methodName):
33 # We want SOAP docs that actually match what we advertize in the WSDL. 34 # So, I override SOAPPublisher's haphazard SOAPpy-based formatter. 35 if result is None: # Error has occurred. This callback shouldn't be 36 # called at all, but for some reason it is, and I can't be bothered 37 # now to figure out why. 38 return "" 39 response = wsdl.serializePrimaryTable(result.original, self.service) 40 self._sendResponse(request, response)
41
42 - def _gotError(self, failure, request, methodName):
43 failure.printTraceback() 44 try: 45 self._sendResponse(request, 46 wsdl.formatFault(failure.value, self.service), status=500) 47 except: 48 base.ui.logError("Error while writing SOAP error:")
49
50 - def soap_useService(self, *args):
51 try: 52 return self.runServiceFromArgs(self.ctx, args) 53 except Exception as exc: 54 base.ui.notifyError("SOAP service failed.") 55 return self._formatError(exc)
56
57 - def _formatError(self, exc):
58 request = inevow.IRequest(self.ctx) 59 self._sendResponse(request, wsdl.formatFault(exc, self.service), 60 status=500)
61
62 63 -class SOAPRenderer(grend.ServiceBasedPage):
64 """A renderer that receives and formats SOAP messages. 65 66 This is for remote procedure calls. In particular, the renderer takes 67 care that you can obtain a WSDL definition of the service by 68 appending ?wsdl to the access URL. 69 """ 70 name="soap" 71 preferredMethod = "POST" 72 urlUse = "full" 73 74 @classmethod
75 - def makeAccessURL(cls, baseURL):
76 return baseURL+"/soap/go"
77
78 - def runServiceFromArgs(self, ctx, args):
79 """starts the service. 80 81 This being called back from the SOAPProcessor, and args is the 82 argument tuple as given from SOAP. 83 """ 84 inputPars = dict(zip( 85 [f.name for f in self.service.getInputKeysFor(self)], 86 args)) 87 return self.runServiceWithFormalData(inputPars, ctx)
88
89 - def renderHTTP(self, ctx):
90 """returns the WSDL for service. 91 92 This is only called when there's a ?wsdl arg in the request, 93 otherwise locateChild will return the SOAPProcessor. 94 """ 95 request = inevow.IRequest(ctx) 96 if not hasattr(self.service, "_generatedWSDL"): 97 queryMeta = svcs.QueryMeta.fromContext(ctx) 98 self.service._generatedWSDL = wsdl.makeSOAPWSDLForService( 99 self.service, queryMeta).render() 100 request.setHeader("content-type", "text/xml") 101 return self.service._generatedWSDL
102
103 - def locateChild(self, ctx, segments):
104 request = inevow.IRequest(ctx) 105 if request.uri.endswith("?wsdl"): # XXX TODO: use parsed headers here 106 return self, () 107 if request.method!='POST': 108 # SOAP only makes sense when data is posted; with no data, 109 # twisted generates ugly tracebacks, and we may as well do 110 # something sensible, like... redirect to the service's info 111 # page 112 raise svcs.WebRedirect(self.service.getURL("info")) 113 return SOAPProcessor(ctx, self.service, self.runServiceFromArgs), ()
114