Projet

Général

Profil

0001-iparapheur-add-handling-of-invalid-response-content.patch

Josué Kouka, 25 septembre 2016 13:18

Télécharger (7,15 ko)

Voir les différences:

Subject: [PATCH] iparapheur: add handling of invalid response content

 passerelle/contrib/iparapheur/models.py | 49 +++++++++++++++++++++++----------
 passerelle/contrib/iparapheur/soap.py   | 12 ++++++--
 tests/test_iparapheur.py                | 21 ++++++++++++++
 3 files changed, 65 insertions(+), 17 deletions(-)
passerelle/contrib/iparapheur/models.py
16 16
import base64
17 17
import json
18 18
import magic
19
from xml.sax._exceptions import SAXParseException
19 20

  
20 21
from django.db import models
21 22

  
......
28 29
from passerelle.utils.api import endpoint
29 30

  
30 31
from .soap import get_client
32
from suds import WebFault
33

  
31 34

  
32 35
def format_type(t):
33 36
    return {'id': unicode(t), 'text': unicode(t)}
......
40 43
    pass
41 44

  
42 45

  
43
class FileNotFoundError(Exception):
46
class FiteNotFoundError(Exception):
44 47
    http_status = 404
45 48

  
46 49

  
50
class InvalidResponseContent(Exception):
51
    http_status = 200
52
    log_error = False
53

  
54

  
55
class ServiceError(Exception):
56
    http_status = 200
57
    log_error = False
58

  
59

  
47 60
class IParapheur(BaseResource):
48 61
    wsdl_url = models.CharField(max_length=128, blank=False,
49 62
            verbose_name=_('WSDL URL'),
......
71 84
    def get_verbose_name(cls):
72 85
        return cls._meta.verbose_name
73 86

  
87
    def call(self, service, *args, **kwargs):
88
        client = get_client(self)
89
        try:
90
            result = getattr(client.service, service)(*args, **kwargs)
91
        except(WebFault,) as e:
92
            raise ServiceError()
93
        except(Exception,) as e:
94
            if not(e.args) or not isinstance(e.args[0], tuple):
95
                raise e
96
            raise InvalidResponseContent('Invalid Response Content, XML expected')
97
        return result
98

  
74 99
    @endpoint(serializer_type='json-api')
75 100
    def types(self, request):
76
        c = get_client(self)
77
        return [format_type(t) for t in c.service.GetListeTypes()]
101
        return [format_type(t) for t in self.call('GetListeTypes')]
78 102

  
79 103
    @endpoint(serializer_type='json-api')
80 104
    def ping(self, request):
81
        c = get_client(self)
82
        return c.service.echo('ping')
105
        return self.call('echo', 'ping')
83 106

  
84 107
    @endpoint(serializer_type='json-api')
85 108
    def subtypes(self, request, type=None):
86
        c = get_client(self)
87 109
        if type:
88
            return [format_type(t) for t in c.service.GetListeSousTypes(type)]
89
        return [format_type(t) for t in c.service.GetListeSousTypes()]
110
            return [format_type(t) for t in self.call('GetListeSousTypes', type)]
111
        return [format_type(t) for t in self.call('GetListeSousTypes')]
90 112

  
91 113
    @endpoint(serializer_type='json-api')
92 114
    def files(self, status=None):
93
        c = get_client(self)
94 115
        if status:
95
            return [format_status(f) for f in c.service.RechercherDossiers(Status=status)]
96
        return [format_status(f) for f in c.service.RechercherDossiers()]
116
            return [format_status(f) for f in self.call('RechercherDossiers', Status=status)]
117
        return [format_status(f) for f in self.call('RechercherDossiers')]
97 118

  
98 119
    @endpoint(serializer_type='json-api', name='create-file', methods=['post'])
99 120
    def create_file(self, request, email=None):
......
131 152

  
132 153
    @endpoint(serializer_type='json-api', name='get-file', pattern='(?P<file_id>[\w-]+)')
133 154
    def get_file(self, request, file_id):
134
        client = get_client(self)
135
        resp = client.service.GetDossier(file_id)
155
        resp = self.call('GetDossier', file_id)
136 156
        if resp.MessageRetour.codeRetour == 'KO':
137 157
            if 'inconnu' in resp.MessageRetour.message:
138 158
                raise Http404(resp.MessageRetour.message)
......
144 164

  
145 165
    @endpoint(serializer_type='json-api', name='get-file-status', pattern='(?P<file_id>[\w-]+)')
146 166
    def get_file_status(self, request, file_id):
147
        c = get_client(self)
148
        resp = c.service.GetHistoDossier(file_id)
167
        resp = self.call('GetHistoDossier', file_id)
149 168
        if resp.MessageRetour.codeRetour == 'KO':
150 169
            if 'inconnu' in resp.MessageRetour.message:
151 170
                raise Http404(resp.MessageRetour.message)
passerelle/contrib/iparapheur/soap.py
23 23

  
24 24
from suds.client import Client
25 25
from suds.transport.http import HttpAuthenticated
26
from suds.transport import Reply
26
from suds.transport import Reply, TransportError
27 27
from suds.plugin import MessagePlugin, DocumentPlugin
28 28

  
29 29
from suds.sudsobject import asdict
......
75 75
        self.addcredentials(request)
76 76
        resp = self.model.requests.post(request.url, data=request.message,
77 77
                headers=request.headers, **self.get_requests_kwargs())
78
        return Reply(resp.status_code, resp.headers, resp.content)
78

  
79
        if resp.status_code in (202, 204):
80
            return None
81
        elif not resp.ok:
82
            raise TransportError(
83
                resp.reason,
84
                resp.status_code, fp=StringIO.StringIO(resp.content))
85
        else:
86
            return Reply(resp.status_code, resp.headers, resp.content)
79 87

  
80 88
def get_client(instance):
81 89
    transport = Transport(instance)
tests/test_iparapheur.py
154 154
    file_sent = os.path.join(os.path.dirname(__file__), 'data/iparapheur_test.pdf')
155 155
    assert resp.headers['Content-Type'] == 'application/pdf'
156 156
    assert hashlib.md5(resp.body[:8192]).hexdigest() == hashlib.md5(file(file_sent).read()[:8192]).hexdigest()
157

  
158

  
159
@mock.patch('passerelle.utils.LoggedRequest.get')
160
@mock.patch('passerelle.utils.LoggedRequest.post')
161
@mock.patch('passerelle.contrib.iparapheur.soap.HttpAuthenticated.open')
162
def test_invalid_response(http_open, mocked_post, mocked_get, setup, xmlmime, wsdl_file):
163
    app, conn = setup
164
    file_id = str(uuid.uuid4())
165

  
166
    http_open.return_value = file(xmlmime)
167
    mocked_get.return_value = mock.Mock(content = file(wsdl_file).read(),
168
                                            status_code=200)
169
    mocked_post.return_value = mock.Mock(status_code=502,
170
            content='<p>Bad Gateway</p>', reason='Bad Gateway', ok=False)
171
    url = reverse('generic-endpoint', kwargs={'slug': conn.slug,
172
                'connector': 'iparapheur', 'endpoint': 'get-file-status',
173
                'rest': file_id})
174
    resp = app.get(url)
175

  
176
    assert 'x-error-code' in dict(resp.headers)
177
    assert resp.json['err_desc'] == 'Invalid Response Content, XML expected'
157
-