C# 即使路径中有百分比编码部分,如何可靠地获取实际URL?
IIS和ASP.NET(MVC)在处理路径中带有%编码的URL时(不是查询字符串;查询字符串可以)。我怎样才能避开这件事?i、 e.如何获取请求的实际URLC# 即使路径中有百分比编码部分,如何可靠地获取实际URL?,c#,asp.net,asp.net-mvc,iis,C#,Asp.net,Asp.net Mvc,Iis,IIS和ASP.NET(MVC)在处理路径中带有%编码的URL时(不是查询字符串;查询字符串可以)。我怎样才能避开这件事?i、 e.如何获取请求的实际URL 例如,如果我导航到/x%3Fa%3Db和(分别)导航到/x?a=b,它们都将.Request.Url报告为/x?a=b,因为路径中的编码数据报告不正确;URL变量包含一个解码值;QUERY\u字符串变量包含仍然编码的查询。我们不能只在URL部分调用encode,因为它也包含原始形式的/等-如果我们盲目地对整个内容进行编码,我们将得到不需要的
例如,如果我导航到
/x%3Fa%3Db
和(分别)导航到/x?a=b
,它们都将.Request.Url
报告为/x?a=b
,因为路径中的编码数据报告不正确;URL
变量包含一个解码值;QUERY\u字符串
变量包含仍然编码的查询。我们不能只在URL
部分调用encode,因为它也包含原始形式的/
等-如果我们盲目地对整个内容进行编码,我们将得到不需要的%2f
值;但是,您可以将其分离并发现问题案例:
private static readonly Regex simpleUrlPath = new Regex("^[-a-zA-Z0-9_/]*$", RegexOptions.Compiled);
private static readonly char[] segmentsSplitChars = { '/' };
// ^^^ avoids lots of gen-0 arrays being created when calling .Split
public static Uri GetRealUrl(this HttpRequest request)
{
if (request == null) throw new ArgumentNullException("request");
var baseUri = request.Url; // use this primarily to avoid needing to process the protocol / authority
try
{
var vars = request.ServerVariables;
var url = vars["URL"];
if (string.IsNullOrEmpty(url) || simpleUrlPath.IsMatch(url)) return baseUri; // nothing to do - looks simple enough even for IIS
var query = vars["QUERY_STRING"];
// here's the thing: url contains *decoded* values; query contains *encoded* values
// loop over the segments, encoding each separately
var sb = new StringBuilder(url.Length * 2); // allow double to be pessimistic; we already expect trouble
var segments = url.Split(segmentsSplitChars);
foreach (var segment in segments)
{
if (segment.Length == 0)
{
if(sb.Length != 0) sb.Append('/');
}
else if (simpleUrlPath.IsMatch(segment))
{
sb.Append('/').Append(segment);
}
else
{
sb.Append('/').Append(HttpUtility.UrlEncode(segment));
}
}
if (!string.IsNullOrEmpty(query)) sb.Append('?').Append(query); // query is fine; nothing needing
return new Uri(baseUri, sb.ToString());
}
catch (Exception ex)
{ // if something unexpected happens, default to the broken ASP.NET handling
GlobalApplication.LogException(ex);
return baseUri;
}
}
虽然这种想法很受欢迎,但StackOverflow不是一个片段站点,也不是一个发布你想出来的东西的地方,比如博客。你的问题和答案的时间戳表明你已经准备好在这里发布这两个问题。请只发布您真正需要帮助的问题。有更合适的方式与社区共享信息。@Chris。允许回答作为提问的一部分的决定也是非常有意的——代码是非常有意地添加的。我知道:我在那个团队工作。此外,在我修复了一个错误后,这个代码已经作为请求的一部分由用户在“meta”上共享。Tl;博士:回答你自己的问题是明确可以的,只要问题和答案是正确的和适当的。