Projet

Général

Profil

0002-misc-allow-fixing-prefix-characters-in-SOAP-response.patch

Benjamin Dauvergne, 29 janvier 2021 19:45

Télécharger (4,57 ko)

Voir les différences:

Subject: [PATCH 2/3] misc: allow fixing prefix characters in SOAP responses
 (#50260)

 passerelle/utils/soap.py | 37 +++++++++++++++++++++++++++++++++++--
 tests/test_soap.py       | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 66 insertions(+), 3 deletions(-)
passerelle/utils/soap.py
36 36
    """
37 37
    def __init__(self, resource, **kwargs):
38 38
        wsdl_url = kwargs.pop('wsdl_url', None) or resource.wsdl_url
39
        transport_kwargs = kwargs.pop('transport_kwargs', {})
39 40
        transport_class = getattr(resource, 'soap_transport_class', SOAPTransport)
40
        transport = transport_class(resource, wsdl_url, session=resource.requests, cache=InMemoryCache())
41
        transport = transport_class(resource, wsdl_url,
42
                                    session=resource.requests,
43
                                    cache=InMemoryCache(), **transport_kwargs)
41 44
        super(SOAPClient, self).__init__(wsdl_url, transport=transport, **kwargs)
42 45

  
43 46

  
47
class ResponseFixContentWrapper:
48
    def __init__(self, response):
49
        self.response = response
50

  
51
    def __getattr__(self, name):
52
        return getattr(self.response, name)
53

  
54
    @property
55
    def content(self):
56
        content = self.response.content
57
        if 'multipart/related' not in self.response.headers.get('Content-Type', ''):
58
            try:
59
                first_left_than_sign = content.index(b'<')
60
                content = content[first_left_than_sign:]
61
            except ValueError:
62
                pass
63
        return content
64

  
65

  
44 66
class SOAPTransport(Transport):
45 67
    """Wrapper around zeep.Transport
46 68

  
47 69
    disable basic_authentication hosts unrelated to wsdl's endpoints
48 70
    """
49
    def __init__(self, resource, wsdl_url, **kwargs):
71
    def __init__(self, resource, wsdl_url, remove_first_bytes_for_xml=False, **kwargs):
50 72
        self.resource = resource
51 73
        self.wsdl_host = urlparse.urlparse(wsdl_url).netloc
74
        # fix content for servers returning unexpected characters before XML document start
75
        self.remove_first_bytes_for_xml = remove_first_bytes_for_xml
52 76
        super(SOAPTransport, self).__init__(**kwargs)
53 77

  
54 78
    def _load_remote_data(self, url):
......
60 84
            return super(SOAPTransport, self)._load_remote_data(url)
61 85
        except RequestException as e:
62 86
            raise SOAPError('SOAP service is down, location %r cannot be loaded: %s' % (url, e), exception=e, url=url)
87

  
88
    def post_xml(self, *args, **kwargs):
89
        response = super().post_xml(*args, **kwargs)
90

  
91
        if self.remove_first_bytes_for_xml:
92
            return ResponseFixContentWrapper(response)
93

  
94
        return response
95

  
tests/test_soap.py
19 19
import requests
20 20
from zeep import Settings
21 21
from zeep.plugins import Plugin
22
from zeep.exceptions import XMLParseError
22
from zeep.exceptions import XMLParseError, TransportError
23 23

  
24 24
from passerelle.utils.soap import SOAPClient
25 25

  
......
78 78
    assert len(result) == 2
79 79
    assert result['skipMe'] is None
80 80
    assert result['price'] == 4.2
81

  
82

  
83
@mock.patch('requests.sessions.Session.post')
84
def test_remove_first_bytes_for_xml(mocked_post):
85
    response = requests.Response()
86
    response.status_code = 200
87
    response._content = force_bytes('''blabla <?xml version='1.0' encoding='utf-8'?>
88
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
89
  <soap-env:Body>
90
    <ns0:TradePrice xmlns:ns0="http://example.com/stockquote.xsd">
91
      <skipMe>1.2</skipMe>
92
      <price>4.20</price>
93
    </ns0:TradePrice>
94
  </soap-env:Body>
95
</soap-env:Envelope>''')
96
    mocked_post.return_value = response
97

  
98
    soap_resource = SOAPResource()
99

  
100
    client = SOAPClient(soap_resource)
101
    with pytest.raises(TransportError):
102
        client.service.GetLastTradePrice(tickerSymbol='banana')
103

  
104
    client = SOAPClient(soap_resource,
105
                        transport_kwargs={'remove_first_bytes_for_xml': True})
106
    result = client.service.GetLastTradePrice(tickerSymbol='banana')
107
    assert len(result) == 2
108
    assert result['skipMe'] == 1.2
109
    assert result['price'] == 4.2
110

  
81
-