суббота, 18 апреля 2015 г.

Как обоблачиться с YandexDisk - 2.5 Протокольные компоненты, часть 1. TidHTTP и JSON

§2.5. Протокольные компоненты

часть 1. TidHTTP и JSON


Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet

Чтобы работать с REST API у нас имеется множество специальных компонентов. Но в принципе достаточно иметь и не специальные, лишь бы по http(s) отправить параметры и получить текст в виде JSON, парсить который ещё проще, чем XML - у нас для этого есть прекрасный модуль (начиная с XE6) System.JSON с его TJSONObject, TJSONValue и TJSONArray. Так что же выбрать? Будем мы сосать молочко из сосочки или станем глотать молоко прямо из пакета? А если пить из пакета через трубочку? 


Давайте попробуем для начала  через компоненты HTTP запросить у Яндекс-Диска количество элементов в папке. Дело в том, что ЯД по-умолчанию выдаёт список содержания пачками по 20 штук. Разумеется, мы можем попросить выдать нам не 20, а какое-то другое количество элементов. Например - всё сразу. Но, поскольку ЯД не понимает (или я не знаю как дать ему понять), что такое "всё сразу", ему нужно сказать сколько это будет конкретно. И хорошо бы действительно знать это число, а не заказывать в параметре limit наобум 100-500 элементов.

function TForm2.GetFolderCount(const AFolder: String): Integer;
var
  LAnswer : String;
begin
  Result := 0;
  //
  with TIdHTTP.Create do
  try
    {$ifdef MSWindows}
    with ProxyParams do begin
      ProxyPort := 8888;
      ProxyServer := '127.0.0.1';
    end;
    {$endif}
    Request.CustomHeaders.AddValue( 
      'Authorization', FAuthorization );
    LAnswer := Get(
      'https://cloud-api.yandex.net/v1/disk/resources?limit=0&path='
      + HTTPEncode( AFolder ) );
    if ResponseCode <> 200 then
      Exit;
  finally  Free
  end;
  //
  with TJSONObject.ParseJSONValue( LAnswer ) as TJSONObject do
  try
    Result := ((
      GetValue( '_embedded' ) as TJSONObject ).
      GetValue( 'total' ) as TJSONNumber ).AsInt;
  finally Free;
  end;
end;
...
// calling of GetFolderCount
const
  LFolder = 'app:/';
begin
  ShowMessage( Format( '%d record(s) in folder %s', 
    [GetFolderCount( LFolder ), LFolder] ) );
...

Рассмотрим некоторые особенности кода, приведённого выше. Он делится на две части. Первая - получение информации от ЯД, вторая - обработка полученного результата. Какие замечания можно сделать по первой части?

Поскольку TIdHTTP мы создаём вручную, а не ищем его в палитре компонентов, то не забываем добавить в uses модуль IdHTTP. Если кто не знает (ну вдруг!), то можно найти компонент в палитре, кинуть на форму, всё сохранить, и удалить его - в uses будет уже всё добавлено. Работу с прокси-сервером мы как раз обсуждали чуть ранее. Думаю, очевидно, что в FAuthorization хранится наш OAuth-токенА вот что касается HTTPEncode, то для неё следует подключить модуль Web.HTTPApp. Надеюсь, вы заметили, что делая запрос мы указали в параметрах limit=0, чтобы не получать неинтересующий нас на данный момент список файлов внутри папки, а только информацию о ней самой. 

Результат запроса выглядит примерно так:


Выделенный на рисунке элемент Items - это массив записей содержимого папки. Естественно, сейчас он пуст. Итак, пора перейти ко второй части кода, где мы вытаскиваем из JSON количество файлов в папке.

Парсинг выглядит довольно просто. Однако, надо понимать следующее: память под объекты выделяется один раз - классовой функцией ParseJSONValue. Метод GetValue возвращает только ссылку на элемент в коллекции. И второе: хотя ввиду неизменности интерфейса ЯД проверять успешность получения элементов структуры особой нужды нет, в общем случае не грех завести переменную для проверки наличия результата GetValue. Имейте в виду особый порядок обработки аппаратных исключений на мобильных платформах.

to be continued...

Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet

четверг, 9 апреля 2015 г.

Как обоблачиться с YandexDisk - 2.4 Скрипач как прокси

§2.4. Скрипач как прокси


Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet

Совсем не секрет, что путь к успеху часто усеян розами без лепестков, но с шипами. Поэтому не стоит сильно удивляться, что даже установив библиотекинеобходимые Indy для работы по https, вы не сможете сделать запрос не только из среды разработки, но и даже из своей запущенной из-под Windows (отладочной версии) программы.

В чём может быть проблема, если в свойствах компонентов или, например, в поле URL вызванного из RAD отладчика Tools/REST Debugger указан адрес сервера, а попытка выполнить запрос заканчивается ошибкой? Вполне возможно, дело в том, что для выхода в Интернет требуется прокси-сервер. Посмотрите настройки подключения вашего браузера. Скорее всего такие же буквы или цифры нужно указывать и в соответствующих свойствах отладчика или компонентов.


Как правило, указание прокси-сервера требуется в условиях работы в офисе. А если работа идёт в домашних условиях, то указание прокси уже строго не приветствуется. Да и бывает, что офис, в котором поднимается проект, тоже не всегда один и тот же - всю неделю мы, скажем, в филиале в Кожевниках, а на выходные нас пригласили в штаб-квартиру на Таганке. В общем, есть смысл подумать над тем, чтобы иметь некий универсальный подход, не слишком отягощённый необходимостью вникать в местные условия.

Поэтому я всем и каждому советую (© Старуха Шапокляк) везде и всюду качать и ставить такую вещь как Fiddler, что в переводе означает "скрипач". На самом деле это одобренный и рекомендуемый фирмой-производителем ОС бесплатный WEB-отладчик-прокси. Это чудо-средство позволяет просматривать веб-разговоры и даже разговаривать самому. Но в рамках нашей текущей задачи нам достаточно и того, что стоит его запустить, как у вас по адресу 127.0.0.1:8888 установится прокси сервер, который станет смотреть в Паутину либо прямо, либо через тот прокси, который стоит в вашем офисе. Местные условия выхода в Интернет определяются "скрипачом" автоматически. Вам же останется только у себя выставить прокси в 127.0.0.1 с номером порта 88888 и не забыть в программе на старте почистить эти значения, если приложение запускается на мобильном устройстве.

procedure Form1.FormCreate(Sender: TObject);
begin
{$IFNDEF MSWINDOWS}
 RESTClient.ProxyServer := '';
{$ENDIF}
end;

Ну вот - кажется, ещё одной засадой на нашем пути стало меньше.


to be continued...

Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet

среда, 1 апреля 2015 г.

Как обоблачиться с YandexDisk - 2.3 Indy и HTTPS

§2.3. Indy и HTTPS


Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet
Как же нам построить программу для работы с REST API Яндекс Диска? Embarcadero предлагает нам мультиплатформенные Indy-компоненты. Но с маленькой оговоркой - они не содержат SSL-шифрования. Т.е. работа по протоколу https, который необходим ЯД (да и прочим сервисам с авторизацией), может стать несколько более сложной, чем "раз, и поехали". Причины этого нюанса лежат в юридической плоскости. Нам же нужно разобраться со следствием в разрезе работоспособности наших приложений. 

Как же нам получить возможность общения по https? (альтернативные варианты типа Synapse здесь не рассматриваются ввиду ограниченности моего кругозора) Для дооснащения Indy-компонентов полноценной поддержкой SSL фирма Embarcadero рекомендует обратиться к ресурсу OpenSSL.org. Здесь лежат Си-исходники библиотек шифрования и рекомендации по их компиляции. К счастью, на сайте есть ссылки и на библиотеки, уже откомпилированные под разные платформы. Вот взять хотя бы http://indy.fulgan.com/SSL/ - вы тоже заметили там слово "indy"? Я лично как раз поэтому и доверился ей. Там, правда, капчу требуют, но на это не стоит обижаться.


В итоге мы имеем пару DLL - libeay32.dll и ssleay32.dll в openssl-1.0.2a-i386-win32.zip для Win32, пару DLL(удивительно, но имена те же, с цифрами 32) в openssl-1.0.2a-x64_86-win64.zip для Win64 и набор для статической линковки под iOS (судя по дате, его уже давно не обновляли) -  libcrypto.a и libssl.a в OpenSSLStaticLibs.7z. А где же Андроидные бинарники? Видите ли, Андроид предоставляет стандартный доступ к шифрованию SSL, и Indy прекрасно может этим пользоваться безо всяких дополнительных приспособлений.


Что делать с DLL - понятно. Есть вариант А - надёжный: кладём их в каталог с приложением  и для дизайн-тайма в C:\Program Files (x86)\Embarcadero\Studio\версия\bin и bi64. Есть вариант Б, который выглядит гораздо предпочтительнее: выложить DLL в системный каталог - C:\Windows\System32 и C:\Windows\SysWOW64 в соответствии с разрядностью библиотек. Важное замечание по второму варианту: имейте в виду, что скорее всего DLL с такими именами у вас уже есть, но они старых версий, и в них нет всех нужных функций. Indy при этом выдаёт сообщение о том, что не удаётся загрузить библиотеки SSL. Обновите их и не забудьте перезагрузить систему. Если и это не поможет, добро пожаловать в "DLL hell"! 

Для того, чтобы запустить йОсное приложение, файлы libcrypto.a и libssl.a надо подключить к проекту через deployment, а в раздел uses добавить модуль IdSSLOpenSSLHeaders_Static, где содержатся объявления об импорте функций и некоторые прочие заголовочные штуки - непонятные, но нужные.


Теперь мы можем делать запросы по https не только в запущенном на устройстве приложении, но даже в ещё незапущенном, в режиме проектирования, прямо в ObjectInspector! 

Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet