Компонент IdHTTP позволяет выполнять GET и POST запросы согласно протоколу HTTP.
( Загружать html- страницы, файлы, производить авторизацию на сайтах )
Содержание
1. Простые примеры. (загрузить страницу сайта, загрузка в файл, заголовки запроса и ответа)
2. Обработка исключений
3. Создание компонета динамически
4. Перенаправление ( редирикт )
5. Кодировки ( cp1251, UTF-8 )
6. Отображения хода загрузки
7. Cookie
8. POST-запрос для авторизации на сайте.
8.1. POST-запрос c загрузкой файла на сайт.(multipart/form-data)
9. Получение страниц в сжатом виде.
10. Передача с использованием HTTPS (расширение протокола HTTP, поддерживающее шифрование.)
11. Ведения лога запросов/ответов
Литература.
Темы.

1. Простые примеры.
1.1. Загрузить страницу сайта.
Простой пример загрузки html страницы в Memo
| C++ | 1
2
3
4
5
6
| //----------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");// Код страницы
}
//--------------------------------------------------------------------------- |
|
1.2.Загрузка в файл.
Сохранить полученную страницу (а также файл ,изображение итп... с сервера) в файл на диск можно используя TMemoryStream :
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| //-----------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMemoryStream *MS = new TMemoryStream;
try
{
IdHTTP1->Get("https://www.cyberforum.ru",MS);
MS->SaveToFile("1.html");
}
__finally
{
delete MS;
}
}
//--------------------------------------------------------------------------- |
|
Или через TFileStream :
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //-----------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFileStream* FS = new TFileStream("1.html", fmCreate | fmOpenWrite);
try
{
IdHTTP1->Get("https://www.cyberforum.ru", FS);
}
__finally
{
delete FS;
}
}
//--------------------------------------------------------------------------- |
|
1.3. Заголовки запроса и ответа.
Доступ к полям заголовка запроса можно получить через IdHTTP1->Request-> ...
К примеру имитируем запрос от Firefox
| C++ | 1
2
3
4
5
| IdHTTP1->Request->UserAgent= "Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0";
IdHTTP1->Request->Accept= "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
IdHTTP1->Request->AcceptLanguage= "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3";
IdHTTP1->Request->Connection= "keep-alive";
IdHTTP1->Request->Host= "store.steampowered.com"; |
|
Если не заполнять эти поля, то будут отсылаться значения полей по умолчанию Indy
После посылки запроса проверить ответ сервера можно, посмотрев содержимое свойство IdHTTP1->Response-> ....
| C++ | 1
2
3
4
5
6
7
| //-----------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");// Код страницы
Memo2->Text= IdHTTP->Response->ResponseText;// Ответ сервера
}
//--------------------------------------------------------------------------- |
|
Можно выполнить запрос без загрузки самой страницы (например для проверки её существования)
| C++ | 1
2
3
4
5
6
7
| //------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdHTTP1->Head("https://www.cyberforum.ru");
Memo1->Text= IdHTTP1->Response->RawHeaders->GetText();
}
//--------------------------------------------------------------------------------- |
|
2. Обработка исключений.
При загрузки страницы могут возникать исключения [7] которые иногда надо обрабатывать
(с целью перенаправления, руссификации и ведения лога ошибок )
Для отлова всех Indy- исключений достаточно :
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //-------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// Добавляем обработку исключения
try
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");
}
catch(const EIdException& E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
};
}
//--------------------------------------------------------------------------- |
|
Если смотреть подробнее стоит выделить:
1. Исключения сокетов [6]
2. Ответы сервера HTTP [2]
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| //----------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
try
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");
}
catch(const EIdSocketError& E) // Исключения сокетов
{
// Обработка, можно получить код ошибки сокета через E.LastError
// см. msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx
ShowMessage("Ошибка:\n"+E.Message);
}
catch(const EIdHTTPProtocolException& E)
{
// Можно получить код ответа сервера HTTP через E.ErrorCode
switch(E.ErrorCode)
{
case 400:
ShowMessage("400 Cервер обнаружил в запросе клиента синтаксическую ошибку");
break;
case 401:
ShowMessage("401 Запрос требует идентификации пользователя.");
break;
case 404:
ShowMessage("404 Страница не найдена");
break;
// ... итд полный список кодов смотри ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP
default :
ShowMessage(String(E.ErrorCode)+" "+E.Message);
break;
}
}
catch(const EIdException& E)// Другие исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
}
catch(const Exception& E) // Другие НЕ Indy исключения
{
ShowMessage("Ошибка:\n"+E.Message);
}
}
//--------------------------------------------------------------------------- |
|
Рассмотрим случай из темы Как проверить наличие соединения с Интернетом\Сетью посты #30,#31.
При коде
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
try
{
IdHTTP1->ConnectTimeout = 1000;
IdHTTP1->ReadTimeout = 1000;
IdHTTP1->Get("https://www.cyberforum.ru");
MessageBox(0, "Соединение с Интернет есть", "Информация", MB_OK + MB_ICONINFORMATION);
}
catch(const EIdHTTPProtocolException& E)
{
// ....
}
catch(const EIdSocketError& E)
{
ShowMessage(E.LastError);
}
}
//--------------------------------------------------------------------------- |
|

Сообщение от Avazart
Пробую этот код. Как бы работает.
Но вот в чем проблема компонент создается не динамически и если отключаю интернет - нажимаю кнопку, выбивает что интернета нет(или 11001 или 10054) потом я подключаю интернет и при повторной проверке- опять выбивает туже ошибку говоря что интернета нет ( хотя он есть ).
Я так понял компонет не выходит из "состояния ошибки".
|
 

Сообщение от MikeSoft
Вы должны его выводить, сам он практически ничего не сделает.
При получении ReadTimeout соединение останется открытым, поэтому его нужно закрыть.
К тому же, есть Connection Gracefully Closed. Это сообщение говорит о том, что удалённая сторона сама послала команду на закрытие соединение. В этом случае, тоже необходимо закрыть всё вручную. Поэтому, проще прописать закрытие на любое действие. Закрытие в новых версиях - это обычный Disconnect ... а вот в старых версиях Indy необходимо было непосредственно закрывать Socket.
| Т.е. после выполнения запроса, соединение может оставаться открытым, поэтому если соединение с данным сайтом больше не нужно, то необходимо позаботиться о его закрытии, в том числе в случаях выбрасывания исключения
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
try
{
try
{
IdHTTP1->Head("https://www.cyberforum.ru");
Memo1->Text= IdHTTP1->Response->RawHeaders->GetText();
}
__finally
{
IdHTTP1->Disconnect();
/* Независимо от того что произошло закрываем соединение.
(не важно было ли исключение или нет, не важно какой тип исключения) */
}
}
catch(const EIdException& E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
}
// catch( ) тут может обрабатваться другие типы ошибок ...
}
//--------------------------------------------------------------------------- |
|
Есть так же другой вариант решения этой проблемы - создавать компонент динамически, в таком случае закрытие будет происходить при уничтожении компонента.
3. Создание компонета динамически.
Если предпологается загружать страницы например в потоке, то удобно создавать компонент динамически.
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| //-------------------------------------------------------------------
/* заголовки необходимые для динамического создания
(обычно автоматом прописываются в h-файл формы
при кидании компонента на форму )*/
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdHTTP.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Динамическое создание
TIdHTTP* IdHTTP2= new TIdHTTP(NULL) ;
try
{
Memo1->Text= IdHTTP2->Get("https://www.cyberforum.ru");
}
catch(const EIdException &E) // Если не обрабатывать исключения удаление IdHTTP2 не произойдет
{
ShowMessage("Ошибка:\n"+E.Message);
}
delete IdHTTP2;
}
//--------------------------------------------------------------------------- |
|
При использовании std::auto_ptr<> отпадает необходимость заботиться об освобождении памяти.
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| //---------------------------------------------------------------------
#include <memory> //std::auto_ptr<>
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Динамическое создание с помощью auto_ptr
std::auto_ptr<TIdHTTP> IdHTTP2 (new TIdHTTP(NULL) );
try
{
Memo1->Text= IdHTTP2->Get("https://www.cyberforum.ru");
}
catch(const EIdException& E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
};
}
//--------------------------------------------------------------------------- |
|
4. Перенаправление ( редирикт ).
Для автоматического перехода на перенаправляемую страницу необходимо установить свойство
| C++ | 1
| IdHTTP1->HandleRedirects= true; |
|
Иначе будет генерироватся исключения с кодом 301,302 идр.. [2]

Судя по статье [1] IdHTTP1->HandleRedirects=true; не всегда помогает при перенаправлении, поэтому возникает необходимость обрабатывать перенаправление вручную.
С помощью IdHTTP1->Response->Location можно получить url куда нас собственно перенаправляют.
ErrorCode - код состояния (ответа) HTTP сервера[2]
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| //---------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
try
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");
// Тут может быть другой код ...
}
catch(const EIdHTTPProtocolException &E)
{
if( E.ErrorCode == 302 ) // код состояния HTTP- cервера [2]
{
Memo1->Text= IdHTTP1->Get(IdHTTP1->Response->Location); // переход
}
}
catch(const EIdException &E)// Другие исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
}
catch(const Exception &E) // Другие НЕ Indy исключения
{
ShowMessage("Ошибка:\n"+E.Message);
}
}
//--------------------------------------------------------------------------- |
|
5. Кодировки.
Иногда стоит задача получить ответ сервера в определенной кодировке, для этого необходимо использовать TStringStream c указанием нужной кодировки в его конструкторе.
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
| #include <memory>
//---------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
std::auto_ptr<TStringStream> // для UTF8
ContentStream(new TStringStream("",TEncoding::UTF8,true));
//std::auto_ptr<TStringStream> // для Windows cp1251
// ContentStream(new TStringStream("",TEncoding::GetEncoding(1251),true));
IdHTTP1->Get("http://avazart.zz.mu",ContentStream.get() );
Memo1->Text= ContentStream->DataString;
}
//-------------------------------------------------------------------- |
|
Старый подход к решению проблемы кодировок.
5.1. При загрузки страниц с кодировкой cp1251 русcкие символы отображаются не верно, я предпологаю что это связано с недоработкой Indy в плане совместимости с Юникодом.Поэтому приходится использовать самописные ф-ции вроде этой:
( Тема: Инди и русские символы )
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| //-----------------------------------------------------------------------
String WinToUnicode(const String St)
{
String Result="";
for (int i = 1; i <= St.Length(); i++)
{
if (int(St[i])>= 0x00C0 && int(St[i])<= 0x00FF)
Result += wchar_t(int(St[i])+0x350);
else Result += St[i];
}
return Result;
}
//------------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text= WinToUnicode( IdHTTP1->Get("http://my.mail.ru/cgi-bin/login?") );
}
//--------------------------------------------------------------------------- |
|
5.2. Для отображения UTF-8 можно использовать такую ф-цию
( Тема: Русские символы и html )
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| //-----------------------------------------------------------------------
wchar_t * utf8_to_unicode(char *utf8_string)
{
int err;
wchar_t * res;
int res_len = MultiByteToWideChar(
CP_UTF8, // Code page
0, // No flags
utf8_string, // Multibyte characters string
-1, // The string is NULL terminated
NULL, // No buffer yet, allocate it later
0 // No buffer
);
if (res_len == 0)
{
return NULL;
}
res = (wchar_t*)calloc(sizeof(wchar_t), res_len);
if (res == NULL)
{
return NULL;
}
err = MultiByteToWideChar(
CP_UTF8, // Code page
0, // No flags
utf8_string, // Multibyte characters string
-1, // The string is NULL terminated
res, // Output buffer
res_len // buffer size
);
if (err == 0)
{
free(res);
return NULL;
}
return res;
}//------------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text=
utf8_to_unicode(AnsiString( IdHTTP1->Get("http://my.mail.ru/cgi-bin/login?") ).c_str() );
}
//--------------------------------------------------------------------------- |
|
6. Отображения хода загрузки.
Для отображения используем компонент TProgressBar.
Вписываем код в соответствующие обработчики событий IdHTTP.
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Text= IdHTTP1->Get("https://www.cyberforum.ru");// Код страницы
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdHTTP1WorkBegin(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax)
{
// Устанавливаем размер загружаемых данных
if(AWorkMode==TWorkMode::wmRead)
ProgressBar1->Max = AWorkCountMax; // download
else if(AWorkMode==TWorkMode::wmWrite)
ProgressBar2->Max = AWorkCountMax; // upload
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdHTTP1Work(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount)
{
// Ход загрузки
if(AWorkMode==TWorkMode::wmRead)
ProgressBar1->Position = AWorkCount; // download
else if(AWorkMode==TWorkMode::wmWrite)
ProgressBar2->Position = AWorkCount; // upload
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdHTTP1WorkEnd(TObject *ASender, TWorkMode AWorkMode)
{
// Конец загрузки тут можно обнулить прогресс бары (а можно этого и не делать)
// if(AWorkMode==TWorkMode::wmRead)
// ProgressBar1->Position = 0;
// else if(AWorkMode==TWorkMode::wmWrite)
// ProgressBar2->Position = 0;
}
//--------------------------------------------------------------------------- |
|
7. Cookie
Для работы с Cookie можно использовать компонент TIdCookieManager связав его с TIdHTTP
| C++ | 1
2
| IdHTTP1->CookieManager= IdCookieManager1;
IdHTTP1->AllowCookies= true; |
|
Стоит заметить что на некоторых сайтах IdCookieManager1 не может воспринять куки так как они записаны в особой форме, поэтому приходится устанавливать куки вручную. (Тема: https://www.cyberforum.ru/post235829.html )
8. POST-запрос для авторизации на сайте. [8]
( Тема: Бот на С++ )
Для авторизации на сайте нужно знать как должен выглядит POST-запрос.
В POST-запросе побычно передаются таки данные как логин,пароль итп.
Определить форму запроса можно просмотрев что шлет браузер при авторизации.
В FireFox для этого можно использовать специальный плагин для просмотров HTTP заголовков.
Также можно использовать такие сниферы как HttpAnalyzerV5 или Charles
Итак пример запроса котрый шлет браузер для авторизации :

http://ganjafarm.ru/?nick=player2012&password=test&page=login
Разбираем этот запрос по строкам согласно разделителям "?" и "&" , запрос передается в виде "переменная = значение"
http://ganjafarm.ru/
? nick=player2012
& password=test
& page=login
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringList *SL= new TStringList;
IdHTTP1->CookieManager= IdCookieManager1;
IdHTTP1->AllowCookies= true;
String Url = "http://ganjafarm.ru";
SL->Add("nick=player2012"); // ? nick=player2012
SL->Add("password=test"); // & password=test
SL->Add("page=login"); // & page=login
try
{
Memo1->Text= IdHTTP1->Post(Url,SL);
}
catch(const EIdException &E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
};
delete SL;
}
//--------------------------------------------------------------------------- |
|
Что бы после авторизации сохранялись кукисы нужно связывать IdHTTP с TIdCookieManager как говорилось выше.
8.1. POST-запрос c загрузкой файла на сайт.
Для запроса содержащего multipart/form-data предназначен класс TIdMultiPartFormDataStream объект которого передается как второй параметр в метод Post()
В качестве примера приведу код загрузки файла на файлообменник
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| /* Далее "ввв" вместо "www", почему ? - спросите у АДминов */
// [url]http://ввв.***********[/url] - файлообменник с предпросмотром изображения
//---------------------------------------------------------------------------
#include <memory> // for std::auto_ptr<>
#include <StrUtils.hpp> // for PosEx()
//---------------------------------------------------------------------------
String ParseLink(String Text,int start,String LeftTag,String RightTag)
{
int left = PosEx(LeftTag,Text,start) + LeftTag.Length();
int right = PosEx(RightTag,Text,left);
if(left< LeftTag.Length() || right<left) return "";
return Text.SubString(left,right-left);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(OpenPictureDialog1->Execute() )
{
std::auto_ptr<TIdMultiPartFormDataStream>
PostData(new TIdMultiPartFormDataStream);
PostData->AddFormField("upload","yes",""); // Один из необходимых полей для данного файлообменника
String Name= "F"; // Имя поля соответствующего файлу
String FileName= OpenPictureDialog1->FileName; // Путь к файлу
PostData->AddFile(Name,FileName);
String Url= "http:/ввв.***********/action.aspx";
String Content = IdHTTP1->Post(Url, PostData.get());
// Вытаскиваем ссылку на изображение
String Link= ParseLink(Content,1,"[img]","[/img]");
// Выводим ссылку
LinkLabel1->Caption= "<a href=""+Link+"">"+Link+"</a>";
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LinkLabel1LinkClick(TObject *Sender, const UnicodeString Link,
TSysLinkType LinkType)
{
// Перейти по ссылке в браузере
ShellExecuteW(Handle,L"open",Link.w_str(),NULL,NULL,SW_RESTORE);
}
//--------------------------------------------------------------------------- |
|
Метод AddFormField() добавляет поле с указанным именем и его значением, а метод AddFile() добавляет файл.
В указанных методах также можно дополнительными параметрами явно указывать тип контента (ContentType) и Сharset.
Из справки XE3:
| C++ | 1
| public: __fastcall TIdFormDataField AddFormField(const AnsiString AFieldName, const AnsiString AFieldValue, const AnsiString ACharset = "", const AnsiString AContentType = "", const AnsiString AFileName = ""); |
|
Из справки Indy
| Delphi | 1
2
3
4
5
| procedure AddFile(
const AFieldName: string;
const AFileName: string;
const AContentType: string
); |
|
Примечание: после отправки POST- запроса с multipart/form-data поле заголовка Content Type изменится на:
| Code | 1
| multipart/form-data; boundary= -- ... |
|
Поэтому для отправки в дальнейшем "обычного" POST запроса нужно Content Type предварительно восстановить:
| C++ | 1
| IdHTTP1->Request->ContentType= "application/x-www-form-urlencoded"; |
|
(Тема: Загрузка файла на сервер и последующая публикация )
9. Получение страниц в сжатом виде.
( Тема: Декомпрессия принятой страницы )
Некоторые сервера поддерживают передачу страниц в сжатом виде, это увеличивает скорость загрузки страницы.
Для получения страницы в сжатом виде устанавливаем свойство:
| C++ | 1
| IdHTTP1->Request->AcceptEncoding = "gzip" ; |
|
Для декомпрессиии используем компонент TIdCompressorZLib ( Не работает в RAD XE2, но работает в RAD XE3 )
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| //------------------------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdHTTP1->HandleRedirects= true;
IdHTTP1->Request->AcceptEncoding = "gzip";
IdHTTP1->Compressor = IdCompressorZLib1;
try
{
Memo1->Text= IdHTTP1->Get("http://google.ru") ; // google позволяет получать в сжатом виде
}
catch(const EIdException &E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
};
}
//--------------------------------------------------------------------------- |
|
10. Передача с использованием HTTPS.
( Тема: Indy и HTTPS )
Для работы с протоколом https связываем TIdHTTP c компонентом TIdSSLIOHandlerSocketOpenSSL
Скорее всего понадобиться библиотеки libeay32.dll и ssleay32.dll которые можно скачать например здесь: http://indy.fulgan.com/SSL/ их необходимо положить в папку с exe-ником вашей программы
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| //-------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdHTTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;
try
{
Memo1->Text= IdHTTP1->Get("https://my.webmoney.ru");
}
catch(const EIdException &E)// Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
};
}
//------------------------------------------------------ |
|
11. Ведения лога запросов/ответов
"Глубины Indy" Перевод: А.П. Подгорецкий стр 71
13.2. Ведение логов (Logging)
Indy 8.0 имел один компонент ведения логов, который мог быть использован для различных
источников. В Indy 9.0 компоненты логов теперь базируются на новом общем классе и имеют
специализированные классы. Базовый класс также предоставляет свойства и функциональность,
такую как регистрация времени, в дополнение к данным.
Все классы ведения логов реализованы, как перехватчики. Это означает, что они перехватывают
входящие данные, после того, как они были прочитаны и перед передачей исходящих в
источник.
Специализированные классы логов, следующее:
• TIdLogEvent – возбуждает события, когда данные приняты, или переданы, или при
появлении события состояния. Класс TIdLogEvent полезен для реализации
пользовательских логов, без необходимости в реализации нового класса.
• TIdLogFile – Записывает данные в файл.
• TIdLogDebug – Записывает данные в окно отладки Windows или в консоль Linux. Также
отмечает данные, как принятые данные, переданные данные или информация о статусе.
Класс TidLogDebug полезен для проведения простой отладки.
• TIdLogStream – Не добавляет комментариев, отметок к данным, как другие классы.
Вместо этого просто записывает сырые данные в указанный поток. Класс TIdLogStream
может использоваться по разному, но обычно он очень эффективно используется для QA
тестирования и удаленной отладки. Могут быть построены и пользовательские классы
логов.
| И так рассмотрим пример с использованием TIdLogEvent для ведения лога в Memo1.
Добавляем компонент на форму, создаем соответствующие для него обработчики событий
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
// Это можно сделать визуально через инспектор обьектов
IdLogEvent1->ReplaceCRLF = false; // чтоб не проводилась замена символов перевода строк
IdLogEvent1->Active=true;
IdHTTP1->Intercept = IdLogEvent1; // Связываем IdHTTP1 с IdLogEvent1
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String Content;
try
{
Content = IdHTTP1->Get("https://www.cyberforum.ru");
}
catch(EIdException &E) // Ловим исключения Indy
{
ShowMessage("Ошибка:\n"+E.Message);
}
if(IdHTTP1->Connected() )
IdHTTP1->Disconnect();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdLogEvent1Sent(TComponent *ASender,
const UnicodeString AText,
const UnicodeString AData)
{
Memo1->Lines->Add(AData); // Передача
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdLogEvent1Received(TComponent *ASender,
const UnicodeString AText,
const UnicodeString AData)
{
Memo1->Lines->Add( AData ); // Приём
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdLogEvent1Status(TComponent *ASender,
const UnicodeString AText)
{
Memo1->Lines->Add(AText); // Статус соединения
}
//--------------------------------------------------------------------------- |
|
В место компонентов Indy для лога, иногда удобнее использовать самописную ф-цию вроде этой:
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| void __fastcall AddToLog(TStrings* Lines, TIdHTTP* IdHTTP, String HtmlContent="Контент не указан")
{
Lines->Add("------------- Запрос --------------------");
Lines->Add( IdHTTP->Request->URL);
Lines->AddStrings( IdHTTP->Request->RawHeaders);
Lines->Add("");
Lines->Add("------------- Ответ --------------------");
Lines->Add( IdHTTP->ResponseText);
Lines->AddStrings( IdHTTP->Response->RawHeaders);
Lines->Add("");
Lines->Add("------------- Контент --------------------");
Lines->Add(HtmlContent);
Lines->Add("");
} |
|
Литература:
1. Для начинающих работать с компонентом idHTTP в Delphi
2. http://ru.wikipedia.org/wiki/%... D1%8F_HTTP
3. Пример авторизации на сайте с помощью idHTTP.Post
4. Компоненты Internet Direct (Indy). Вводная статья для новичков
5. Уроки C++ Builder с нуля
6. http://msdn.microsoft.com/en-u... s.85).aspx
7. http://docwiki.embarcadero.com... lException
8. http://parsing-and-i.blogspot.... ppost.html
9. "Глубины Indy" Перевод: А.П. Подгорецкий
Темы:
1. Сайт в мемо
2. Инди и русские символы
3. Авторизация на сайте через IdHTTP
4. Чтение html из url
5. Создание и копирование настроек IdHTTP
6. Post Запрос авторизации на сайте + куки
7. Как проверить наличие соединения с Интернетом\Сетью
8. IdHTTP авторизаця на форуме
9. Парсинг характеристик товара с Яндекс.Маркета
10. Взять значения из сайта
11. Поток: программа зависает во время парсинга
12. Наличие файла на сайте
13. Русские символы и html
14. IdHTTP Авторизация на сайте
15. Кодировка страницы
16. IdHTTP Русский запрос!
17. IdHTTP или TIdMultiPartFormDataStream передает кириллицу в неправильной кодировке
18. idHTTP и unicodeString
19. Очень медленно скачивает страницу (TIdHTTP). Как ускорить? // TIdCompressorZLib,сжатые страницы
20. Indy и HTTPS // IdSSLIOHandlerSocketOpenSSL
21. Скачка файла с интернета // Прогрессбар
22. Пример авторизации на mail.ru (С++)
23. Как отправить запрос на онлайн-сервис // TIdMultiPartFormDataStream
24. Бот на С++ // Post запрос
25. IdHTTP->Get в потоке и прогрессом
26. Получение результата после POST запроса
27. IdHTTP Русский запрос!
28. Загрузка файла на сервер и последующая публикация
29. Нормализация URL в C++ Builder
30. TIdFormDataField передача XML
31. Как сохранять и загружать cookie? [C++/Indy]
|