Skip to content

Commit 1399ecb

Browse files
authored
Merge pull request #926 from launchableinc/error-message-capture
Make sure to report server side error message
2 parents 26a9e3c + 0da7d94 commit 1399ecb

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

launchable/commands/subset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ def run(self):
485485

486486
# The status code 422 is returned when validation error of the test mapping file occurs.
487487
if res.status_code == 422:
488-
msg = "Error: {}".format(res.json().get("reason"))
488+
msg = "Error: {}".format(res.reason)
489489
tracking_client.send_error_event(
490490
event_name=Tracking.ErrorEvent.USER_ERROR,
491491
stack_trace=msg,

launchable/utils/http_client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ def request(
104104
"received response status:{} message:{} headers:{}".format(response.status_code, response.reason,
105105
response.headers)
106106
)
107+
108+
# because (I believe, though I could be wrong) HTTP/2 got rid of status message, our server side HTTP stack
109+
# doesn't let us forward the status message (=response.reason), which would have been otherwise a very handy
110+
# mechanism to reliably forward error messages. So instead, we forward JSON error response of the form
111+
# {"reason": ...}. Backfill response.reason with this JSON error message if it exists, so that the exceptions
112+
# thrown from response.raise_for_status() will have a meaningful message.
113+
if response.status_code >= 400 and response.headers.get("Content-Type", "").startswith("application/json"):
114+
try:
115+
response.reason = response.json().get("reason", response.reason)
116+
except json.JSONDecodeError:
117+
pass
118+
107119
return response
108120

109121
def _headers(self, compress):

tests/utils/test_http_client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import platform
33
from unittest import TestCase, mock
44

5+
from requests import Session
6+
57
from launchable.utils.http_client import _HttpClient
68
from launchable.version import __version__
79

@@ -43,3 +45,19 @@ def test_header(self):
4345
"dummy",
4446
),
4547
})
48+
49+
def test_reason(self):
50+
'''make sure we correctly propagate error message from the server'''
51+
52+
# use new session to disable retry
53+
cli = _HttpClient(session=Session())
54+
# /error is an actual endpoint that exists on our service to test the behavior
55+
res = cli.request("GET", "intake/error")
56+
self.assertEqual(res.status_code, 500)
57+
self.assertEqual(res.reason, "Welp")
58+
59+
try:
60+
res.raise_for_status()
61+
self.fail("should have raised")
62+
except Exception as e:
63+
self.assertIn("Welp", str(e))

0 commit comments

Comments
 (0)