tornado(およびサードパーティのtornadowsモジュール)を使用してSOAPWebサービスを実装しています。私のサービスの操作の1つは別の操作を呼び出す必要があるので、チェーンがあります。
- 操作Aへの(SOAPUIを介した)外部要求
- 操作Bへの(要求モジュールを介した)内部要求
- 操作Bからの内部応答
- 操作Aからの外部応答
すべてが1つのサービスで実行されているため、どこかでブロックされています。私はトルネードの非同期機能に精通していません。
すべてが単一のURLで受信され、SOAPActionリクエストヘッダー値に基づいて特定の操作(処理を実行するメソッド)が呼び出されるため、リクエスト処理メソッド(post)は1つだけです。postメソッドを@tornado.web.asynchronousで装飾し、最後に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サービスの2つの操作(get_currencyとget_temp)です。したがって、SOAPUIはget_tempにヒットし、get_currencyへのSOAPリクエストを作成します(make_curr_requestおよびrequestsモジュールを介して)。次に、結果をチェーンバックしてSOAPUIに送り返す必要があります。
サービスの実際の操作は意味がありません(温度を求められたときに通貨を返す)が、私は機能を動作させようとしているだけであり、これらは私が持っている操作です。