Поделиться через


Метод IHttpContext::ExecuteRequest

Выполняет дочерний запрос.

Синтаксис

virtual HRESULT ExecuteRequest(  
   IN BOOL fAsync,  
   IN IHttpContext* pHttpContext,  
   IN DWORD dwExecuteFlags,  
   IN IHttpUser* pHttpUser,  
   OUT BOOL* pfCompletionExpected = NULL  
) = 0;  

Параметры

fAsync
[IN] Всегда true (указывает асинхронное выполнение).

pHttpContext
[IN] Указатель на дочерний элемент IHttpContext для выполнения.

dwExecuteFlags
[IN] Объект , DWORD содержащий флаги выполнения запроса.

pHttpUser
[IN] Указатель на IHttpUser для запроса. (необязательно)

pfCompletionExpected
[OUT] true значение , если асинхронное завершение по-прежнему ожидается; в противном случае — false. (необязательно)

Возвращаемое значение

Объект HRESULT. Допустимые значения включают, но не ограничиваются, значения, приведенные в следующей таблице.

Значение Описание:
S_OK Указывает, что операция прошла успешно.
ERROR_NOT_SUPPORTED Указывает, что запрос не поддерживается (например, fAsync задано значение false или дочерний запрос не был клонирован из родительского запроса).
ERROR_STACK_OVERFLOW Указывает, что запрос превышает ограничение для рекурсивных дочерних запросов.

Комментарии

Метод ExecuteRequest выполняет дочерний запрос, указанный интерфейсом IHttpContext в параметре pHttpContext . Этот контекст запроса необходимо создать с помощью метода IHttpContext::CloneContext .

Важно!

Попытка выполнить дочерний запрос, который не был клонирован родительским запросом, вернет ERROR_NOT_SUPPORTED.

Каждый дочерний контекст может выполняться только один раз, хотя дочерние запросы могут быть вложены рекурсивно.

Примечание

Ограничение для рекурсивных дочерних запросов составляет 10.

Метод ExecuteRequest поддерживает только асинхронную операцию, которая предотвращает исчерпание пула потоков.

Важно!

Попытка выполнить синхронный дочерний запрос вернет ERROR_NOT_SUPPORTED.

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

Значение Описание
EXECUTE_FLAG_NO_HEADERS Подавляйте заголовки HTTP для дочернего запроса.
EXECUTE_FLAG_IGNORE_CURRENT_INTERCEPTOR Игнорируйте текущий обработчик сопоставления скриптов для этой цепочки запросов.
EXECUTE_FLAG_IGNORE_APPPOOL Выполните запрос, даже если дочерний запрос находится не в том же пуле приложений.
EXECUTE_FLAG_DISABLE_CUSTOM_ERROR Отключите пользовательские ошибки для дочернего запроса.
EXECUTE_FLAG_SAME_URL URL-адрес дочернего запроса совпадает с url-адресом родительского запроса. Примечание: Обработчики карты скриптов используют этот флаг для пересылки выполнения.
EXECUTE_FLAG_BUFFER_RESPONSE Не сбрасывайте дочерний ответ; возвращает ответ на родительский запрос.
EXECUTE_FLAG_HTTP_CACHE_ELIGIBLE Ответ ребенка по-прежнему имеет право на кэширование Http.sys. Примечание: Кэширование отключено по умолчанию при выполнении дочернего запроса.

Если указать IHttpUser интерфейс для pHttpUser, проверка подлинности для дочернего запроса будет пропущена.

Пример

В следующем примере кода показано, как создать модуль HTTP, который выполняет следующие задачи:

  1. Модуль регистрируется для уведомления RQ_MAP_PATH .

  2. Модуль создает класс CHttpModule , содержащий методы OnMapPath и OnAsyncCompletion .

  3. Когда веб-клиент запрашивает URL-адрес, IIS вызывает метод модуля OnMapPath . Этот метод выполняет следующие задачи:

    1. Проверяет, соответствует ли URL-адрес текущего запроса двум конкретным URL-адресам в корне веб-сайта. Если URL-адрес совпадает с указанным URL-адресом, модуль использует IHttpContext::CloneContext метод для создания клона текущего запроса.

    2. Вызывает метод клона IHttpRequest::SetUrl , чтобы задать ДЛЯ клона URL-адрес /example/default.aspx.

    3. ExecuteRequest Вызывает метод для выполнения дочернего запроса.

    4. Проверяет асинхронное завершение. Если асинхронное завершение ожидается, модуль возвращает обработку в интегрированный конвейер обработки запросов. В противном случае модуль освобождает клонированные контексты.

  4. Если требуется асинхронное завершение, СЛУЖБЫ IIS вызывают метод модуля OnAsyncCompletion . Этот метод освобождает клонированные контексты.

  5. Модуль удаляет CHttpModule класс из памяти, а затем завершает работу.

#define _WINSOCKAPI_
#include <windows.h>
#include <sal.h>
#include <httpserv.h>

// Create the module class.
class MyHttpModule : public CHttpModule
{

private:

    // Create a pointer for a child request.
    IHttpContext * m_pChildRequestContext;

public:

    MyHttpModule(void)
    {
        m_pChildRequestContext = NULL;
    }

    REQUEST_NOTIFICATION_STATUS
    OnMapPath(
        IN IHttpContext * pHttpContext,
        IN IMapPathProvider * pProvider
    )
    {
        UNREFERENCED_PARAMETER( pProvider );

        HRESULT hr;
        BOOL fCompletionExpected;

        // Retrieve a pointer to the URL.
        PCWSTR pwszUrl = pProvider->GetUrl();

        // Only process requests for the root.
        if (0 == wcscmp(pwszUrl,L"/") || 0 == wcscmp(pwszUrl,L"/default.aspx"))
        {            
            // Clone the current context.
            hr = pHttpContext->CloneContext(
                CLONE_FLAG_BASICS, &m_pChildRequestContext );
            
            // Test for a failure.
            if (FAILED(hr))
            {
                goto Failure;
            }
            
            // Test for an error.
            if ( NULL != m_pChildRequestContext )
            {
                // Set the URL for the child request.
                hr = m_pChildRequestContext->GetRequest()->SetUrl(
                    "/example/default.aspx",
                    (DWORD)strlen("/example/default.aspx"),false);
            
                // Test for a failure.
                if (FAILED(hr))
                {
                    goto Failure;
                }
                
                // Execute the child request.
                hr = pHttpContext->ExecuteRequest(
                    TRUE, m_pChildRequestContext,
                    0, NULL, &fCompletionExpected );
                
                // Test for a failure.
                if (FAILED(hr))
                {
                    goto Failure;
                }
                
                // Test for pending asynchronous operations.
                if (fCompletionExpected)
                {
                    return RQ_NOTIFICATION_PENDING;
                }

            }

 Failure:
            // Test for a child request.
            if (NULL != m_pChildRequestContext)
            {
                // Release the child request.
                m_pChildRequestContext->ReleaseClonedContext();
                m_pChildRequestContext = NULL;
            }
        }
        
        // Return processing to the pipeline.
        return RQ_NOTIFICATION_CONTINUE;
    }
    
    REQUEST_NOTIFICATION_STATUS
        OnAsyncCompletion(
        IN IHttpContext * pHttpContext,
        IN DWORD dwNotification,
        IN BOOL fPostNotification,
        IN IHttpEventProvider * pProvider,
        IN IHttpCompletionInfo * pCompletionInfo
        )
    {
        // Test for a child request.
        if (NULL != m_pChildRequestContext)
        {
            // Release the child request.
            m_pChildRequestContext->ReleaseClonedContext();
            m_pChildRequestContext = NULL;
        }
        // Return processing to the pipeline.
        return RQ_NOTIFICATION_CONTINUE;
    }

};

// Create the module's class factory.
class MyHttpModuleFactory : public IHttpModuleFactory
{
public:
    HRESULT
    GetHttpModule(
        OUT CHttpModule ** ppModule, 
        IN IModuleAllocator * pAllocator
    )
    {
        UNREFERENCED_PARAMETER( pAllocator );

        // Create a new instance.
        MyHttpModule * pModule = new MyHttpModule;

        // Test for an error.
        if (!pModule)
        {
            // Return an error if we cannot create the instance.
            return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
        }
        else
        {
            // Return a pointer to the module.
            *ppModule = pModule;
            pModule = NULL;
            // Return a success status.
            return S_OK;
        }            
    }

    void Terminate()
    {
        // Remove the class from memory.
        delete this;
    }
};

// Create the module's exported registration function.
HRESULT
__stdcall
RegisterModule(
    DWORD dwServerVersion,
    IHttpModuleRegistrationInfo * pModuleInfo,
    IHttpServer * pGlobalInfo
)
{
    UNREFERENCED_PARAMETER( dwServerVersion );
    UNREFERENCED_PARAMETER( pGlobalInfo );

    return pModuleInfo->SetRequestNotifications(
        new MyHttpModuleFactory,
        RQ_MAP_PATH,
        0
    );
}

Модуль должен экспортировать функцию RegisterModule . Эту функцию можно экспортировать, создав файл определения модуля (DEF- файл) для проекта, или скомпилировать модуль с помощью /EXPORT:RegisterModule параметра . Дополнительные сведения см. в разделе Пошаговое руководство. Создание модуля HTTP Request-Level с помощью машинного кода.

При необходимости можно скомпилировать код с помощью __stdcall (/Gz) соглашения о вызовах вместо явного объявления соглашения о вызовах для каждой функции.

Требования

Тип Описание
клиент — IIS 7.0 в Windows Vista
— IIS 7.5 в Windows 7
— IIS 8.0 в Windows 8
— IIS 10.0 в Windows 10
Сервер — IIS 7.0 в Windows Server 2008
— IIS 7.5 в Windows Server 2008 R2
— IIS 8.0 в Windows Server 2012
— IIS 8.5 в Windows Server 2012 R2
— IIS 10.0 в Windows Server 2016
Продукт — IIS 7.0, IIS 7.5, IIS 8.0, IIS 8.5, IIS 10.0
- IIS Express 7.5, IIS Express 8.0, IIS Express 10.0
Заголовок Httpserv.h

См. также:

Интерфейс IHttpContext
Метод IHttpContext::CloneContext
Метод IHttpContext::GetParentContext
Метод IHttpContext::ReleaseClonedContext