我正在使用 tornado(和第三方 tornadows 模块)实现 SOAP Web 服务。我的服务中的一个操作需要调用另一个,所以我有链:
- (通过 SOAPUI)对操作 A 的外部请求
- 操作 B 中的内部请求(通过请求模块)
- 操作 B 的内部响应
- 操作 A 的外部响应
因为它都在一个服务中运行,所以它在某个地方被阻止了。我不熟悉龙卷风的异步功能。
只有一种请求处理方法(post),因为所有内容都来自单个 url,然后根据 SOAPAction 请求标头值调用特定操作(执行处理的方法)。我用@tornado.web.asynchronous 修饰了我的 post 方法,最后调用了 self.finish() 但没有骰子。
龙卷风可以处理这种情况吗?如果可以,我该如何实施?
编辑(添加代码):
class SoapHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def post(self):
""" Method post() to process of requests and responses SOAP messages """
try:
self._request = self._parseSoap(self.request.body)
soapaction = self.request.headers['SOAPAction'].replace('"','')
self.set_header('Content-Type','text/xml')
for operations in dir(self):
operation = getattr(self,operations)
method = ''
if callable(operation) and hasattr(operation,'_is_operation'):
num_methods = self._countOperations()
if hasattr(operation,'_operation') and soapaction.endswith(getattr(operation,'_operation')) and num_methods > 1:
method = getattr(operation,'_operation')
self._response = self._executeOperation(operation,method=method)
break
elif num_methods == 1:
self._response = self._executeOperation(operation,method='')
break
soapmsg = self._response.getSoap().toprettyxml()
self.write(soapmsg)
self.finish()
except Exception as detail:
#traceback.print_exc(file=sys.stdout)
wsdl_nameservice = self.request.uri.replace('/','').replace('?wsdl','').replace('?WSDL','')
fault = soapfault('Error in web service : {fault}'.format(fault=detail), wsdl_nameservice)
self.write(fault.getSoap().toxml())
self.finish()
这是来自请求处理程序的 post 方法。它来自我正在使用的 Web 服务模块(所以不是我的代码),但我添加了异步装饰器和 self.finish()。它基本上所做的只是调用正确的操作(如请求的 SOAPAction 中所述)。
class CountryService(soaphandler.SoapHandler):
@webservice(_params=GetCurrencyRequest, _returns=GetCurrencyResponse)
def get_currency(self, input):
result = db_query(input.country, 'currency')
get_currency_response = GetCurrencyResponse()
get_currency_response.currency = result
headers = None
return headers, get_currency_response
@webservice(_params=GetTempRequest, _returns=GetTempResponse)
def get_temp(self, input):
get_temp_response = GetTempResponse()
curr = self.make_curr_request(input.country)
get_temp_response.temp = curr
headers = None
return headers, get_temp_response
def make_curr_request(self, country):
soap_request = """<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:coun='CountryService'>
<soapenv:Header/>
<soapenv:Body>
<coun:GetCurrencyRequestget_currency>
<country>{0}</country>
</coun:GetCurrencyRequestget_currency>
</soapenv:Body>
</soapenv:Envelope>""".format(country)
headers = {'Content-Type': 'text/xml;charset=UTF-8', 'SOAPAction': '"http://localhost:8080/CountryService/get_currency"'}
r = requests.post('http://localhost:8080/CountryService', data=soap_request, headers=headers)
try:
tree = etree.fromstring(r.content)
currency = tree.xpath('//currency')
message = currency[0].text
except:
message = "Failure"
return message
这是 Web 服务的两个操作(get_currency 和 get_temp)。因此 SOAPUI 命中 get_temp,它向 get_currency 发出 SOAP 请求(通过 make_curr_request 和 requests 模块)。然后结果应该只是链回并被发送回 SOAPUI。
服务的实际操作没有任何意义(当要求温度时返回货币)但我只是想让功能正常工作,这些是我拥有的操作。