Skip to content

Commit cc688ec

Browse files
authored
Update LineBotApiError to get X-Line-Request-Id (#218)
* add X-Line-Request-Id into LineBotApiError * add field for HTTP headers * update __str__ * update test cases * remove debug code * rename class name * add description about header's type * implement LineBotApiError#headers as Dict
1 parent 850aa7a commit cc688ec

File tree

6 files changed

+46
-13
lines changed

6 files changed

+46
-13
lines changed

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ https://developers.line.biz/en/reference/messaging-api/#error-responses
521521
line_bot_api.push_message('to', TextSendMessage(text='Hello World!'))
522522
except linebot.exceptions.LineBotApiError as e:
523523
print(e.status_code)
524+
print(e.request_id)
524525
print(e.error.message)
525526
print(e.error.details)
526527

linebot/api.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,5 +1008,9 @@ def __check_error(response):
10081008
if 200 <= response.status_code < 300:
10091009
pass
10101010
else:
1011-
error = Error.new_from_json_dict(response.json)
1012-
raise LineBotApiError(response.status_code, error)
1011+
raise LineBotApiError(
1012+
status_code=response.status_code,
1013+
headers=dict(response.headers.items()),
1014+
request_id=response.headers.get('X-Line-Request-Id'),
1015+
error=Error.new_from_json_dict(response.json)
1016+
)

linebot/exceptions.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,27 @@ def __init__(self, message='-'):
5858
class LineBotApiError(BaseError):
5959
"""When LINE Messaging API response error, this error will be raised."""
6060

61-
def __init__(self, status_code, error=None):
61+
def __init__(self, status_code, headers, request_id=None, error=None):
6262
"""__init__ method.
6363
64-
:param int status_code: http status code
64+
:param int status_code: HTTP status code
65+
:param headers: Response headers
66+
:type headers: dict[str, str]
67+
:param str request_id: (optional) Request ID. A unique ID is generated for each request
6568
:param error: (optional) Error class object.
6669
:type error: :py:class:`linebot.models.error.Error`
6770
"""
6871
super(LineBotApiError, self).__init__(error.message)
6972

7073
self.status_code = status_code
74+
self.headers = headers
75+
self.request_id = request_id
7176
self.error = error
7277

7378
def __str__(self):
7479
"""str.
7580
7681
:rtype: str
7782
"""
78-
return '{0}: status_code={1}, error_response={2}'.format(
79-
self.__class__.__name__, self.status_code, self.error)
83+
return '{0}: status_code={1}, request_id={2}, error_response={3}, headers={4}'.format(
84+
self.__class__.__name__, self.status_code, self.request_id, self.error, self.headers)

linebot/http_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,10 @@ def status_code(self):
233233

234234
@property
235235
def headers(self):
236-
"""Get headers."""
236+
"""Get headers.
237+
238+
:rtype :py:class:`requests.models.CaseInsensitiveDict`
239+
"""
237240
return self.response.headers
238241

239242
@property

tests/api/test_error_handle.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import unittest
1818

1919
import responses
20+
2021
from linebot import (
2122
LineBotApi
2223
)
@@ -31,6 +32,8 @@
3132
class TestLineBotApi(unittest.TestCase):
3233
def setUp(self):
3334
self.tested = LineBotApi('channel_secret')
35+
self.request_id = 'f70dd685-499a-4231-a441-f24b8d4fba21'
36+
self.headers = {'X-Line-Request-Id': self.request_id, 'HOGE': 'FUGA'}
3437

3538
@responses.activate
3639
def test_error_handle(self):
@@ -40,6 +43,7 @@ def test_error_handle(self):
4043
json={
4144
"message": "Invalid reply token"
4245
},
46+
headers=self.headers,
4347
status=401
4448
)
4549

@@ -48,6 +52,8 @@ def test_error_handle(self):
4852
except LineBotApiError as e:
4953
self.assertEqual(e.status_code, 401)
5054
self.assertEqual(e.error.message, 'Invalid reply token')
55+
self.assertEqual(e.request_id, self.request_id)
56+
self.assertEqual(e.headers['HOGE'], 'FUGA')
5157

5258
@responses.activate
5359
def test_error_with_detail_handle(self):
@@ -69,6 +75,7 @@ def test_error_with_detail_handle(self):
6975
}
7076
]
7177
},
78+
headers=self.headers,
7279
status=400
7380
)
7481

@@ -90,6 +97,8 @@ def test_error_with_detail_handle(self):
9097
"richmessage, template, imagemap]"
9198
)
9299
self.assertEqual(e.error.details[1].property, 'messages[1].type')
100+
self.assertEqual(e.request_id, self.request_id)
101+
self.assertEqual(e.headers['HOGE'], 'FUGA')
93102

94103
@responses.activate
95104
def test_error_handle_get_message_content(self):
@@ -99,6 +108,7 @@ def test_error_handle_get_message_content(self):
99108
json={
100109
"message": "Invalid reply token"
101110
},
111+
headers=self.headers,
102112
status=404
103113
)
104114

@@ -107,6 +117,8 @@ def test_error_handle_get_message_content(self):
107117
except LineBotApiError as e:
108118
self.assertEqual(e.status_code, 404)
109119
self.assertEqual(e.error.message, 'Invalid reply token')
120+
self.assertEqual(e.request_id, self.request_id)
121+
self.assertEqual(e.headers['HOGE'], 'FUGA')
110122

111123

112124
if __name__ == '__main__':

tests/test_exceptions.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,25 @@
2020
from linebot.models import Error, ErrorDetail
2121

2222

23-
class TestUtils(unittest.TestCase):
23+
class TestExceptions(unittest.TestCase):
24+
maxDiff = None
25+
2426
def test_str(self):
27+
headers = {'X-Line-Request-Id': 'f70dd685-499a-4231-a441-f24b8d4fba21'}
2528
line_bot_api_error = LineBotApiError(
26-
400,
29+
status_code=400,
30+
request_id='f70dd685-499a-4231-a441-f24b8d4fba21',
31+
headers=headers,
2732
error=Error(message='The request body has 1 error(s)',
2833
details=[ErrorDetail(message='May not be empty',
2934
property='messages[0].text')]))
30-
self.assertEqual(line_bot_api_error.__str__(),
31-
'LineBotApiError: status_code=400, error_response={"details": '
32-
'[{"message": "May not be empty", "property": "messages[0].text"}], '
33-
'"message": "The request body has 1 error(s)"}')
35+
self.assertEqual(
36+
line_bot_api_error.__str__(),
37+
'LineBotApiError: status_code=400, request_id=f70dd685-499a-4231-a441-f24b8d4fba21, '
38+
'error_response={"details": [{"message": "May not be empty", '
39+
'"property": "messages[0].text"}], "message": "The request body has 1 error(s)"}, '
40+
+ 'headers={}'.format(headers)
41+
)
3442

3543

3644
if __name__ == '__main__':

0 commit comments

Comments
 (0)