美文网首页
使用构造的soap报文与Webservice通信

使用构造的soap报文与Webservice通信

作者: hylide | 来源:发表于2017-07-17 19:52 被阅读0次

    背景:项目使用了 gSoap 来自动生成 Webservice, 在尝试了诸多 python 类库之后( suds, pysoap等),均无法与server端正确通信

    正因如此,开始尝试自己构造 soap 报文来与 Webservice 通信。

    WebService 暴露的接口如下:

      ControlDevice(xs:string deviceSerialNums, xs:string szCommandInfo, xs:string szCommandParam, xs:boolean bGroup, )
      ExportConfigs(xs:string deviceSerialNum, xs:string softServiceName, xs:string configName, )
      GetDeviceInfo(xs:string deviceSerialNums, xs:int nDeviceInfoType, xs:boolean bGroup, )
      GetHSCConfig(xs:string deviceSerialNum, xs:string softServiceName, xs:string configName, )
      GetSoftStatusInfo(xs:string deviceSerialNum, xs:string softServiceName, xs:string section, )
      GetUpgradeProgress(xs:string deviceSerialNums, xs:string packagePath, xs:boolean bGroup, )
      GetVersion()
      ImportConfigs(xs:string deviceSerialNums, xs:string configContent, )
      SetDeviceInfo(xs:string deviceSerialNum, xs:string newDeviceInfo, xs:boolean bGroup, )
      SetDeviceNetInfo(xs:string deviceSerialNums, xs:string netInfo, xs:boolean bGroup, )
      SetHSCConfigItem(xs:string deviceSerialNums, xs:string softServiceName, xs:string configName, xs:string newValues, )
      UpgradeSoftware(xs:string deviceSerialNums, xs:string packagePath, xs:boolean bGroup, )
    

    将整个client 工程分为两部分,第一部分用于构造 soap报文与整个post请求;第二部分使用 httplib 收发构造的请求与WebService的返回

    第一部分: envelope.py
    <code>
    # -- coding: utf-8 --
    # @Author: riposa
    # @Date: 2016-07-15 11:12:15
    # @Last Modified by: riposa
    # @Last Modified time: 2016-07-15 17:58:46
    '''
    module for constructing soap request and resolve soap post
    '''

    import xml.etree.cElementTree as ET
    import json
    
    
    class SoapEnvelopeTree(object):
        '''
            Soap Envelope Tree parser
        '''
    
        def __init__(self, envString):
    
            if not envString:
                # construct new envelope xml tree
                root = ET.Element('soapenv:Envelope')
                root.set('xmlns:soapenv', 'http://schemas.xmlsoap.org/soap/envelope/')
                ET.SubElement(root, 'soapenv:Body')
                self.root = root
                self.tree = ET.ElementTree(root)
    
            else:
                self.root = ET.fromstring(envString)
    
        def set_sub_element(self, father, tag, text=None, attrib=None):
            '''
                add sub element to the specific father tag
            '''
    
            father_el = [ i for i in self.root.iter(father)][0]
            if type(father_el) == None:
                return ('error', 'can not find the node')
            child = ET.SubElement(father_el, tag)
            if text:
                child.text = text
            if attrib:
                for i in attrib.keys():
                    child.set(i, attrib[i])
    
            return 0
    
        def get_post_content(self):
            '''
                get the soap post content(json) by resolving xml string
            '''
    
            try:
                err_el = [ i for i in self.root.iter('SOAP-ENV:Fault')][0]
                return ('error', err_el.find('faultstring').text)
            except IndexError:
                a = [j for j in self.root.iter('result')][0]
                try:
                    return ('success', json.loads(a.text))
                except ValueError:
                    return ('success', a.text)
    
    
    def soap_request(url, method, param=None):
        with open('header.conf') as head_file:
            head = json.loads(head_file.read().replace(r'%url%', url))
    
        env_tree = SoapEnvelopeTree(None)
        env_tree.set_sub_element('soapenv:Body', 'ns1:%s' % method, None,
                                {"xmlns:ns1":"http://tempuri.org/vtns.xsd"})
        if param:
            for i in param.keys():
                env_tree.set_sub_element('ns1:%s' % method, i, param[i], None)
        
        data = '<?xml version="1.0" encoding="UTF-8"?>' + ET.tostring(env_tree.root, encoding='utf-8')
    
        return (head, data)
    
    
    def resolve_post(response):
        env_tree_post = SoapEnvelopeTree(response)
        (status, content) = env_tree_post.get_post_content()
    
        return content
    

    </code>

    第二部分: soap_client.py

    <code>
    # -- coding: utf-8 --
    # @Author: riposa
    # @Date: 2016-07-15 14:48:29
    # @Last Modified by: riposa
    # @Last Modified time: 2016-07-15 17:02:12
    '''module for send and recv soap message'''

    import httplib
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    
    from envelope import soap_request, resolve_post
    
    def call(url, port, method, param=None):
        (head, data) = soap_request(url, method, param)
    
        http_client = httplib.HTTPConnection(url, port, timeout=5)
        http_client.request('POST', '/', data, head)
        try:
            response = http_client.getresponse()
        except httplib.BadStatusLine:
            print 'illegal params cause no response'
        result = resolve_post(response.read())
        http_client.close()
    
        return result
    

    </code>

    调用方式:
    soap_client.call(目标IP, 目标端口, 方法名, 参数(Optional))

    基于项目约定, webservice返回值一律为 json, 因此 call() 返回值为解析后的soap content,类型为 dict(python)

    相关文章

      网友评论

          本文标题:使用构造的soap报文与Webservice通信

          本文链接:https://www.haomeiwen.com/subject/rnuqkxtx.html