Сегодня было немного свободного времени и я решил снова немного поработать с API сервиса “Мегаплан”. В прошлый раз мы остановились на том, что научились правильно авторизовываться в сервисе, получать необходимые ключи (AccessId и SecretKey) и подписывать с помощью заголовков свои запросы к API.
Однако каждый раз при запросе вручную формировать необходимые заголовки не совсем удобно, поэтому сегодня продолжим начатую работу и напишем небольшой класс, используя который, можно достаточно просто и удобно отправлять самые распространенные запросы (Get и Post) на сервер.
Итак, определимся с тем, какие операции будут выполнятся классом?
- Рассчитывать подпись к запросу
- Отправлять GET-запрос и возвращать ответ в виде строки (string)
- Отправлять POST-запрос и возвращать ответ в виде строки (string)
Какие модули и библиотеки будет использовать в своей работе класс?
Я решил не изменять своим привычкам и вновь воспользоваться библиотекой Synapse. Из библиотеки нам будут необходимы следующие модули:
- httpsend – для отправки запросов
- synacode – для работы с MD5, HMAC-SHA1, Base64 и т.д.
- ssl_openssl – для поддержки безопасного HTTPS
- synautil – для работ со вспомогательными методами, например, для преобразования дат в формат RFC-822 и т.д.
Теперь создаем новый модуль Delphi, подключаем в uses необходимые модули Synapse и определяем новый класс:
type TMegaplanRequest = class private FAccessID: string; //ключ AccessId, полученный при авторизации FSecretKey: string; //ключ SecretKey, полученный при авторизации FData : TStringStream;//даные для отправки с помощью POST procedure SetData(Str: string); function GetData:string; function CalcSignarure(const Method,URL: string; Date: TDateTime): string; function GetURI(const URL:string):string; public constructor Create(AccessID,SecretKey: string); destructor Destroy; function Get(const URL: string):string; function Post(const URL:string;Params:TStringList):string; property Data: string read GetData write SetData; end;
Теперь рассмотрим методы, используемые при работе с классом.
Create — конструктор. Создает новый экземпляр класса и заполняет необходимые поля FAccessId и FSecretKey:
constructor TMegaplanRequest.Create(AccessID,SecretKey: string); begin inherited Create; FAccessID:=AccessID; FSecretKey:=SecretKey; FData:=TStringStream.Create; end;
GetData получает данные из потока FData:TStringStream и представляет данные в виде строки string:
function TMegaplanRequest.GetData: string;
begin Result:=FData.DataString end;
SetData — обновляет данные в потоке FData, записывая в него строку:
procedure TMegaplanRequest.SetData(Str: string); begin FData.Clear; FData.WriteString(Str); end;
GetURI по заданному значению URL определяет URI — строку для формирования подписи:
function TMegaplanRequest.GetURI(const URL: string): string; begin if pos('http://',URL)>0 then Result:=Copy(URL,8,length(URL)-7) else if pos('https://',URL)>0 then Result:=Copy(URL,9,length(URL)-8) else Result:=URL; end;
CalcSignarure на основании данных, содержащихся в полях класса рассчитывает значение подписи:
function TMegaplanRequest.CalcSignarure(const Method, URL: string; Date: TDateTime): string; var BaseString: TStringStream; HMACsig,RFCDate: String; begin BaseString:=TStringStream.Create; try BaseString.WriteString(Method+LF);//метод if FData.Size=0 then BaseString.WriteString(LF)//ContentMD5 отсутствует else BaseString.WriteString(StrToHex(MD5(FData.DataString))+LF); if UpperCase(Method)='POST' then BaseString.WriteString('application/x-www-form-urlencoded'+LF) else BaseString.WriteString(LF);//Content-Type отсутствует RFCDate:=Rfc822DateTime(Date);//формируем дату в формате RFC-822 BaseString.WriteString(RFCDate+LF); BaseString.WriteString(URL);//HOST+URI HMACsig:=HMAC_SHA1(BaseString.DataString,FSecretKey);//зашифровали по HMAC-SHA1 Result:=EncodeBase64((StrToHex(HMACsig)));//перевели в HEX и шифроали по Base64 finally BaseString.Free; end; end;
Get — выполняет GET-запрос и возвращает ответ в виде строки string:
function TMegaplanRequest.Get(const URL: string): string; var URI:string; Date: TDateTime; DataStream: TstringStream; begin Date:=Now; DataStream:=TStringStream.Create; try with THTTPSend.Create do begin Headers.Add('Date: '+Rfc822DateTime(Date)); Headers.Add('X-Authorization: '+FAccessID+':'+CalcSignarure('GET',GetURI(URL),Date)); Headers.Add('Accept: application/json'); if HTTPMethod('GET',URL) then DataStream.LoadFromStream(Document) else Exception.Create(Format(cErrString,[ResultCode,ResultString])); end; Result:=DataStream.DataString; finally DataStream.Free; end; end;
Post — отправляет на сервер POST-запрос и возвращает ответ в виде строки:
function TMegaplanRequest.Post(const URL: string): string; var URI:string; Date: TDateTime; DataStream: TstringStream; begin Date:=Now; DataStream:=TStringStream.Create; try with THTTPSend.Create do begin Headers.Add('Date: '+Rfc822DateTime(Date)); Headers.Add('X-Authorization: '+FAccessID+':'+CalcSignarure('POST',GetURI(URL),Date)); Headers.Add('Accept: application/json'); FData.Position:=0; Document.LoadFromStream(FData); if HTTPMethod('POST',URL) then DataStream.LoadFromStream(Document) else Exception.Create(Format(cErrString,[ResultCode,ResultString])); end; Result:=DataStream.DataString; finally DataStream.Free; end; end;
Рассмотрим пример работы с классом TMegaplanRequest. В качестве примера повторим получение списка всех задач, которое мы рассматривали в предыдущем посте про Мегаплан:
var MegaAPI: TMegaplanRequest; begin MegaAPI:=TMegaplanRequest.Create('AccessID','SecretKey'); Memo1.Lines.Add(MegaAPI.Get('http://webdelphi.megaplan.ru/BumsTaskApiV01/Task/list.api')); ... end;
Вот и весь пример. Всего две строки и список всех задач из вашего аккаунта в Мегаплане у Вас в руках, ну, а дальше берем библиотеку SuperObject или другую, предназначенную для работы с JSON и парсим строку на предмет необходимых данных.
Модуль с классом TMegaplanRequest можно скачать здесь:
Книжная полка
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
[…] This post was mentioned on Twitter by Королевство Delphi, Vlad. Vlad said: Класс для отправки запросов к Мегаплан API. | Delphi в Internet http://bit.ly/fyGY14 […]
Спасибо!
Не за что, Алексей. Появилась одна неприятная проблемка — не хотят отсылаться POST-запросы :) Сегодня уже поздновато что-либо решать, но есть одна идея, которую я завтра попробую реализовать — должно сработать
Влад, здравствуйте.
Получилось победить POST?
ой как давно это было.. Вы скажите какая у вас проблема с POST-запросами, а я попытаюсь помочь, т.к. тот модуль уже где-то глубоко в недрах папки с исходниками и я им уже 100 лет не занимался :)
При попытке отправить любой POST-запрос, получаю «401 Unauthorized».
Меняю метод «POST» на «GET» — все Ок.
Я подумал, что «не хотят отсылаться POST-запросы» — из той же оперы.
Можно, конечно, и задачи методом GET создавать, но как-то криво :(
Код с паролями могу в мыло кинуть.