Неделя прошла, можно сказать, не зря. Одним из главных событий неделю для меня стало то, что все-таки заставил себя залезть в мануалы по Delphi, немного подготовиться и пройти тест в Delphi Certification Program. Экзамен сдал, сертификат получил — осталось распечатать в цвете и повесить на стенку =).
В остальном, что касается Delphi — идей по чести Delphi XE2 громадьё, а времени сейчас практически нет. Но, тем не менее, сегодня у меня вынужденный отдых от работы — заболел. И пока болею решил потратить время с пользой — решить некоторый проблемы по части работы с Google OAuth 2.0., которые частично были указаны в комментариях к одному из постов, посвященных этой теме.
Итак, вначале разберемся с тем, что случилось с авторизацией в OAuth. Для того, чтобы разобраться в проблеме я воспользовался демкой к посту «Google API в Delphi. Обновление модуля для OAuth.«. Действительно, токен был успешно получен, но на любой запрос к API возвращалась ошибка с сообщением о том, что авторизация провалена. Проблема крылась, как оказалось, в оформлении запроса, а именно — в заголовках запроса. Все дело в том, что когда я впервые писал про Google OAuth — это было в статье «Google API в Delphi. OAuth для Delphi-приложений.«, то для правильной авторизации в сервисе использовался стандартный заголовок авторизации:
Authorization: OAuth ВАШ_ТОКЕН
и это нормально, правильно и замечательно. Но в Google в какой-то момент решили сделать ещё нормальнее и правильнее (говорю без иронии — см. протокол OAuth 2.0.) и теперь заголовок авторизации для настольных приложений стал выглядеть так:
Соответственно, уже только одно это изменение стало причиной того, что полученный токен не работал. НО это оказалось не единственной проблемой. Теперь для получения доступа к API Google по OAuth надо указывать не один, а два заголовка:
Authorization: Bearer YOUR_ACCESS_TOKEN Host: accounts.google.com
Вот чего я так и не смог понять, так это зачем указывать вручную заголовок Host, который заполняется автоматом перед отправкой запроса на основании URL? То ли это опечатка в документации Google, то ли злая шутка разработчиков — не знаю, но без этого заголовка Host запрос к API проваливается. В общем я решил воспользоваться вторым вариантом авторизации и использовать не заголовки для указания токена, а параметры запроса.
В итоге модуль GoogleOAuth.pas претерпел некоторые изменения, а точнее метод PrepareParams. Теперь он стал таким:
function TOAuth.PrepareParams(Params: TStrings): string; var S: string; begin if Assigned(Params) then begin {вставляем параметр с токеном авторизации} Params.Add('access_token='+FAccess_token); for S in Params do Result := Result + TIdURI.ParamsEncode(S) + '&'; Delete(Result, Length(Result), 1); Result := '?' + Result; Exit; end; Result := ''; end;
После этого запросы к API Google Tasks стали проходить без проблем.
Теперь, что касается работы с API Google Tasks. Ещё до того как Google не запостил в своем блоге информацию про «убийство 18-ти API» я задумывал разработать небольшой модуль для работы с API Задач. Работа, можно сказать, повисла практически в самом начале, но тем не менее, кое-какие моменты для работы с API были реализованы. Тот самый модуль (кому интересно) можно скачать по ссылке в конце поста. В модуле реализован следующий класс:
type TGTaskAPI = class(TComponent) private FOAuthClient: TOAuth; function GetVersion: string; procedure SetOAuthClient(const Value: TOAuth); public constructor Create(AOwner:TComponent);override; destructor Destroy;override; function ListsList(maxResults: string = ''; pageToken: string = ''): string; function ListsGet(const ListID: string): string; function ListsInsert(JSONStream: TStringStream):string; function TasksList(const ListID: string):string;overload; function TasksList(const ListID: string; Params:TStrings):string;overload; function TasksGet(const ListID: string; TaskID:string):string;overload; function TasksGet(const TaskID: string):string;overload; function TasksInsert(const ListID, Parent, Previous: string; JSONStream: TStringStream):string; overload; function TasksInsert(const ListID: string; JSONStream: TStringStream):string; overload; function TasksInsert(const JSONStream: TStringStream):string; overload; function TasksMove(const ListID, TaskID, parentTaskID, previousTaskID:string):string;overload; function TasksMove(const TaskID, parentTaskID, previousTaskID:string):string;overload; function TasksUpdate(const ListID,TaskID:string; JSONStream: TStringStream):string;overload; function TasksUpdate(const TaskID:string; JSONStream: TStringStream):string;overload; function TasksDelete(const ListID,TaskID:string):boolean;overload; function TasksDelete(const TaskID:string):boolean;overload; property Version: string read GetVersion; published property OAuthClient: TOAuth read FOAuthClient write SetOAuthClient; end;
То есть класс TGTaskAPI активно использует тот самый компонент для работы с OAuth 2.0. с проблем которого я и начал эту статью. Как вы можете видеть по описанию класса, методы TGTaskAPI возвращают только строки или boolean-значения. Если метод возвращает строку, то эта строка ни что иное как JSON-объект и для его разбора Вы можете воспользоваться любой удобной для Вас библиотекой, например SuperObject или родными модулями Delphi для работы с JSON — DBXJSON (для Delphi XE), Data.DBXJSON (для Delphi XE2) или System.JSON для более поздних версий.
Что касается примера работы, то, думаю, что по мере наличия времени набросаю пример того, как можно работать с API Google Tasks без использования сторонних библиотек — только Indy и DBXJSON System.JSON. Думаю, что такой пример будет не лишним.
Книжная полка
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
Спасибо большое.
Но не могли бы вы сказать, реально ли сделать работу с Google Tasks через ClientLogin с передачей Auth? Ибо если регать через OAuth, то количество запросов действительно сокращается до 5000 на всех, кто юзает программу, а вот если каждый будет входить через свой gmail, то тут уже количество увеличивается до 5000 на каждого. Поэтому и интересует вопрос по входу через ClientLigin.
Заранее спасибо большое и огромное вам! Действительно порекомендовал данный блог многим своим знакомым Delphiстам, и людям продвигающим сайты. Все как и я очень довольны подобной находкой!
Николай, спасибо за рекомендации. Надеюсь ваши друзья и знакомые не разочаруются =)
Что касается работы с Google Tasks через ClientLogin, то здесь все печально — поддерживается только OAuth 2.0. либо API Key НО БЕЗ доступа к персональным данным клиента, то бишь — толку от API Key -ноль целых ноль десятых. Собственно вариантов использования API тоже практически ноль с такими-то лимитами. Только если в приложении ставить ограничение, скажем не более 3 синхронизаций с Google…но это как-то не серьёзно
[…] деле экзамен я уже давно сдал и получил сертификат, о чем упоминал в одной из статей в блоге, но это письмо заставило […]
Доброго времени суток. Спасибо за хороший материал! Но одно место никак не могу понять… Создал я проект, получил все необходимые данные. все хорошо, но… Ведь я же буду ограничен только своим аккаунтом. А хотелка звучит так, как получить содержимое произвольного аккаунтв ютуб, зная его логин и пароль. Подскажите плиз направление куда копать… Заранее спасибо!
Здравствуйте. На сколько я помню, можно просто получить множество OAuth-токенов к любому количеству аккуантов и их использовать. Чтобы каждый раз в браузере не попадать на страницу с регистрационными данными одного аккаунта — достаточно подчищать куки и вы будете каждый раз вводить новый логин и пароль. То есть алгоритм работы примерно такой:
1. Перенаправляем пользователя на страничку логина
2. Логинимся и получаем токен
3. Сохраняем токен, закрываем браузер, чистим куки
4. Работаем с токеном пока его срок действия не истек
5. Если нужен новый токен — переходим к п.1
Спасибо за ответ! Буду думать… «можно просто получить множество OAuth-токенов к любому количеству аккуантов и их использовать» вот тут-то и зарыта собака… мне заране в принципе не ищвестны какие аккаунты потребуются…
Так, пользователь-то свои аккаунты же знает? Захотел YouTube — авторизовался, вы запомнили токен, захотел Твиттер — авторизовался и вы опять запомнили токен. Ничего сверхъестественного нету :)