WinInet в Delphi. Начало. HTTP запрос.

Здравствуйте уважаемые коллеги!

Библиотека WinInet, или Win32 Internet Extensions, предоставляет набор API функций для работы с протоколами HTTP и FTP. В данном примере я покажу как используя данную библиотеку получить исходный HTML код страницы.

Для работы с API нам понадобиться добавить в раздел USES модуль Winapi.WinInet (или просто WinInet для более поздних версий Delphi).

Для начала опишу функции WinInet, которые понадобятся мне в данном примере:

InternetOpen

Это первая функция WinINet, которая должна вызываться в приложении. Она говорит DLL инициализировать внутренние структуры данных и подготовиться к будущим вызовам приложения. В случае неудачи вернет NIL. Информацию об ошибке можно получить с помощь функции GetLastError.

InternetOpen(
  lpszAgent: LPWSTR; 
  dwAccessType: DWORD; 
  lpszProxy: LPWSTR;
  lpszProxyBypass: LPWSTR; 
  dwFlags: DWORD
): HINTERNET;

lpszAgent — Указатель на строку содержащую имя приложения, которое используется как user agent в HTTP протоколе.
dwAccessType — Указывает какой тип доступа использовать из списка значений:

INTERNET_OPEN_TYPE_DIRECT Прямое подключение.
INTERNET_OPEN_TYPE_PRECONFIG Получить настройки подключения из реестра.
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY Получает настройки из реестра и предотвращает использование Microsoft JScript или Internet Setup (INS) файла.
INTERNET_OPEN_TYPE_PROXY Доступ через прокси сервер.

lpszProxy — Указатель на строку содержащую адрес прокси сервера, если dwAccessType указан INTERNET_OPEN_TYPE_PROXY.
lpszProxyBypass — Указатель на строку, которая содержит адреса, которые не нужно передавать через прокси.
dwFlags — Флаг дополнительных опций, который может принимать значение:

INTERNET_FLAG_ASYNC Выполнять только асинхронные запросы.
INTERNET_FLAG_FROM_CACHE Все запросы возвращаются только из кэша. Если запрашиваемого элемента нет в кэше, то возвращается ошибка ERROR_FILE_NOT_FOUND.
INTERNET_FLAG_OFFLINE Аналогично INTERNET_FLAG_FROM_CACHE запросы возвращаются из кэша.

InternetConnect

Функция открывает сессию работы с FTP или HTTP протоколом для указанного сайта. При неудаче возвращает NIL.

InternetConnect(
	hInet: HINTERNET; 
	lpszServerName: LPWSTR;
	nServerPort: INTERNET_PORT; 
	lpszUsername: LPWSTR; 
	lpszPassword: LPWSTR;
	dwService: DWORD; 
	dwFlags: DWORD; 
	dwContext: DWORD_PTR
	): HINTERNET;

hInet — Указатель созданный функцией InternetOpen.
lpszServerName — Указатель на строку содержащую имя сервера, например asd-soft.ru или IP адрес.
nServerPort — Порт сервера. Можно использовать константы:

INTERNET_DEFAULT_FTP_PORT Порт FTP по умолчанию (21).
INTERNET_DEFAULT_HTTP_PORT Порт HTTP по умолчанию (80).
INTERNET_DEFAULT_HTTPS_PORT Порт HTTPS по умолчанию (443).
INTERNET_DEFAULT_SOCKS_PORT Порт SOCKS по умолчанию (1080).
INTERNET_INVALID_PORT_NUMBER Использовать стандартный порт для службы, указанной в dwService.

lpszUsername — Указатель на строку, которая определяет имя пользователя. Если параметр NIL, то функция использует значение по умолчанию. Для FTP протокола это «anonymous».
lpszPassword — Указатель на строку, которая определяет пароль пользователя.
dwService — Определяет тип сервиса:

INTERNET_SERVICE_FTP FTP протокол.
INTERNET_SERVICE_GOPHER Gopher.
INTERNET_SERVICE_HTTP HTTP протокол.

dwFlags — Опции, специфичные для выбранного сервиса в dwService.
dwContext — Указатель на функцию, которая будет обрабатывать возвращаемые события. Например, при асинхронной работе.

HttpOpenRequest

Подготовка HTTP запроса.

HttpOpenRequest(
	hConnect: HINTERNET; 
	lpszVerb: LPWSTR;
	lpszObjectName: LPWSTR; 
	lpszVersion: LPWSTR; 
	lpszReferrer: LPWSTR;
	lplpszAcceptTypes: PLPSTR; 
	dwFlags: DWORD;
	dwContext: DWORD_PTR
	): HINTERNET;

hConnect — Указатель на HTTP сессию, созданную функцией InternetConnect.
lpszVerb — Указатель на строку с типом запроса GET или POST. Если указать NIL, то будет использоваться GET запрос.
lpszObjectName — Указатель на строку, которая содержит объект запроса. Это может быть HTML страница, скрипт или файл.
lpszVersion — Указатель на строку с версией протокола. Если передать NIL, то функция использует HTTP версии 1.1 или 1.0 в зависимости от настроек Internet Explorer.
lpszReferrer — Указатель на строку с адресом предыдущей страницы.
lplpszAcceptTypes — Указатель на строку с типом содержимого. Какие именно значения могут быть переданы описаны в этом документе.
dwFlags — Набор флагов из списка:

INTERNET_FLAG_CACHE_IF_NET_FAIL Возвращать данные из кэша, если сеть не доступна.
INTERNET_FLAG_HYPERLINK Перезагружает данные из сети, если нет Expires time или LastModified time.
INTERNET_FLAG_IGNORE_CERT_CN_INVALID Отключает проверку SSL/PCT сертификатов, которые возвращает сервер.
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID Отключает проверку SSL/PCT сертификатов на достоверные даты.
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP При использовании этого флага WinInet позволяет делать переадресацию с HTTPS на HTTP адреса.
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS При использовании этого флага WinInet позволяет делать переадресацию с HTTP на HTTPS адреса.
INTERNET_FLAG_KEEP_CONNECTION Поддерживать соединение с сервером.
INTERNET_FLAG_NEED_FILE Указывается в случае, если временный файл должен быть создан при отсутствии в кэше.
INTERNET_FLAG_NO_AUTH Не использовать автоматическую аутентификацию.
INTERNET_FLAG_NO_AUTO_REDIRECT Не использовать автоматическую переадресацию.
INTERNET_FLAG_NO_CACHE_WRITE Не добавляет данные в кэш.
INTERNET_FLAG_NO_COOKIES Отключает использование кукисов.
INTERNET_FLAG_NO_UI Отключает диалоговое окно cookie.
INTERNET_FLAG_PRAGMA_NOCACHE Получать данные с исходного сервера, даже при наличии их в кэше прокси сервера.
INTERNET_FLAG_RELOAD Запрашивает загрузку данных с сервера, а не из кэша.
INTERNET_FLAG_RESYNCHRONIZE Перезагрузить HTTP ресурсы, если они были изменены с момента последней загрузки.
INTERNET_FLAG_SECURE Использовать безопасные SSL/PCT транзакции. Имеет смысл только для HTTP запросов.

dwContext — Ссылка на ресурсы связанные с этим запросом.

HttpSendRequest

Отправляет HTTP запрос. Возвращает True в случае удачного выполнения запроса.

HttpSendRequest(
	hRequest: HINTERNET; 
	lpszHeaders: LPWSTR; 
	dwHeadersLength: DWORD; 
	lpOptional: Pointer; 
	dwOptionalLength: DWORD
	): boolean;	

hRequest — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpszHeaders — Указатель на строку с дополнительными заголовками запроса.
dwHeadersLength — Длинна дополнительных заголовков.
lpOptional — Указатель на буфер, содержащий дополнительные данные. Этот параметр обычно используется при POST и PUT запросах.
dwOptionalLength — Размер передаваемого буфера.

HttpQueryInfo

Запросить информацию связанную с HTTP запросом.

HttpQueryInfo(
	hRequest: HINTERNET; 
	dwInfoLevel: DWORD;
	lpvBuffer: Pointer; 
	var lpdwBufferLength: DWORD;
	var lpdwReserved: DWORD
): boolean;

hRequest — Указатель на запрос подготовленный функцией HttpOpenRequest.
dwInfoLevel — Набор флагов, определяющих тип возвращаемой информации. Со списком возможных флагов можно ознакомиться на данной странице. В нашем примере нам понадобится всего два:

HTTP_QUERY_FLAG_NUMBER Указывает на то, что нужно возвращать число в качестве статуса.
HTTP_QUERY_STATUS_CODE Нужно возвращать стату. Список возможных статусов перечислен на этой странице.

lpvBuffer — Указатель на буфер для возвращаемой информации. Этот параметр не может быть NIL.
lpdwBufferLength — Указатель на переменную, в которую будет записан размер возвращаемого буфера.
lpdwReserved — Указатель на переменную в которой содержится индекс заголовка возвращаемой информации.

InternetQueryDataAvailable

Запрашивает кол-во данных полученных в результате запроса.

InternetQueryDataAvailable(
	hFile: HINTERNET; 
	var lpdwNumberOfBytesAvailable: DWORD;
	dwFlags: DWORD; 
	dwContext: DWORD_PTR
	): boolean;

hFile — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpdwNumberOfBytesAvailable — Указатель на переменную в которую будет передано кол-во доступных байт.
dwFlags — Параметр не используется и должен быть равным 0.
dwContext — Параметр не используется и должен быть равным 0.

InternetReadFile

Читает данные полученные запросом.

InternetReadFile(
	hFile: HINTERNET; 
	lpBuffer: Pointer;
	dwNumberOfBytesToRead: DWORD; 
	var lpdwNumberOfBytesRead: DWORD
	): boolean;

hFile — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpBuffer — Указатель на буфер для чтения данных.
dwNumberOfBytesToRead — Кол-во байт для чтения.
lpdwNumberOfBytesRead — Кол-во прочитанных байт.

InternetCloseHandle

Освобождает указатель созданный функциями InternetOpen, InternetConnect или HttpOpenRequest.

InternetCloseHandle(
	hInet: HINTERNET
	): boolean;

hInet — Указатель.

И последняя функция, которая не относится к API WinInet, но которая нам понадобиться: GetLastError — Возвращает код последней ошибки.

Теперь напишем код, который получит HTML код страницы с адресом http://asd-soft.ru/delphi-wininet-begin-http

var
  hInet, hCon, hReq: HINTERNET;
  Status, StatusSize, Index: DWORD;
  bytes, b, pos: Cardinal;
  ResponseString: AnsiString;
begin
  hInet := InternetOpen('My Agent', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(hInet) then
	raise Exception.Create('Ошибка при выполнении функции InternetOpen' + sLineBreak + SysErrorMessage(GetLastError));
  try
	hCon := InternetConnect(hInet, 'asd-soft.ru', INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
	if not Assigned(hCon) then 
	  raise Exception.Create('Ошибка при выполнении функции InternetConnect' + sLineBreak + SysErrorMessage(GetLastError));
	try
	  hReq := HttpOpenRequest(hCon, 'GET', 'delphi-wininet-begin-http', HTTP_VERSION, nil, nil, INTERNET_FLAG_KEEP_CONNECTION or INTERNET_FLAG_RELOAD, 0);
	  if not Assigned(hReq) then
		raise Exception.Create('Ошибка при выполнении функции HttpOpenRequest' + sLineBreak + SysErrorMessage(GetLastError));
	  try
		HttpSendRequest(hReq,'', 0, nil, 0);
		StatusSize := SizeOf(Status);
		Index := 0;
		HttpQueryInfo(hReq, HTTP_QUERY_FLAG_NUMBER or HTTP_QUERY_STATUS_CODE, @Status, StatusSize, Index);
		if Status <> HTTP_STATUS_OK then
		  raise Exception.Create('Ошибка при выполнении функции HttpSendRequest' + sLineBreak + 'Статус: ' + IntToStr(Status) + sLineBreak + SysErrorMessage(GetLastError));
		pos := 1;
		b := 1;
		ResponseString := '';
		while b > 0 do begin
          if not InternetQueryDataAvailable( hReq, bytes, 0, 0 ) then
			raise Exception.Create('Ошибка при выполнении функции InternetQueryDataAvailable' + sLineBreak + SysErrorMessage(GetLastError));
          SetLength( ResponseString, Length(ResponseString) + bytes );
          InternetReadFile( hReq, @ResponseString[Pos], bytes, b );
          Inc(Pos, b);
        end;
	  finally
        InternetCloseHandle(hReq);
      end;
	finally
      InternetCloseHandle(hCon);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;

Результатом выполнения данного кода будет HTML код страницы в переменной ResponseString.

Функция SysErrorMessage — возвращает текст ошибки по коду из GetLastError.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *