Проблема хронического тайм-аута с API Google через Python? - PullRequest
0 голосов
/ 26 октября 2018

Я работаю над небольшим веб-приложением, которое поможет мне управлять своей электронной почтой. Я настроил его через API Google с помощью следующей функции, используя токен OAuth, полученный через django-allauth.

import google.oauth2.credentials
from .choices import GMAIL
from allauth.socialaccount.models import SocialToken, SocialAccount
from apiclient.discovery import build


def get_credentials(user):
    account = SocialAccount.objects.get(user=user.id)
    token = SocialToken.objects.get(app=GMAIL, account=account).token
    credentials = google.oauth2.credentials.Credentials(token)
    service = build('gmail', 'v1', credentials=credentials)
    return service

Иногда кажется, что это работает, но, к сожалению, это не очень надежно. Он часто отключается при работе функции build(), но выполняется только примерно треть времени. Мне интересно, что может вызвать такое поведение и есть ли более надежный способ доступа к API?

Я нашел следующий AuthorizedSession класс из этих документов :

from google.auth.transport.requests import AuthorizedSession

authed_session = AuthorizedSession(credentials)

response = authed_session.request(
    'GET', 'https://www.googleapis.com/storage/v1/b')

Но я не знаю, как превратить его в объект, который работает с API Google:

def get_labels(user):
    service = get_credentials(user)
    results = service.users().labels().list(userId='me').execute()
    labels = results.get('labels', [])
    return labels

К сожалению, Документы Google рекомендуют использовать устаревший пакет, который я надеялся избежать.

Это мой первый опыт использования API с поддержкой OAuth. У кого-нибудь есть совет?

РЕДАКТИРОВАТЬ: я опубликовал после попытки с моего MacBook. Я также попробовал это сделать на своей машине с Windows, где она работает более согласованно, но каждый раз для выполнения build() требуется около 20 секунд. Я чувствую, что делаю что-то не так.

1 Ответ

0 голосов
/ 27 октября 2018

Это работает намного лучше этим утром после того, как я наконец добавил токен обновления в смесь.Возможно, его отсутствие вызывало некоторые проблемы на другом конце.Я продолжу тестирование, но сейчас все работает хорошо:

Вот мое полное решение:

import google.oauth2.credentials
from google.auth.transport.requests import Request

from apiclient import errors, discovery

from myproject.settings import GMAIL_CLIENT_API_KEY, GMAIL_CLIENT_API_SECRET


def get_credentials(user):
    token_set = user.socialaccount_set.first().socialtoken_set.first()
    token = token_set.token
    refresh_token = token_set.token_secret
    credentials = google.oauth2.credentials.Credentials(
        token,
        refresh_token=refresh_token,
        client_id=GMAIL_CLIENT_API_KEY,
        client_secret=GMAIL_CLIENT_API_SECRET,
        token_uri= google.oauth2.credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT,
    )

    if credentials.expired:
        request = Request()
        credentials.refresh(request)

    service = discovery.build('gmail', 'v1', credentials=credentials)
    return service

Как видите, я добавил свои ключи API в файл настроек иссылался на них здесь.Я случайно наткнулся на token_uri, когда носился вокруг в исходных файлах вчера.refresh_token был предметом, который потребовалось больше всего, чтобы найти.

Хорошей новостью является то, что django-allauth сохранит маркер обновления в модель SocialToken в столбце token_secret.Тем не менее, он будет делать это только в том случае, если в ваших настройках указано следующее:

SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
            'https://www.googleapis.com/auth/gmail.labels',
            'https://www.googleapis.com/auth/gmail.modify'
        ],
        'AUTH_PARAMS': {
            'access_type': 'offline',
        }
    }
}

В частности, access_type in AUTH_PARAMS должно быть установлено на 'offline' в соответствии с документами .

Теперь, это все еще будет создавать проблемы, если вы подключили свою учетную запись до того, как внедрили это изменение, поэтому вам также придется отозвать доступ к вашему приложению через разрешения Google , чтобы получитьновый токен обновления.Подробнее об этом можно узнать в этом вопросе .

Я не уверен, является ли это правильным / предполагаемым способом сделать это, но пока Google не обновит свои документы для Django, этот подходдолжен работать по крайней мере для целей тестирования.

...