diff --git a/fitbit/api.py b/fitbit/api.py index 6498f7a..ad27245 100644 --- a/fitbit/api.py +++ b/fitbit/api.py @@ -19,6 +19,7 @@ HTTPTooManyRequests) from fitbit.utils import curry +TIMEOUT_SECONDS = 27.0 class FitbitOauthClient(object): API_ENDPOINT = "https://api.fitbit.com" @@ -64,7 +65,7 @@ def _request(self, method, url, **kwargs): """ A simple wrapper around requests. """ - return self.session.request(method, url, **kwargs) + return self.session.request(method, url, timeout=TIMEOUT_SECONDS, **kwargs) def make_request(self, url, data={}, method=None, **kwargs): """ @@ -169,6 +170,9 @@ def __init__(self, client_id , client_secret, self.session = requests.Session() self.client_id = client_id self.client_secret = client_secret + dec_str = ":".join([client_id, client_secret]) + enc_str = base64.b64encode(dec_str.encode("utf-8")) + self.auth_header = {"Authorization": b'Basic ' + enc_str} self.token = {'access_token' : access_token, 'refresh_token': refresh_token} self.oauth = OAuth2Session(client_id) @@ -177,7 +181,7 @@ def _request(self, method, url, **kwargs): """ A simple wrapper around requests. """ - return self.session.request(method, url, **kwargs) + return self.session.request(method, url, timeout=TIMEOUT_SECONDS, **kwargs) def make_request(self, url, data={}, method=None, **kwargs): """ @@ -188,28 +192,8 @@ def make_request(self, url, data={}, method=None, **kwargs): if not method: method = 'POST' if data else 'GET' - try: - auth = OAuth2(client_id=self.client_id, token=self.token) - response = self._request(method, url, data=data, auth=auth, **kwargs) - except TokenExpiredError as e: - self.refresh_token() - auth = OAuth2(client_id=self.client_id, token=self.token) - response = self._request(method, url, data=data, auth=auth, **kwargs) - - #yet another token expiration check - #(the above try/except only applies if the expired token was obtained - #using the current instance of the class this is a a general case) - if response.status_code == 401: - d = json.loads(response.content.decode('utf8')) - try: - if(d['errors'][0]['errorType']=='oauth' and - d['errors'][0]['fieldName']=='access_token' and - d['errors'][0]['message'].find('Access token invalid or expired:')==0): - self.refresh_token() - auth = OAuth2(client_id=self.client_id, token=self.token) - response = self._request(method, url, data=data, auth=auth, **kwargs) - except: - pass + auth = OAuth2(client_id=self.client_id, token=self.token) + response = self._request(method, url, data=data, auth=auth, **kwargs) if response.status_code == 401: raise HTTPUnauthorized(response) @@ -269,8 +253,7 @@ def fetch_access_token(self, code, redirect_uri): auth = OAuth2Session(self.client_id, redirect_uri=redirect_uri) self.token = auth.fetch_token( self.access_token_url, - username=self.client_id, - password=self.client_secret, + headers=self.auth_header, code=code) return self.token @@ -281,15 +264,19 @@ def refresh_token(self): the token is internally saved """ - unenc_str = (self.client_id + ':' + self.client_secret).encode('utf8') - headers = { - 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', - 'Authorization': b'Basic ' + base64.b64encode(unenc_str) - } - self.token = self.oauth.refresh_token( - self.refresh_token_url, - refresh_token=self.token['refresh_token'], - headers=headers) + try: + self.token = self.oauth.refresh_token( + self.refresh_token_url, + refresh_token=self.token['refresh_token'], + auth=(self.client_id, self.client_secret), + timeout=TIMEOUT_SECONDS) + except requests.Timeout: + self.token = self.oauth.refresh_token( + self.refresh_token_url, + refresh_token=self.token['refresh_token'], + auth=(self.client_id, self.client_secret), + timeout=TIMEOUT_SECONDS) + return self.token