text: import json
  
  import requests
  
  from gfypy.const import REDIRECT_URI
  from gfypy.exceptions import GfypyAuthException, GfypyApiException
  from gfypy.http.abstract_http import AbstractHttpClient
  from gfypy.route import Route
  
  
  class BearerAuth(requests.auth.AuthBase):
      def __init__(self, token):
          self.token = token
  
      def __call__(self, r):
          r.headers["authorization"] = "Bearer " + self.token
          return r
  
  
  class SyncHttpClient(AbstractHttpClient):
      def __init__(self, client_id, client_secret):
          self._client_id = client_id
          self._client_secret = client_secret
          self._session = requests.Session()
          self._auth = None
          self.creds = {
              "access_token": None,
              "expires_in": None,
              "refresh_token": None,
              "refresh_token_expires_in": None,
              "resource_owner": None,
          }
  
      def close(self):
          self._session.close()
  
      def request(self, route, **kwargs):
          no_auth = kwargs.pop("no_auth", False)
          refresh = kwargs.pop("refresh", True)
  
          if self._auth is not None and not no_auth:
              resp = self._session.request(
                  route.method, route.url, **kwargs, auth=self._auth
              )
          else:
              resp = self._session.request(route.method, route.url, **kwargs)
  
          content_type = resp.headers.get("content-type")
  
          if content_type == "application/json":
              content = resp.json()
          else:
              content = resp.text
  
          if 200 <= resp.status_code < 300:
              return content
          elif resp.status_code in [401, 403]:
              if refresh:
                  # try to refresh the oauth token in case it's become invalid
                  self.refresh_oauth_token()
  
                  return self.request(route, **kwargs, refresh=False)
              else:
                  if "message" in content:
                      raise GfypyAuthException(content["message"], resp.status_code, None)
                  else:
                      raise GfypyAuthException(
                          content["errorMessage"]["description"],
                          resp.status_code,
                          content["errorMessage"]["code"],
                      )
          else:
              raise GfypyApiException(
                  content["errorMessage"] if "message" in content else content,
                  resp.status_code,
              )
  
      def get_oauth_token(self, code):
          payload = {
              "code": code,
              "client_id": self._client_id,
              "client_secret": self._client_secret,
              "grant_type": "authorization_code",
              "redirect_uri": REDIRECT_URI,
          }
  
          resp = self.request(
              Route("POST", "/oauth/token"),
              data=json.dumps(payload),
              headers={"content-type": "application/json"},
          )
  
          self.creds = resp
          self.auth = resp["access_token"]
  
      def refresh_oauth_token(self, **kwargs):
          payload = {
              "refresh_token": self.creds["refresh_token"],
              "client_id": self._client_id,
              "client_secret": self._client_secret,
              "grant_type": "refresh",
          }
  
          resp = self.request(
              Route("POST", "/oauth/token"),
              data=json.dumps(payload),
              headers={"content-type": "application/json"},
              **kwargs,
          )
  
          self.creds = resp
          self.auth = resp["access_token"]
  
      @property
      def auth(self):
          return self._auth
  
      @auth.setter
      def auth(self, token):
          self._auth = BearerAuth(token)
  