0001-iparapheur-add-handling-of-invalid-response-content.patch
passerelle/contrib/iparapheur/models.py | ||
---|---|---|
28 | 28 |
from passerelle.utils.api import endpoint |
29 | 29 | |
30 | 30 |
from .soap import get_client |
31 |
from suds import WebFault |
|
32 | ||
31 | 33 | |
32 | 34 |
def format_type(t): |
33 | 35 |
return {'id': unicode(t), 'text': unicode(t)} |
... | ... | |
44 | 46 |
http_status = 404 |
45 | 47 | |
46 | 48 | |
49 |
class InvalidResponseContent(Exception): |
|
50 |
http_status = 200 |
|
51 |
log_error = False |
|
52 | ||
53 | ||
54 |
class ServiceError(Exception): |
|
55 |
http_status = 200 |
|
56 |
log_error = False |
|
57 | ||
58 | ||
47 | 59 |
class IParapheur(BaseResource): |
48 | 60 |
wsdl_url = models.CharField(max_length=128, blank=False, |
49 | 61 |
verbose_name=_('WSDL URL'), |
... | ... | |
71 | 83 |
def get_verbose_name(cls): |
72 | 84 |
return cls._meta.verbose_name |
73 | 85 | |
86 |
def call(self, service, *args, **kwargs): |
|
87 |
client = get_client(self) |
|
88 |
try: |
|
89 |
result = getattr(client.service, service)(*args, **kwargs) |
|
90 |
except(WebFault,) as e: |
|
91 |
# Remote Service Error: <SOAP-ENV:Fault> in response |
|
92 |
raise ServiceError(e.args[0]) |
|
93 |
except(Exception,) as e: |
|
94 |
# Exception different from suds.tranport.TransportError |
|
95 |
if not(e.args) or not isinstance(e.args[0], tuple): |
|
96 |
raise e |
|
97 |
# TransportError Exception |
|
98 |
raise InvalidResponseContent(e.args[0]) |
|
99 |
return result |
|
100 | ||
74 | 101 |
@endpoint(serializer_type='json-api') |
75 | 102 |
def types(self, request): |
76 |
c = get_client(self) |
|
77 |
return [format_type(t) for t in c.service.GetListeTypes()] |
|
103 |
return [format_type(t) for t in self.call('GetListeTypes')] |
|
78 | 104 | |
79 | 105 |
@endpoint(serializer_type='json-api') |
80 | 106 |
def ping(self, request): |
81 |
c = get_client(self) |
|
82 |
return c.service.echo('ping') |
|
107 |
return self.call('echo', 'ping') |
|
83 | 108 | |
84 | 109 |
@endpoint(serializer_type='json-api') |
85 | 110 |
def subtypes(self, request, type=None): |
86 |
c = get_client(self) |
|
87 | 111 |
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()]
|
|
112 |
return [format_type(t) for t in self.call('GetListeSousTypes', type)]
|
|
113 |
return [format_type(t) for t in self.call('GetListeSousTypes')]
|
|
90 | 114 | |
91 | 115 |
@endpoint(serializer_type='json-api') |
92 | 116 |
def files(self, status=None): |
93 |
c = get_client(self) |
|
94 | 117 |
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()]
|
|
118 |
return [format_status(f) for f in self.call('RechercherDossiers', Status=status)]
|
|
119 |
return [format_status(f) for f in self.call('RechercherDossiers')]
|
|
97 | 120 | |
98 | 121 |
@endpoint(serializer_type='json-api', name='create-file', methods=['post']) |
99 | 122 |
def create_file(self, request, email=None): |
... | ... | |
131 | 154 | |
132 | 155 |
@endpoint(serializer_type='json-api', name='get-file', pattern='(?P<file_id>[\w-]+)') |
133 | 156 |
def get_file(self, request, file_id): |
134 |
client = get_client(self) |
|
135 |
resp = client.service.GetDossier(file_id) |
|
157 |
resp = self.call('GetDossier', file_id) |
|
136 | 158 |
if resp.MessageRetour.codeRetour == 'KO': |
137 | 159 |
if 'inconnu' in resp.MessageRetour.message: |
138 | 160 |
raise Http404(resp.MessageRetour.message) |
... | ... | |
144 | 166 | |
145 | 167 |
@endpoint(serializer_type='json-api', name='get-file-status', pattern='(?P<file_id>[\w-]+)') |
146 | 168 |
def get_file_status(self, request, file_id): |
147 |
c = get_client(self) |
|
148 |
resp = c.service.GetHistoDossier(file_id) |
|
169 |
resp = self.call('GetHistoDossier', file_id) |
|
149 | 170 |
if resp.MessageRetour.codeRetour == 'KO': |
150 | 171 |
if 'inconnu' in resp.MessageRetour.message: |
151 | 172 |
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 |
from suds.sudsobject import asdict
|
|
29 |
from requests.execptions import RequestException
|
|
30 | 30 | |
31 | 31 | |
32 | 32 |
class Filter(MessagePlugin): |
... | ... | |
73 | 73 |
def send(self, request): |
74 | 74 |
request.message = request.message.replace("contentType", "xm:contentType") |
75 | 75 |
self.addcredentials(request) |
76 |
resp = self.model.requests.post(request.url, data=request.message, |
|
76 |
try: |
|
77 |
resp = self.model.requests.post(request.url, data=request.message, |
|
77 | 78 |
headers=request.headers, **self.get_requests_kwargs()) |
78 |
return Reply(resp.status_code, resp.headers, resp.content) |
|
79 |
except(RequestException,) as e: |
|
80 |
raise TransportError(e.message.message, None) |
|
81 | ||
82 |
if resp.status_code in (202, 204): |
|
83 |
return None |
|
84 |
elif not resp.ok: |
|
85 |
raise TransportError( |
|
86 |
resp.reason, |
|
87 |
resp.status_code, fp=StringIO.StringIO(resp.content)) |
|
88 |
else: |
|
89 |
return Reply(resp.status_code, resp.headers, resp.content) |
|
79 | 90 | |
80 | 91 |
def get_client(instance): |
81 | 92 |
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 |
- |