-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add timeout to all requests #50
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,9 @@ | |
#: The ID of the application to register with, when using PIN authentication | ||
APPLICATION_ID = None | ||
|
||
#: Timeout in seconds for all requests | ||
TIMEOUT = 30 | ||
|
||
#: Global session to make requests with | ||
session = requests.Session() | ||
|
||
|
@@ -141,7 +144,7 @@ def pin_auth(pin=None, client_id=None, client_secret=None, store=False): | |
'client_id': CLIENT_ID, | ||
'client_secret': CLIENT_SECRET} | ||
|
||
response = session.post(''.join([BASE_URL, '/oauth/token']), data=args) | ||
response = session.post(''.join([BASE_URL, '/oauth/token']), data=args, timeout=TIMEOUT) | ||
OAUTH_TOKEN = response.json().get('access_token', None) | ||
|
||
if store: | ||
|
@@ -231,7 +234,7 @@ def get_device_code(client_id=None, client_secret=None): | |
data = {"client_id": CLIENT_ID} | ||
|
||
device_response = session.post(device_code_url, | ||
json=data, headers=headers).json() | ||
json=data, headers=headers, timeout=TIMEOUT).json() | ||
print('Your user code is: {user_code}, please navigate to ' | ||
'{verification_url} to authenticate'.format( | ||
user_code=device_response.get('user_code'), | ||
|
@@ -272,7 +275,7 @@ def get_device_token(device_code, client_id=None, client_secret=None, | |
} | ||
|
||
response = session.post( | ||
urljoin(BASE_URL, '/oauth/device/token'), json=data | ||
urljoin(BASE_URL, '/oauth/device/token'), json=data, timeout=TIMEOUT | ||
) | ||
|
||
# We only get json on success. | ||
|
@@ -415,7 +418,7 @@ def _refresh_token(s): | |
'redirect_uri': REDIRECT_URI, | ||
'grant_type': 'refresh_token' | ||
} | ||
response = session.post(url, json=data, headers=HEADERS) | ||
response = session.post(url, json=data, headers=HEADERS, timeout=TIMEOUT) | ||
s.logger.debug('RESPONSE [post] (%s): %s - %s', url, str(response), response.content) | ||
if response.status_code == 200: | ||
data = response.json() | ||
|
@@ -542,10 +545,10 @@ def _handle_request(self, method, url, data=None): | |
self.logger.debug('method, url :: %s, %s', method, url) | ||
if method == 'get': # GETs need to pass data as params, not body | ||
response = session.request(method, url, headers=HEADERS, | ||
params=data) | ||
params=data, timeout=TIMEOUT) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance error handling and documentation in _handle_request The timeout parameter has been added, but there are two improvements needed:
Apply these changes to improve error handling and documentation: def _handle_request(self, method, url, data=None):
"""Handle actually talking out to the trakt API, logging out debug
information, raising any relevant `TraktException` Exception types,
and extracting and returning JSON data
:param method: The HTTP method we're executing on. Will be one of
post, put, delete, get
:param url: The fully qualified url to send our request to
:param data: Optional data payload to send to the API
+ :raises TraktTimeout: If the request times out after TIMEOUT seconds
:raises TraktException: If any non-200 return code is encountered
:return: The decoded JSON response from the Trakt API
"""
self.logger.debug('%s: %s', method, url)
HEADERS['trakt-api-key'] = CLIENT_ID
HEADERS['Authorization'] = 'Bearer {0}'.format(OAUTH_TOKEN)
self.logger.debug('method, url :: %s, %s', method, url)
+ try:
if method == 'get': # GETs need to pass data as params, not body
response = session.request(method, url, headers=HEADERS,
params=data, timeout=TIMEOUT)
else:
response = session.request(method, url, headers=HEADERS,
data=json.dumps(data), timeout=TIMEOUT)
+ except requests.exceptions.Timeout:
+ self.logger.error('Request to %s timed out after %s seconds', url, TIMEOUT)
+ raise errors.TraktTimeout(f"Request timed out after {TIMEOUT} seconds") Also, add the new exception class to class TraktTimeout(TraktException):
"""Request timed out"""
http_code = 0 # Not an HTTP error Also applies to: 551-551 |
||
else: | ||
response = session.request(method, url, headers=HEADERS, | ||
data=json.dumps(data)) | ||
data=json.dumps(data), timeout=TIMEOUT) | ||
self.logger.debug('RESPONSE [%s] (%s): %s', method, url, str(response)) | ||
if response.status_code in self.error_map: | ||
raise self.error_map[response.status_code](response) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add timeout exception handling for authentication requests
While adding timeouts is good, the code should explicitly handle
requests.exceptions.Timeout
exceptions for these critical authentication operations. A timeout during authentication should provide clear feedback to the user.Example implementation for the pin_auth function:
Similar error handling should be added to:
Also applies to: 237-237, 278-278, 421-421