Сервер Web своими руками. Язык HTML, приложения CGI и ISAPI

Приложение ISHELLO


В качестве нашего первого расширения ISAPI мы предлагаем приложение ISHELLO, выполняющее простейшие функции.

Вызов расширения ishello.dll выполняется из формы, исходный текст которой приведен в листинге 8.1.

Листинг 8.1. Файл chap8\ishello\ishello.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<HTML>

  <HEAD>

    <TITLE>ISAPI Script Test</TITLE>

  </HEAD>

  <BODY BGCOLOR=#FFFFFF>

    <H1>Вызов расширения ISAPI</H1>

    <FORM METHOD=POST     ACTION="http://frolov/scripts/ishello.dll?Param1|Param2|Param3">

      <INPUT TYPE=submit VALUE="Send">

    </FORM>



  </BODY>

</HTML>

Расширение вызывается в параметре ACTION оператора <FORM> аналогично тому, как это делается для программ CGI.

Расширение ishello.dll динамически создает документ HTML, представленный на рис. 8.1.

Рис. 8.1. Документ HTML, созданный динамически расширением ishello.dll

В верхней части этого документа отображается содержимое некоторых полей структуры EXTENSION_CONTROL_BLOCK, а в нижней в качетсве примера отображается содержимое переменной ALL_HTTP, полученное с помощью функции GetServerVariable.

Исходный текст расширения ishello.dll представлен в листинге 8.2.

Листинг 8.2. Файл chap8\ishello\ishello.c

// ===============================================

// Расширение ISAPI ishello.c

// Пример простейшего расширения ISAPI

//

// (C) Фролов А.В., 1997

// E-mail: frolov@glas.apc.org

// WWW:    http://www.glasnet.ru/~frolov

//         или

//         http://www.dials.ccas.ru/frolov

// ===============================================

#include <windows.h>

#include <httpext.h>

// =============================================================

// Функция GetExtensionVersion

// Запись версии интерфейса ISAPI и

// строки описания расширения

// =============================================================

BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)


{

  // Записываем версию интерфейса ISAPI

  pVer->dwExtensionVersion =

    MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR );

  // Записываем строку описания расширения

  lstrcpyn(pVer->lpszExtensionDesc,

    "Simple ISAPI DLL", HSE_MAX_EXT_DLL_NAME_LEN);

  return TRUE;

}

// =============================================================

// Функция HttpExtensionProc

// =============================================================

DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *lpECB)

{

  CHAR  szBuff[4096];

  CHAR  szTempBuf[4096];

 

  DWORD  dwSize;

  // Нулевой код состояния - признак успешного выполнения

  lpECB->dwHttpStatusCode = 0;

  // Записываем в буфер заголовок HTTP и начальный

  // фрагмент формируемого динамически документа HTML

  wsprintf(szBuff,

    "Content-Type: text/html\r\n\r\n"

    "<HTML><HEAD><TITLE>Simple ISAPI Extension</TITLE></HEAD>\n"

    "<BODY BGCOLOR=#FFFFFF><H1>Hello from ISAPI Extension!</H1>\n");

  // Добавляем разделительную линию

  strcat(szBuff, "<HR>");

 

  // Добавляем версию интерфейса ISAPI

  wsprintf(szTempBuf, "<P>Extension Version: %d.%d",

    HIWORD(lpECB->dwVersion), LOWORD(lpECB->dwVersion));

  strcat(szBuff, szTempBuf);

 

  // Название метода передачи данных

  wsprintf(szTempBuf, "<BR>Method: %s", lpECB->lpszMethod);

  strcat(szBuff, szTempBuf);

 

  // Строка параметров запуска расширения ISAPI

  wsprintf(szTempBuf, "<BR>QueryString: %s",

    lpECB->lpszQueryString);

  strcat(szBuff, szTempBuf);

 

  // Физический путь к программному файлу расширения ISAPI

  wsprintf(szTempBuf, "<BR>PathTranslated: %s",

    lpECB->lpszPathTranslated);

  strcat(szBuff, szTempBuf);

  // Полный размер данных, которые нужно получить

  wsprintf(szTempBuf, "<BR>TotalBytes: %d",



    lpECB->cbTotalBytes);

  strcat(szBuff, szTempBuf);

  // Тип данных

  wsprintf(szTempBuf, "<BR>ContentType: %s",

    lpECB->lpszContentType);

  strcat(szBuff, szTempBuf);

  // Отображаем содержимое переменных сервера

  strcat(szBuff, "<HR><P><B>Server Variables:</B><BR>");

  dwSize = 4096;

  lpECB->GetServerVariable(lpECB->ConnID,

    (LPSTR)"ALL_HTTP", (LPVOID)szTempBuf, &dwSize);

  strcat(szBuff, szTempBuf);

  // Конечный фрагмент документа HTML

  strcat(szBuff, "</BODY></HTML>"); 

  // Посылаем содержимое буфера удаленному пользователю

  if(!lpECB->ServerSupportFunction(lpECB->ConnID,

    HSE_REQ_SEND_RESPONSE_HEADER, NULL, NULL,

    (LPDWORD)szBuff))

  {

    // Если послать данные не удалось,

    // завершаем работу нашего расширения ISAPI

    // с кодом ошибки

    return HSE_STATUS_ERROR;

  }

  // Записываем код успешного завершения

  lpECB->dwHttpStatusCode = 200;

 

  // Возвращаем признак успешного завершения 

  return HSE_STATUS_SUCCESS;

}

Обратите внимание, что наряду с обычным для приложений Windows файлом windows.h мы включили в наш исходный текст файл httpext.h, в котором определены все необходимые константы, структуры данных и прототипы функций. Этот файл поставляется в составе Microsoft Visual C++ версии 4.2, а также в составе Internet SDK, который можно получить на сервере www.microsoft.com.

В приложении определена функция GetExtensionVersion, которая уже была рассмотрена нами ранее. Эта функция с небольшими изменениями будет встречаться во всех наших примерах расширений ISAPI. Она записывает версию интерфейса ISAPI и текстовую строку описания расширения в поля структуры типа HSE_VERSION_INFO с именами dwExtensionVersion и lpszExtensionDesc, сответственно. Адрес структуры HSE_VERSION_INFO передается функции GetExtensionVersion через единственный параметр.

Функция HttpExtensionProc использует буфер szBuff для подготовки динамически создаваемого документа HTML, который будет послан удаленному пользователю в результате работы нашего расширения. В качестве вспомогательного буфера применяется буфер szTempBuf.



Прежде всего в буфер szBuff записывается заголовок HTTP и начальный фрагмент документа HTML, для чего используется функция wsprintf. Далее к буферу szBuff с помощью функции strcat будут добавляться другие строки документа. Например, разделительная линия добавляется так:

strcat(szBuff, "<HR>");

После первой разделительной линии в документ добавляется несколько строк со значениями некоторых полей структуры типа EXTENSION_CONTROL_BLOCK. В следующем фрагменте кода добавляется строка версии интерфейса ISAPI:

wsprintf(szTempBuf, "<P>Extension Version: %d.%d",

  HIWORD(lpECB->dwVersion), LOWORD(lpECB->dwVersion));

strcat(szBuff, szTempBuf);

Далее в документ выводятся строка с названием метода передачи данных (поле lpszMethod), строка параметров запуска расширения ISAPI (поле lpszQueryString), физический путь к программному файлу библиотеки DLL расширения (поле lpszPathTranslated), полный размер данных, которые нужно прочитать (поле cbTotalBytes), а также тип данных (поле lpszContentType).

После этого в документ снова выводится разделительная линия и отображается содержимое переменных сервера с префиксом имени HTTP, для чего используется рассмотренная ранее функция GetServerVariable.

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

strcat(szBuff, "</BODY></HTML>");

Документ посылается удаленному пользователю функцией ServerSupportFunction, как это показано ниже:

if(!lpECB->ServerSupportFunction(lpECB->ConnID,

    HSE_REQ_SEND_RESPONSE_HEADER, NULL, NULL, (LPDWORD)szBuff))

{

  return HSE_STATUS_ERROR;

}

Если при посылке данных произошла ошибка, расширение завершает свою работу с кодом HSE_STATUS_ERROR.

В случае успеха в поле состояния dwHttpStatusCode записывается код 200, вслед за чем расширение завершает свою работу с кодом HSE_STATUS_SUCCESS.

Файл определения модуля для библиотеки DLL расширения ISAPI представлен в листинге 8.3.

Листинг 8.3. Файл chap8\ishello\ishello.def

LIBRARY            ishello

DESCRIPTION  'Simple ISAPI DLL'

EXPORTS

    GetExtensionVersion

    HttpExtensionProc


Содержание раздела