Execution order of modules in IIS7

Each request received by IIS 7.0 goes through multiple stages in the IIS request pipeline (read more about request pipeline here). In IIS, request processing move from one stage to the next stage in a fixed sequence. If any of the modules in system.webServer/modules section have subscribed to the event for the current stage then IIS calls each of those modules one by one before moving on to next stage. If there are multiple modules which subscribe to the same event (say RQ_BEGIN_REQUEST), module with higher priority is called first. Native modules can set execution priority for itself in RegisterModule using SetPriorityForRequestNotification. The following code snippet illustrates this for RQ_BEGIN_REQUEST.

HRESULT
RegisterModule(
    DWORD dwServerVersion,
    IHttpModuleRegistrationInfo* pModuleInfo,
    IHttpServer* pGlobalInfo
)
{

    HRESULT hr = S_OK;

    IHttpModuleFactory* pModuleFactory = NULL;
 
    // create module factory

    hr = pModuleInfo->SetRequestNotifications(pModuleFactory, RQ_BEGIN_REQUEST, 0 );
    // some stuff

    hr = pModuleInfo->SetPriorityForRequestNotification(
               
RQ_BEGIN_REQUEST,
                PRIORITY_ALIAS_FIRST);

    // more stuff
    return hr;
}

If multiple modules subscribe to the same event and set the same priority, the module that is listed first in the system.webServer/modules section gets executed first. RQ_EXECUTE_REQUEST_HANDLER is different in this respect as it picks up the ordering from system.webServer/handlers section. Taking the example of StaticFile handler entry from default IIS configuration which looks like the following

<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />

IIS picks one handler for a request but each entry can have multiple modules executed which can appear as comma separated list as is the case for StaticFile handler. StaticFileModule, DefaultDocumentModule and DirectoryListingModule, all three subscribe to RQ_EXECUTE_HANDLER and use default priority. The default ordering of these modules is important to ensure they work correctly. Changing it can have undesirable effects. For example, putting DefaultDocumentModule before DirectoryListingModule will make DirectoryListingModule run first and if directoryBrowse is disabled, it will generate a 403.14 even before DefaultDocumentModule got a chance to check defaultDocument section and pick default file. DirectoryListingModule should execute only if defaultDocument is disabled and putting it after DefaultDocumentModule serve that purpose.

So IIS decides module execution order as following:

  1. Module which subscribe to an earlier pipeline stages execute before the modules which subscribe to a later stage.
  2. Among modules which subscribe for the same event, module with higher priority runs before module with lower priority. RQ_SEND_RESPONSE priority order is opposite of other notifications. Modules with RQ_SEND_RESPONSE priority LAST are run first, followed by priority LOW and so on. You cannot set priority of managed modules. All managed modules assume default priority.
  3. Among modules which subscribe for the same event and with same priority, module appearing first in system.webServer/modules section gets called first (RQ_EXECUTE_REQUEST_HANDLER stage is special and ordering is picked from system.webServer/handlers section and not from system.webServer/modules).

Global modules which subscribe only to global events can use IHttpModuleRegistrationInfo::SetPriorityForGlobalNotification for setting the priority. Step 3 for globalModules is based on ordering in system.webServer/globalModules section. For native modules which subscribe to only request events, ordering in system.webServer/globalModules section is immaterial (even though they appear in globalModules section). IIS just use the globalModules entry to load the module but calls only modules which appear in system.webServer/modules section.

-Kanwal

Leave a Reply

Your email address will not be published. Required fields are marked *