博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Url rewrite详细分析
阅读量:6032 次
发布时间:2019-06-20

本文共 14202 字,大约阅读时间需要 47 分钟。

在写这篇随笔之前,其实网上早已有高手分析了.text的urlrewrite的实现(点击 查看全文),问题是作为一个初学者的我,看了以后,感觉没有切中要害。所以,产生了写这篇dd的冲动。 
从头说起,.text是通过httpModules和httpHandlers来实现urlrewrite的,看看web.config中的配置 
 1
        
<
httpHandlers
> 
 2
            
<!--
 Can not see to load asmx like .aspx, since we will grap all requests later, make sure these are processed by their default factory 
--> 
 3
            
<
add 
verb
="*"
 path
="*.asmx"
 type
="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
 
 4
                validate
="false"
 
/> 
 5
            
<!--
Since we are grabbing all requests after this, make sure Error.aspx does not rely on .Text 
--> 
 6
            
<
add 
verb
="*"
 path
="Error.aspx"
 type
="System.Web.UI.PageHandlerFactory"
 
/> 
 7
            
<!--
This will process any ext mapped to aspnet_isapi.dll 
--> 
 8
            
<
add 
verb
="*"
 path
="*"
 type
="Dottext.Common.UrlManager.UrlReWriteHandlerFactory,Dottext.Common"
 
/> 
 9
        
</
httpHandlers
> 
10
        
<
httpModules
> 
11
            
<
add 
name
="UrlReWriteModule"
 type
="Dottext.Common.UrlManager.UrlReWriteModule, Dottext.Common"
 
/> 
12
            
<
add 
name
="EventHttpModule"
 type
="Dottext.Framework.ScheduledEvents.EventHttpModule, Dottext.Framework"
 
/> 
13
            
<!--
<add name="MsftBlogsHttpModule" type= "AspNetWeb.MsftBlogsHttpModule, MsftBlogsHttpModule" />
--> 
14
        
</
httpModules
> 
15
看看第11行,配置了
Dottext.Common.UrlManager.UrlReWriteModule这个httpModule,很显然,从名字来看,它就是实现urlrewrite功能的httpmodule,去看看它的源代码 
 1
        
static UrlReWriteModule() 
 2
ExpandedBlockStart.gif         { 
 3
            regexPath = 
new Regex(@"^/?(\w|-|_)+\.aspx$",RegexOptions.IgnoreCase|RegexOptions.Compiled); 
 4
            regexApplication = 
new Regex(HttpContext.Current.Request.ApplicationPath,RegexOptions.IgnoreCase|RegexOptions.Compiled); 
 5
        } 
 6
 
 7
        
private 
void context_BeginRequest(
object sender, EventArgs e) 
 8
ExpandedBlockStart.gif         { 
 9
            
if(ConfigProvider.Instance().IsAggregateSite) 
10
ExpandedSubBlockStart.gif            { 
11
                HttpContext context  = ((HttpApplication)sender).Context; 
12
 
13
                
string path = context.Request.Path.ToLower(); 
14
                
int iExtraStuff = path.IndexOf(".aspx"); 
15
                
if(iExtraStuff > -1 || path.IndexOf(".") == -1) 
16
ExpandedSubBlockStart.gif                { 
17
                    
if(iExtraStuff > -1) 
18
ExpandedSubBlockStart.gif                    { 
19
                        path = path.Remove(iExtraStuff+5,path.Length - (iExtraStuff+5)); 
20
                    } 
21
 
22
                    path = regexApplication.Replace(path,
string.Empty,1,0); 
23
 
24
                    
if(path == "" || path == "/"  || regexPath.IsMatch(path)) 
25
ExpandedSubBlockStart.gif                    { 
26
                        UrlHelper.SetEnableUrlReWriting(context,
false); 
27
                    } 
28
                     
29
                } 
30
                
else 
if(context.Request.Path.ToLower().IndexOf("services") > 0 && context.Request.Path.ToLower().IndexOf(".asmx") > 0 ) 
31
ExpandedSubBlockStart.gif                { 
32
                    
if(AlllowService(context)) 
33
ExpandedSubBlockStart.gif                    { 
34
                        
if(context.Request.RequestType!="POST") 
35
ExpandedSubBlockStart.gif                        { 
36
                            
string regexstr=@"/\w+/services/"; 
37
                            
string url=Regex.Replace(context.Request.RawUrl,regexstr,"/services/",RegexOptions.IgnoreCase); 
38
                            context.RewritePath(url); 
39
                        } 
40
                        
//
string fileName =context.Request; 
//
System.IO.Path.GetFileName(context.Request.Path); 
41
                        
//
context.RewritePath("~/Services/" + fileName);
 
42
                    } 
43
                    
else 
44
ExpandedSubBlockStart.gif                    { 
45
                        context.Response.Clear(); 
46
                        context.Response.End(); 
47
                    } 
48
                } 
49
             
50
            } 
51
        } 
52
代码有点长,不过没关系,结构还是很清晰的。用户发出的url请求,在context_BeginRequest中进行了第一次过滤,这个函数把url做了一下归整,判断来自用户的请求是 应用程序根目录下的.aspx文件,如果是则不进行urlrewrite(由UrlHelper.SetEnableUrlReWriting这个函数进行设置)。什么?看不懂regexPath = 
new Regex(@"^/?(\w|-|_)+\.aspx$",……); 这句话?建议你去看一下正则表达式,这里的意思是指,需要匹配的字符串所对应的文件是否在根目录下,举例来说, 
/contact.aspx 
default.aspx 
匹配,而 
 /oop80/default.aspx 
则不匹配, 
总而言之,context_BeginRequest函数把对根目录下.aspx文件的请求,以及webservice,设置成不需要进行urlrewrite,其余的,则需要进行下一步的处理,在什么地方处理呢,我们来看看web.config中的配置,第8行,很清晰的告诉我们,在
Dottext.Common.UrlManager.UrlReWriteHandlerFactory中,会对用户的请求做进一步分析和处理。 来看看源代码 
 1
public 
class UrlReWriteHandlerFactory:  IHttpHandlerFactory 
 2
ExpandedBlockStart.gif     { 
 3
ExpandedSubBlockStart.gif        
public UrlReWriteHandlerFactory(){} 
//
Nothing to do in the cnstr
 
 4
         
 5
        
protected 
virtual HttpHandler[] GetHttpHandlers(HttpContext context) 
 6
ExpandedSubBlockStart.gif        { 
 7
            
return HandlerConfiguration.Instance().HttpHandlers; 
 8
        } 
 9
 
10
ExpandedSubBlockStart.gif        
///
 
<summary>
 
11
        
///
 Implementation of IHttpHandlerFactory. By default, it will load an array of HttpHanlder (Dottext.UrlManager.HttpHandler) from 
12
        
///
 the blog.config. This can be changed, by overrideing the GetHttpHandlers(HttpContext context) method.  
13
        
///
 
</summary>
 
14
        
///
 
<param name="context">
Current HttpContext
</param>
 
15
        
///
 
<param name="requestType">
Request Type (Passed along to other IHttpHandlerFactory's)
</param>
 
16
        
///
 
<param name="url">
The current requested url. (Passed along to other IHttpHandlerFactory's)
</param>
 
17
        
///
 
<param name="path">
The physical path of the current request. Is not gaurenteed to exist (Passed along to other IHttpHandlerFactory's)
</param>
 
18
        
///
 
<returns>
 
19
        
///
 Returns an Instance of IHttpHandler either by loading an instance of IHttpHandler or by returning an other 
20
        
///
 IHttpHandlerFactory.GetHanlder(HttpContext context, string requestType, string url, string path) method 
21
        
///
 
</returns>
 
22
        
public 
virtual IHttpHandler GetHandler(HttpContext context, 
string requestType, 
string url, 
string path) 
23
ExpandedSubBlockStart.gif        { 
24
            
//
Get the Handlers to process. By defualt, we grab them from the blog.config 
25
            
//
Dottext.Framework.Logger.LogManager.Log("url",context.Request.Path);
 
26
            HttpHandler[] items = GetHttpHandlers(context); 
27
            
//
Dottext.Framework.Logger.LogManager.Log("path",Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath)); 
28
            
//
Do we have any?
 
29
            
if(items != 
null
30
ExpandedSubBlockStart.gif            { 
31
                
int count = items.Length; 
32
 
33
                
for(
int i = 0; i<count; i++) 
34
ExpandedSubBlockStart.gif                { 
35
                    
//
We should use our own cached Regex. This should limit the number of Regex's created 
36
                    
//
and allows us to take advantage of RegexOptons.Compiled 
 
37
                     
38
                    
if(items[i].IsMatch(Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath))) 
39
ExpandedSubBlockStart.gif                    { 
40
                        
//
throw new Exception();
 
41
                        
switch(items[i].HandlerType) 
42
ExpandedSubBlockStart.gif                        { 
43
                            
case HandlerType.Page:
//
默认是Page
 
44
                                                         
45
                                
return ProccessHandlerTypePage(items[i],context,requestType,url); 
46
                            
case HandlerType.Direct: 
47
                                HandlerConfiguration.SetControls(context,items[i].BlogControls); 
48
                                
return (IHttpHandler)items[i].Instance(); 
49
                            
case HandlerType.Factory: 
50
                                
//
Pass a long the request to a custom IHttpHandlerFactory
 
51
                                
return ((IHttpHandlerFactory)items[i].Instance()).GetHandler(context,requestType,url,path); 
52
                            
default
53
                                
throw 
new Exception("Invalid HandlerType: Unknown"); 
54
                        } 
55
                    } 
56
                } 
57
            } 
58
            
//
If we do not find the page, just let ASP.NET take over
 
59
            
return PageHandlerFactory.GetHandler(context,requestType,url, path); 
60
        } 
61
 
62
 
63
        
private IHttpHandler ProccessHandlerTypePage(HttpHandler item, HttpContext context, 
string requestType, 
string url) 
64
ExpandedSubBlockStart.gif        { 
65
            
string pagepath = item.FullPageLocation; 
66
            
if(pagepath == 
null
67
ExpandedSubBlockStart.gif            { 
68
                pagepath = HandlerConfiguration.Instance().FullPageLocation; 
69
            } 
70
            HandlerConfiguration.SetControls(context,item.BlogControls); 
71
            IHttpHandler myhandler=PageParser.GetCompiledPageInstance(url,pagepath,context); 
72
            
return myhandler; 
73
        } 
74
 
75
 
76
        
public 
virtual 
void ReleaseHandler(IHttpHandler handler)  
77
ExpandedSubBlockStart.gif        { 
78
 
79
        } 
80
    } 
81
代码很长,但是它是实现urlrewrite的关键,我们来分析分析看。 
UrlReWriteHandlerFactory实现了IHttpHandlerFactory接口,而IHttpHandlerFactory最关键的地方在于GetHandler这个函数接口,所以我们从GetHandler函数入手。 
首先是 HttpHandler [] items = GetHttpHandlers(context); 通过查看GetHttpHandlers的定义,可以得知返回的其实是HandlerConfiguration中一个叫HttpHandlers的属性,它的值,是通过这么一句话来进行初始化的,return ((HandlerConfiguration)ConfigurationSettings.GetConfig("HandlerConfiguration")); 想必大家现在都明白了,HandlerConfiguration对象是通过将web.config中<HandlerConfiguration>节进行反序列化获得的,关于ConfigurationSettings.GetConfig的使用,网上已经有很多了,在这里就不重复劳动了。看看web.config中的HandlerConfiguration节
 1
    
<
HandlerConfiguration 
defaultPageLocation
="default.aspx"
 type
="Dottext.Common.UrlManager.HandlerConfiguration, Dottext.Common"
>
 2
        
<
HttpHandlers
>
 3
            
<
HttpHandler 
pattern
="(\.config|\.asax|\.ascx|\.config|\.cs|\.vb|\.vbproj|\.asp|\.licx|\.resx|\.resources)$"
    type
="Dottext.Framework.UrlManager.HttpForbiddenHandler, Dottext.Framework"
 handlerType
="Direct"
 
/>
 4
            
<
HttpHandler 
pattern
="(\.gif|\.js|\.jpg|\.zip|\.jpeg|\.jpe|\.css|\.rar|\.xml|\.xsl)$"
 type
="Dottext.Common.UrlManager.BlogStaticFileHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
 5
            
<
HttpHandler 
pattern
="/rss\.aspx$"
 type
="Dottext.Common.Syndication.RssHandler, Dottext.Common"
    handlerType
="Direct"
 
/>
 6
            
<
HttpHandler 
pattern
="/CommentsRSS\.aspx$"
 type
="Dottext.Common.Syndication.RecentCommentsRSS, Dottext.Common"
 handlerType
="Direct"
 
/>
 7
            
<
HttpHandler 
pattern 
= "/RecentCommentsRSS\.aspx$"
 type 
= "Dottext.Common.Syndication.RecentCommentsRSS, Dottext.Common"
 handlerType 
= "Direct"
 
/>
 8
            
<
HttpHandler 
pattern
="/atom\.aspx$"
 type
="Dottext.Common.Syndication.AtomHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
 9
            
<
HttpHandler 
pattern
="/comments/commentRss/\d+\.aspx$"
 type
="Dottext.Common.Syndication.RssCommentHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
10
            
<
HttpHandler 
pattern
="/aggbug/\d+\.aspx$"
 type
="Dottext.Framework.Tracking.AggBugHandler, Dottext.Framework"
 handlerType
="Direct"
 
/>
11
            
<
HttpHandler 
pattern
="/customcss\.aspx$"
 type
="Dottext.Web.UI.Handlers.BlogSecondaryCssHandler, Dottext.Web"
 handlerType
="Direct"
 
/>
12
            
<
HttpHandler 
pattern
="/category\/(\d|\w|\s)+\.aspx/rss$"
 type
="Dottext.Common.Syndication.RssCategoryHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
13
            
<
HttpHandler 
pattern
="/favorite\/(\d|\w|\s)+\.aspx/rss$"
 type
="Dottext.Common.Syndication.RssLinksHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
14
            
<
HttpHandler 
pattern
="/articles/\d+\.aspx$"
 controls
="viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx"
 
/>
15
            
<
HttpHandler 
pattern
="/articles/\w+\.aspx$"
 controls
="viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx"
 
/>
16
            
<
HttpHandler 
pattern
="/PreviewPost.aspx$"
 controls
="PreviewPost.ascx"
 
/>
17
            
<
HttpHandler 
pattern
="/archive/\d{4}/\d{2}/\d{2}/\d+\.(aspx|htm)$"
 controls
="viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx"
 
/>
18
            
<
HttpHandler 
pattern
="/archive/\d{4}/\d{2}/\d{2}/\w+\.(aspx|htm)$"
 controls
="viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx"
 
/>
19
            
<
HttpHandler 
pattern
="/archive/\d{4}/\d{1,2}/\d{1,2}\.aspx$"
 controls
="ArchiveDay.ascx"
 
/>
20
            
<
HttpHandler 
pattern
="/archive/\d{4}/\d{1,2}\.aspx$"
 controls
="ArchiveMonth.ascx"
 
/>
21
            
<
HttpHandler 
pattern
="/archives/\d{4}/\d{1,2}\.aspx$"
 controls
="ArticleArchiveMonth.ascx"
 
/>
22
            
<
HttpHandler 
pattern
="/contact\.aspx$"
 controls
="Contact.ascx"
 
/>
23
            
<
HttpHandler 
pattern
="/AddToFavorite\.aspx$"
 handlerType
="Page"
 pageLocation
="AddToFavorite.aspx"
 
/>
24
            
<
HttpHandler 
pattern
="/BlogSearch\.aspx$"
 controls
="BlogSearch.ascx"
 
/>
25
            
<
HttpHandler 
pattern
="/posts/|/story/|/archive/"
 type
="Dottext.Web.UI.Handlers.RedirectHandler,Dottext.Web"
    handlerType
="Direct"
 
/>
26
            
<
HttpHandler 
pattern
="/gallery\/\d+\.aspx$"
 controls
="GalleryThumbNailViewer.ascx"
 
/>
27
            
<
HttpHandler 
pattern
="/gallery\/image\/\d+\.aspx$"
 controls
="ViewPicture.ascx"
 
/>
28
            
<
HttpHandler 
pattern
="/(?:category|stories)/(\w|\s)+\.aspx$"
 controls
="CategoryEntryList.ascx"
 
/>
29
            
<
HttpHandler 
pattern
="/favorite/(\w|\s)+\.aspx$"
 controls
="FavoriteList.ascx"
 
/>
30
            
<
HttpHandler 
pattern
="/(?:admin)"
 type
="Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web"
 handlerType
="Factory"
 
/>
31
            
<!--
<HttpHandler pattern = "^(?:\/(\w|\s|\.(?!aspx))+((\/login\.aspx)?|(\/?))?)$" type = "Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web" handlerType = "Factory" />
-->
32
            
<!--
<HttpHandler pattern = "^(?:/\w+\/(\w|\s|\.)+\/(?:admin|logout\.aspx|login\.aspx))" type = "Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web" handlerType = "Factory" />
-->
33
            
<
HttpHandler 
pattern
="/comments\/\d+\.aspx$"
 type
="Dottext.Common.Syndication.CommentHandler, Dottext.Common"
 handlerType
="Direct"
 
/>
34
            
<
HttpHandler 
pattern
="/services\/trackbacks/\d+\.aspx$"
 type
="Dottext.Framework.Tracking.TrackBackHandler, Dottext.Framework"
 handlerType
="Direct"
 
/>
35
            
<
HttpHandler 
pattern
="/services\/pingback\.aspx$"
 type
="Dottext.Framework.Tracking.PingBackService, Dottext.Framework"
    handlerType
="Direct"
 
/>
36
            
<
HttpHandler 
pattern
="/services\/metablogapi\.aspx$"
 type
="Dottext.Framework.XmlRpc.MetaWeblog, Dottext.Framework"
    handlerType
="Direct"
 
/>
37
            
<
HttpHandler 
pattern
="/Services\/SyncHanlder\.aspx$"
 handlerType
="Page"
 pageLocation
="Sevices/DottextAPI.aspx"
 
/>
38
            
<!--
 只显示文章标题列表 
-->
39
            
<!--
<HttpHandler pattern="^((/default\.aspx)|(/)|(/index\.aspx))$" controls="CategoryPostsList.ascx" />
-->
40
            
<!--
 显示文章内容 
-->
41
            
<
HttpHandler 
pattern
="^((/default\.aspx)|(/)|(/index\.aspx))$"
 controls
="PagedPosts.ascx"
 
/>
42
            
<
HttpHandler 
pattern
="^(/posts\.aspx)$"
 controls
="PagedPosts.ascx"
 
/>
43
            
<!--
<HttpHandler pattern = "/services/\w+.asmx$" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"  handlerType = "Factory" />
-->
44
            
<
HttpHandler 
pattern 
= "^(?:\/(\w|\s|\.(?!aspx))+((\/default\.aspx)?|(\/?))?)$"
  controls 
= "homepage.ascx"
/>
45
            
<!--
<HttpHandler pattern="^(?:/\w+\/(\w|\s|\.(?!aspx))+((\/default\.aspx)?|(\/?))?)$" controls="homepage.ascx" />
-->
46
            
47
        
</
HttpHandlers
>
48
    
</
HandlerConfiguration
>
49
其实在visual studio.net中看这段代码会更加清楚一点,这里的每一个pattern其实都会建立对应的Regex ,来对用户请求的url进行匹配,下面的代码会很详细说明这一点,我们往下看。
接下来是一个循环,循环中执行这么一句话
if (items[i].IsMatch(Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath))) {...}
它把web.config中每一个httphandler来匹配用户的请求,IsMatch函数中会根据pattern建立相应的Regex,并调用Regex.IsMatch函数,如果请求匹配该pattern,则调用对应的模块来进行处理。很显然,这里是实现urlrewrite的关键之处,比如,请求的是这么一个url 
那么,他就会匹配这一个handler
<HttpHandler pattern="/archive/\d{4}/\d{2}/\d{2}/\d+\.(aspx|htm)$" controls="viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx" />
那么,程序就会调用 viewpost.ascx,Comments.ascx,AnonymousPostComment.ascx,LoginPostComment.ascx 来处理用户的请求,
又如,请求这么一个url
匹配
<HttpHandler pattern="/(?:category|stories)/(\w|\s)+\.aspx$" controls="CategoryEntryList.ascx" />
最后程序是一个switch语句,根据handlertype的不同进行各种处理,具体就不在解释了,因为……这一段我自己也没有进行更深入一步的研究,里面还有一些细节,如SetControls的控件在什么地方载入,GetCompiledPageInstance函数的具体用法等等。不过,这些东西终归和urlrewrite没多大关系了,不在我们讨论的范围之内。
请大家多多指教,谢谢
欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 330987132 | Go:217696290 | Python:336880185 | 做人要厚道,转载请注明出处!http://www.cnblogs.com/sunshine-anycall/archive/2009/10/27/1590371.html
你可能感兴趣的文章
java 获取系统当前时间的方法
查看>>
Ubuntu 10.04升级git 到1.7.2或更高的可行方法
查看>>
Spring Security4实战与原理分析视频课程( 扩展+自定义)
查看>>
消息队列服务器 memcacheq的搭建
查看>>
VMware Horizon View 7.5 虚拟桌面实施咨询与购买--软件硬件解决方案
查看>>
RabbitMQ如何保证队列里的消息99.99%被消费?
查看>>
第一周博客作业
查看>>
thinkpython2
查看>>
String、StringBuffer和StringBuilder的区别
查看>>
oracle recyclebin与flashback drop
查看>>
svmlight使用说明
查看>>
Swing 和AWT之间的关系
查看>>
Mysql设置自增长主键的初始值
查看>>
Android计时器正确应用方式解析
查看>>
获取post传输参数
查看>>
ASP生成静态页面的方法
查看>>
mysql 权限
查看>>
HDU 1325 Is It A Tree? 判断是否为一棵树
查看>>
Shell命令-文件压缩解压缩之gzip、zip
查看>>
个人总结
查看>>