Fixing an issue with output parameters that are of type IntPtr
[castle.git] / MonoRail / Castle.MonoRail.Framework / RoutingModule.cs
blob3111106e022f6dfe1d7bd3de1712ab39494aa15d
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework
17 using System;
18 using System.Collections;
19 using System.Web;
20 using Castle.MonoRail.Framework.Configuration;
22 /// <summary>
23 /// Provides routing basic services in response to rules defined in
24 /// <see cref="MonoRailConfiguration.RoutingRules"/>.
25 /// <remarks>
26 /// This class delegates the resolving of the path that will be evaluated
27 /// to derivided classes.
28 /// </remarks>
29 /// </summary>
30 public class RoutingModule : IHttpModule
32 internal static readonly String OriginalPathKey = "rails.original_path";
33 private IList routingRules;
35 /// <summary>
36 /// Initializes a module and prepares it to handle requests.
37 /// </summary>
38 /// <param name="context">An <see cref="T:System.Web.HttpApplication"></see> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param>
39 public void Init(HttpApplication context)
41 context.BeginRequest += OnBeginRequest;
43 routingRules = MonoRailConfiguration.GetConfig().RoutingRules;
46 /// <summary>
47 /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"></see>.
48 /// </summary>
49 public void Dispose()
53 /// <summary>
54 /// Called when [begin request].
55 /// </summary>
56 /// <param name="sender">The sender.</param>
57 /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
58 private void OnBeginRequest(object sender, EventArgs e)
60 if (routingRules.Count == 0) return;
62 HttpContext context = HttpContext.Current;
63 HttpRequest request = context.Request;
65 String newPath;
67 String sourcePath = GetSourcePath();
69 SaveOriginalPath(context, sourcePath);
71 if (FindMatchAndReplace(sourcePath, out newPath))
73 // Handle things differently depending on wheter we need
74 // to keep a query string or not
76 int queryStringIndex = newPath.IndexOf('?');
78 if (queryStringIndex == -1)
80 context.RewritePath(newPath);
82 else
84 String path = newPath.Substring(0, queryStringIndex);
85 String queryString = newPath.Substring(queryStringIndex + 1);
86 context.RewritePath(path, request.PathInfo, queryString);
91 /// <summary>
92 /// Gets the source path.
93 /// </summary>
94 /// <returns></returns>
95 protected static string GetSourcePath()
97 if (ShouldUseHostAndPath)
99 return GetHostNameAndPath();
101 else if (ExcludeAppPath)
103 return GetPathWithoutAppPath();
105 else
107 return GetPath();
111 private static bool ShouldUseHostAndPath
113 get { return MonoRailConfiguration.GetConfig().MatchHostNameAndPath; }
116 private static bool ExcludeAppPath
118 get { return MonoRailConfiguration.GetConfig().ExcludeAppPath; }
121 private static string GetHostNameAndPath()
123 HttpContext context = HttpContext.Current;
124 HttpRequest request = context.Request;
126 String host = request.Headers["host"];
128 if (String.IsNullOrEmpty(host))
130 return request.FilePath;
132 else
134 return host + request.FilePath;
138 private static string GetPathWithoutAppPath()
140 //if ApplicationPath.Length == 1 then it must be "/" which we don't want to remove
142 string appPath = HttpContext.Current.Request.ApplicationPath;
143 string filePath = HttpContext.Current.Request.FilePath;
145 return (appPath.Length == 1) ? filePath : filePath.Remove(0, appPath.Length);
148 private static string GetPath()
150 return HttpContext.Current.Request.FilePath;
153 private bool FindMatchAndReplace(String currentPath, out String newPath)
155 newPath = String.Empty;
157 foreach(RoutingRule rule in routingRules)
159 if (rule.CompiledRule.IsMatch(currentPath))
161 newPath = rule.CompiledRule.Replace(currentPath, rule.Replace);
163 //Append the query string
164 String queryString = HttpContext.Current.Request.Url.Query;
166 if (queryString.Length > 0)
168 //If we already have some query string params on the new path...
169 bool hasParams = (newPath.LastIndexOf("?") != -1);
171 if (hasParams)
173 //...make sure we append the query string nicely rather than adding another ?
174 queryString = queryString.Replace("?", "&");
177 newPath += queryString;
180 if (ExcludeAppPath)
182 string appPath = HttpContext.Current.Request.ApplicationPath;
184 if (appPath.Length > 1)
186 newPath = appPath + newPath;
190 return true;
194 return false;
197 /// <summary>
198 /// Returns the original path
199 /// (before rewriting occured), or <c>null</c>
200 /// if rewriting didn't occur on this request.
201 /// </summary>
202 public static String OriginalPath
206 HttpContext context = HttpContext.Current;
208 if (context.Items.Contains(OriginalPathKey))
210 return context.Items[OriginalPathKey] as String;
213 return null;
217 private static void SaveOriginalPath(HttpContext context, String virtualPath)
219 context.Items.Add(OriginalPathKey, virtualPath);