• 【小结】IIS7下的Http Native Module开发


      今天接到Product Manager的通知,Exchange 2007环境下的Native Module不再需要开发(详情可见上篇),但最近几天一直在做Prototype,那就做一下小结吧,总结一下最近几天的收获。

      一. 准备工作:

      1. 开发前安装Windows Platform SDK,主要是使用其中的#include <httpserv.h>(用到的很多接口都可以在其中看到)

      2. WireShark,用来进行抓包,可以验证自己是否正确拿到http request和response的信息

      

      二. Visual Studio 2005编码:

      1. Native Module主要使用3个基本组件:

        A. HttpModule类 - HttpModule是当前模块的积累。在HttpModule类中我们将实现请求通知方法,这个方法是由IIS在相关的请求处理事件中调用的。(其中主要是定义我们的处理时间方法,例如onBeginRequest)

        B. HttpModule类工厂 - 针对每个被处理的请求,HttpModule类工厂可以创建或删除用于处理请求的模块

        C. RegisterModule类函数 - 一个Native Module只会实现一个此函数,用于导出函数,使IIS能够加载模块(我遇到一个问题,至今还没解决,就是此函数中我发现只能注册一个事件,如果多个会导致IIS ative sync pool stop掉,DLL用不起来)

      2. 其他具体编码可参见我的示例,具体开发流程可参见《IIS 7开发与管理完全参考手册》

      

      三. 安装此Native Module

      经过我的测试发现,我的Native Module能够工作,主要是做了以下几项工作:

      1. 编译后的DLL放置在C:WindowsSystem32inetsrv下

      2. 修改applicationHost.xml配置文件,C:WindowsSystem32inetsrvconfig,在其中的<globalModules>中添加我们的模块

      3. IIS 7中,[DomainUser]下,Module中,右键选择Configure Native Module,然后选择Register,填入我们模块的信息。

      目前我还不确定2,3是否是重复了,但是我发现这两者都做的情况,我的Native Module是工作的,而3的Register不是修改2的配置文件,具体有待验证。

      经过以上三个步骤,我的Native Module可以工作了!目前可以拿到Http的Request Header的信息。希望这次小结,能对有开发此类需求的同学一点参考,由于此功能被PM去掉了,所以很遗憾这块我不能继续做下去,只能是小结啦。:-)

    参考资料:

    1. 《Professional IIS7》,Wrox出版社出版(Programmer to Programer的理念),非常详细的讲解IIS7,其中12章详细介绍了Http两类Module的开发。其中文版是《IIS 7开发与管理完全参考手册》

    2. MSDN

      http://msdn.microsoft.com/en-us/library/ms690856(v=vs.90).aspx

    Prototype代码附上,功能:取Http request的header信息

    #define _WINSOCKAPI_
    #include <windows.h>
    #include <sal.h>
    #include <httpserv.h>
    #include "writeLog.h"
    
    // Create the module class.
    class CTestNativeModule : public CHttpModule
    {
        //TODO
        // Implement Notification Method/s
        REQUEST_NOTIFICATION_STATUS
            OnBeginRequest( IN IHttpContext * pHttpContext,
            IN IHttpEventProvider * pProvider
            )
        {
            WriteLog("--> CTestNativeModule, OnBeginRequest()");
            // We won’t be using this, so confirm that to avoid compiler warnings        
            UNREFERENCED_PARAMETER( pProvider );
    
            IHttpRequest* pHttpRequest = pHttpContext->GetRequest();
            
            //dump request header
            DumpRequestHeader(pHttpContext, pHttpRequest);
            
            WriteLog("<-- CTestNativeModule, OnBeginRequest()");
          
            return RQ_NOTIFICATION_CONTINUE;
        }
      void DumpRequestHeader(IHttpContext * pHttpContext, IHttpRequest* pHttpRequest)
        {
            WriteLog("--> CTestNativeModule, DumpRequestHeader()");
            
            // Buffer size for returned variable values.
            DWORD cbValue = 512;
            PCSTR pHeaderValue = (PCSTR) pHttpContext->AllocateRequestMemory( cbValue );
    
            for(HTTP_HEADER_ID i = (HTTP_HEADER_ID)0; i < HttpHeaderRequestMaximum; i = (HTTP_HEADER_ID)((int)i + 1))
            {
                pHeaderValue = pHttpRequest->GetHeader(i);
                WriteLog(pHeaderValue);            
            }
            
            HTTP_REQUEST* rawHttpRequest = pHttpRequest->GetRawHttpRequest();
            WriteLog("RawUrl", rawHttpRequest->pRawUrl);
            
            PCSTR pKey = "";
    
            pKey = "Cmd";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            pKey = "DeviceId";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            pKey = "DeviceType";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            pKey = "AttachmentName";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
            
            pKey = "MS-ASProtocolVersion";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            pKey = "X-EAS-Proxy";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            pKey = "User-Agent";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            WriteLog(pKey, pHeaderValue);
    
            /*
            //Authorization
            pKey = "Authorization";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            writeLog(pKey, pHeaderValue);
    
            //Content-Type
            pKey = "Content-Type";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            writeLog(pKey, pHeaderValue);
    
            //Host
            pKey = "Host";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            writeLog(pKey, pHeaderValue);
    
            //Content-Length
            pKey = "Content-Length";
            pHeaderValue = pHttpRequest->GetHeader(pKey);
            writeLog(pKey, pHeaderValue);*/
    
            WriteLog("<-- CTestNativeModule, DumpRequestHeader()");
        }
        
        void DumpRequestContent(IHttpContext* pHttpContext, IHttpRequest* pHttpRequest)
        {
            // Create an HRESULT to receive return values from methods.
            /*HRESULT hr;
            // Allocate a 1K buffer.
            DWORD cbBytesReceived = 1024;
            void* pvRequestBody = pHttpContext->AllocateRequestMemory(cbBytesReceived);
            hr = pHttpRequest->ReadEntityBody( pvRequestBody, cbBytesReceived, false, &cbBytesReceived, NULL);*/
        }
    };
    
    // Create the module's class factory.
    class CTestNativeModuleFactory : public IHttpModuleFactory
    {
    public:
        HRESULT
            GetHttpModule(
            OUT CHttpModule ** ppModule, 
            IN IModuleAllocator * pAllocator
            )
        { 
            WriteLog("--> CTestNativeModuleFactory, GetHttpModule()");
    
            UNREFERENCED_PARAMETER( pAllocator );
    
            // Create a new instance.
            CTestNativeModule * pModule = new CTestNativeModule;
    
            // Test for an error.
            if (!pModule)
            {
                // Return an error if the factory 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;
            }
            WriteLog("<-- CTestNativeModuleFactory, GetHttpModule()");
        }
    
        void
            Terminate()
        {
            WriteLog("--> CTestNativeModuleFactory, Terminate()");
            // Remove the class from memory.
            delete this;
            WriteLog("<-- CTestNativeModuleFactory, Terminate()");
        }
    };
    
    // Create the module's exported registration function.
    HRESULT
    __stdcall
    RegisterModule(
                   DWORD dwServerVersion,
                   IHttpModuleRegistrationInfo * pModuleInfo,
                   IHttpServer * pGlobalInfo
                   )
    {
        WriteLog("--> RegisterModule()");
        HRESULT hr = S_OK;
    
        UNREFERENCED_PARAMETER( dwServerVersion );
        UNREFERENCED_PARAMETER( pGlobalInfo );
    
        // TODO
        // Register for notifications
        // Set notification priority
        
        CTestNativeModuleFactory* testNMFacotry = new CTestNativeModuleFactory;
        
        // Set the request notifications
        // BeginRequest
        hr = pModuleInfo->SetRequestNotifications(
            testNMFacotry,
            RQ_BEGIN_REQUEST, // Register for BeginRequest notifications
            0);    
        
        if( hr == S_OK ) // Do this only if there was no error
        {
            hr = pModuleInfo->SetPriorityForRequestNotification(
                RQ_BEGIN_REQUEST,     // which notification
                PRIORITY_ALIAS_FIRST  // what priority
                );
        }
        WriteLog("<-- RegisterModule()");
        return hr;
    }
  • 相关阅读:
    gitlab+jenkens+maven私服
    记录一次gitlab+jenkins入坑到排坑的过程
    python进阶之路一,变量、运算符、判断、while循环
    cat EOF追加与覆盖
    tcpdump使用
    iptables学习
    Java生产消费模型—ArrayBlockingQueue详解
    Java泛型详解(透彻)
    Java源码初探_logging日志模块实现
    Java设计模式学习总结
  • 原文地址:https://www.cnblogs.com/KevinSong/p/3347314.html
Copyright © 2020-2023  润新知