Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Введение
IIS 7.0 и более поздних версий позволяет расширить сервер по модулям, разработанным двумя способами:
- Использование управляемого кода и API расширения сервера ASP.NET
- Использование машинного кода и API расширяемости собственного сервера IIS
В отличие от предыдущих версий IIS, большинство сценариев расширяемости сервера не требуют разработки собственного кода (C++) и могут быть размещены с помощью управляемого кода и api ASP.NET. Использование ASP.NET для расширения сервера позволяет значительно сократить время разработки и воспользоваться широкими возможностями ASP.NET и .NET Framework. Дополнительные сведения о расширении служб IIS с использованием ASP.NET см. в статье "Разработка модуля IIS с помощью .NET".
IIS также предоставляет собственный API-интерфейс основного сервера C++, который заменяет API фильтра и расширения ISAPI из предыдущих выпусков IIS. Если у вас есть определенные требования, требующие разработки машинного кода, или хотите преобразовать существующие собственные компоненты ISAPI, воспользуйтесь этим API для создания компонентов сервера. Новый API собственного сервера предоставляет объектно-ориентированное разработку с интуитивно понятной объектной моделью, обеспечивает больший контроль над обработкой запросов и использует более простые шаблоны проектирования для создания надежного кода.
В этом пошаговом руководстве рассматриваются следующие задачи:
- Разработка собственного модуля с помощью собственного API сервера (C++)
- Развертывание собственного модуля на сервере
Чтобы скомпилировать модуль, необходимо установить пакет SDK платформы, содержащий файлы заголовков IIS. Последняя версия пакета SDK для платформы Windows Vista доступна здесь.
Чтобы использовать пакет SDK платформы с Visual Studio 2005, необходимо зарегистрировать пакет SDK. После установки SDK выполните это через Пуск > Программы > Microsoft Windows SDK > Регистрация Visual Studio > Регистрация каталогов Windows SDK в Visual Studio.
Исходный код этого модуля доступен в примере собственного модуля Visual Studio IIS7.
Разработка собственного модуля
В этой задаче мы рассмотрим разработку собственного модуля с помощью нового собственного API сервера (C++). Собственный модуль — это библиотека DLL Windows, содержащая следующие компоненты:
- Экспортируемая функция RegisterModule . Эта функция отвечает за создание фабрики модулей и регистрацию модуля для одного или нескольких событий сервера.
- Реализация класса модуля, наследуемого от базового класса CHttpModule . Этот класс предоставляет основные функциональные возможности модуля.
- Реализация класса фабрики модулей, реализующего интерфейс IHttpModuleFactory . Класс отвечает за создание экземпляров модуля.
Замечание
В некоторых случаях можно также реализовать интерфейс IGlobalModule , чтобы расширить некоторые функции сервера, которые не связаны с обработкой запросов. Это расширенный раздел, который не рассматривается в этом пошаговом руководстве.
Собственный модуль имеет следующий жизненный цикл:
При запуске рабочего процесса сервера она загружает библиотеку DLL, содержащую модуль, и вызывает экспортированную функцию RegisterModule . В этой функции вы:
a. Создайте фабрику модулей.
б. Зарегистрируйте фабрику модулей для событий конвейера запроса, которые ваш модуль реализует.При поступлении запроса сервер:
a. Создает экземпляр вашего класса модуля с использованием предоставленной вами фабрики.
б. Вызывает соответствующий метод обработчика событий в экземпляре модуля для каждого зарегистрированного события запроса.
с. Удаляет экземпляр модуля в конце обработки запросов.
Теперь начнем его строить.
Полный исходный код модуля доступен в примере собственного модуля Visual Studio IIS7. Приведенные ниже шаги являются наиболее важными для разработки модуля и не включают в себя поддержку обработки кода и ошибок.
Реализуйте функцию RegisterModule , вызываемую сервером при загрузке библиотеки DLL модуля. Его сигнатура и остальная часть собственного API определяются в заголовочном файле httpserv.h, который является частью пакета Platform SDK. Если у вас нет пакета Platform SDK, ознакомьтесь со введением, чтобы узнать, как его получить.
main.cpp:
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo * pModuleInfo,
IHttpServer * pHttpServer
)
{
// step 1: save the IHttpServer and the module context id for future use
g_pModuleContext = pModuleInfo->GetId();
g_pHttpServer = pHttpServer;
// step 2: create the module factory
pFactory = new CMyHttpModuleFactory();
// step 3: register for server events
hr = pModuleInfo->SetRequestNotifications( pFactory,
RQ_ACQUIRE_REQUEST_STATE,
0 );
}
The RegisterModule
Существует три основных задачи, которые необходимо выполнить внутри RegisterModule:
Сохраните глобальное состояние
Мы будем хранить глобальный экземпляр сервера и идентификатор контекста модуля для последующего использования в глобальных переменных. Хотя в этом примере эта информация не используется, многие модули могут оказаться полезными для сохранения и использования позже во время обработки запросов. Интерфейс IHttpServer предоставляет доступ ко многим функциям сервера, таким как открытие файлов и доступ к кэшу. Идентификатор контекста модуля используется для связывания пользовательского состояния модуля с несколькими объектами сервера, такими как запрос и приложение.
Создание фабрики модулей
Мы реализуем класс фабрики CMyHttpModuleFactory далее в этой пошаговой инструкции. Эта фабрика отвечает за производственные экземпляры нашего модуля для каждого запроса.
Регистрация фабрики модулей для событий обработки требуемого запроса
Регистрация выполняется с помощью метода SetRequestNotifications, который инструктирует сервер следующим образом: создать экземпляр нашего модуля для каждого запроса, используя указанную фабрику; а также вызывать соответствующие обработчики событий на каждом из этапов обработки запроса, которые указаны.
В этом случае нас интересует только этап RQ_ACQUIRE_REQUEST_STATE. Полный список этапов, составляющих конвейер обработки запросов, определяется в httpserv.h:
#define RQ_BEGIN_REQUEST 0x00000001 // request is beginning
#define RQ_AUTHENTICATE_REQUEST 0x00000002 // request is being authenticated
#define RQ_AUTHORIZE_REQUEST 0x00000004 // request is being authorized
#define RQ_RESOLVE_REQUEST_CACHE 0x00000008 // satisfy request from cache
#define RQ_MAP_REQUEST_HANDLER 0x00000010 // map handler for request
#define RQ_ACQUIRE_REQUEST_STATE 0x00000020 // acquire request state
#define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040 // pre-execute handler
#define RQ_EXECUTE_REQUEST_HANDLER 0x00000080 // execute handler
#define RQ_RELEASE_REQUEST_STATE 0x00000100 // release request state
#define RQ_UPDATE_REQUEST_CACHE 0x00000200 // update cache
#define RQ_LOG_REQUEST 0x00000400 // log request
#define RQ_END_REQUEST 0x00000800 // end request
Кроме того, вы можете подписаться на несколько недетерминированных событий, которые могут возникать во время обработки запросов из-за действий, которые выполняют другие модули, например очистка ответа клиенту:
#define RQ_CUSTOM_NOTIFICATION 0x10000000 // custom notification
#define RQ_SEND_RESPONSE 0x20000000 // send response
#define RQ_READ_ENTITY 0x40000000 // read entity
#define RQ_MAP_PATH 0x80000000 // map a url to a physical path
Чтобы реализация RegisterModule была доступна серверу, необходимо экспортировать ее. Используйте . DEF-файл, содержащий ключевое слово EXPORTS для экспорта функции RegisterModule.
Затем реализуйте класс фабрики модулей:
mymodulefactory.h:
class CMyHttpModuleFactory : public IHttpModuleFactory
{
public:
virtual HRESULT GetHttpModule(
OUT CHttpModule **ppModule,
IN IModuleAllocator *
)
{
}
virtual void Terminate()
{
}
};
Фабрика модулей реализует интерфейс IHttpModuleFactory и служит для создания экземпляров модуля по каждому запросу.
Сервер вызывает метод GetHttpModule в начале каждого запроса, чтобы получить экземпляр модуля, который будет использоваться для этого запроса. Реализация просто возвращает новый экземпляр класса модуля CMyHttpModule, который мы реализуем далее. Как мы видим вскоре, это позволяет нам легко хранить состояние запроса, не беспокоясь о безопасности потоков, так как сервер всегда создает и использует новый экземпляр модуля для каждого запроса.
Более сложные реализации фабрики могут решить использовать единый шаблон вместо создания нового экземпляра каждый раз или использовать предоставленный интерфейс IModuleAllocator для выделения памяти модуля в пуле запросов. Эти расширенные шаблоны не рассматриваются в этом пошаговом руководстве.
Метод завершения вызывается сервером, когда рабочий процесс завершает работу, чтобы выполнить окончательную очистку модуля. Если вы инициализируете любое глобальное состояние в RegisterModule, осуществите его очистку в этом методе.
Реализация класса модуля
Этот класс отвечает за предоставление основных функциональных возможностей модуля во время одного или нескольких событий сервера:
myhttpmodule.h:
class CMyHttpModule : public CHttpModule
{
public:
REQUEST_NOTIFICATION_STATUS
OnAcquireRequestState(
IN IHttpContext * pHttpContext,
IN OUT IHttpEventProvider * pProvider
);
};
Класс модуля наследует от базового класса CHttpModule , который определяет метод обработчика событий для каждого из событий сервера, рассмотренных ранее. Когда конвейер обработки запросов выполняет каждое событие, он вызывает связанный метод обработчика событий для каждого экземпляра модуля, зарегистрированного для этого события.
Каждый метод обработчика событий имеет следующую подпись:
REQUEST_NOTIFICATION_STATUS
OnEvent(
IN IHttpContext * pHttpContext,
IN OUT IHttpEventProvider * pProvider
);
Интерфейс IHttpContext предоставляет доступ к объекту контекста запроса, который можно использовать для выполнения задач обработки запросов, таких как проверка запроса и управление ответом.
Интерфейс IHttpEventProvider заменяется более конкретным интерфейсом для каждого события, предоставляющего определенные функциональные возможности модуля. Например, обработчик событий OnAuthenticateRequest получает интерфейс IAuthenticationProvider , позволяющий модулю задать прошедшего проверку подлинности пользователя.
Возвращаемым значением каждого метода обработчика событий является одно из значений перечисления REQUEST_NOTIFICATION_STATUS. Необходимо вернуть RQ_NOTIFICATION_CONTINUE, если модуль успешно выполнил задачу; Конвейер должен продолжать выполнение.
Если произошел сбой и требуется прервать обработку запросов с ошибкой, необходимо задать состояние ошибки и вернуть RQ_NOTIFICATION_FINISH_REQUEST. Возврат RQ_NOTIFICATION_PENDING позволяет асинхронно выполнять работу и освободить поток, обрабатывающий запрос, чтобы его можно было использовать повторно для другого запроса. Асинхронное выполнение не рассматривается в этой статье.
Класс модуля переопределяет метод обработчика событий OnAcquireRequestState. Чтобы обеспечить функциональные возможности на любом из этапов конвейера, класс модуля должен переопределить соответствующий метод обработчика событий. Если вы регистрируетесь на событие в RegisterModule, но не переопределяете соответствующий метод обработчика событий в вашем модульном классе, то модуль завершится сбоем во время выполнения (и утверждение будет активировано во время отладки, если он откомпилирован в режиме отладки). Будьте осторожны и убедитесь, что сигнатура метода переопределения точно эквивалентна методу базового класса класса CHttpModule , который вы переопределяете.
Компиляция модуля
Помните, что для компиляции требуется пакет SDK для платформы. Дополнительные сведения о получении и настройке ссылок для возможности использования их в Visual Studio см. в "Введение".
Развертывание собственного модуля
После компиляции модуля необходимо развернуть его на сервере. Скомпилируйте модуль, а затем скопируйте IIS7NativeModule.dll (и файл символов отладки IIS7NativeModule.pdb при необходимости) в любое расположение на компьютере под управлением IIS.
Собственные модули, в отличие от управляемых модулей, которые можно добавить непосредственно в приложение, сначала необходимо установить на сервере. Для этого требуются права администратора.
Чтобы установить собственный модуль, у вас есть несколько вариантов:
-
Использование средства командной строки APPCMD.EXE
APPCMD упрощает установку модуля. Перейдите к разделу "Запуск>программ>"Аксессуары, щелкните правой кнопкой мыши командную строку и выберите "Запуск от имени администратора". В окне командной строки выполните следующее:
%systemroot%\system32\inetsrv\appcmd.exe install module /name:MyModule /image:[FULL\_PATH\_TO\_DLL]
Где [FULL_PATH_TO_DLL] — это полный путь к скомпилированной библиотеке DLL, содержащей только что созданный модуль. -
Использование средства администрирования IIS
Это позволяет добавить модуль с помощью графического интерфейса. Перейдите к запуску>введите inetmgr и нажмите клавишу ВВОД. Подключитесь к localhost, найдите задачу "Модули" и дважды щелкните ее, чтобы открыть ее. Затем щелкните задачу "Добавить собственный модуль " на правой панели. -
Установка модуля вручную
Установите модуль вручную, добавив его <в раздел конфигурации system.webServer>/<globalModules> в файле конфигурации applicationHost.config и добавьте ссылку на него в <разделе конфигурации system.webServer>/<modules> в том же файле, чтобы включить его. Рекомендуется использовать один из предыдущих двух вариантов для установки модуля, а не редактирования конфигурации напрямую.
Задача завершена. Мы закончили настройку нового собственного модуля.
Сводка
В этом пошаговом руководстве вы узнали, как разрабатывать и развертывать пользовательский модуль с помощью новых API расширяемости (C++). Ознакомьтесь с обзором Native-Code разработки, чтобы узнать больше о native API сервера C++.
Дополнительные сведения о расширении IIS с помощью управляемого кода и платформы .NET см. в статье «Разработка модуля IIS с помощью .NET». Дополнительные сведения об управлении модулями IIS см. в техническом документе по модулю.