如果我在.Net Core 3.1中这样做:
await new HttpClient().GetAsync("http://test.com/page?parameter=%2D%2E%5F%2E%2D");
然后发生这种情况:
GET http://test.com/page?parameter=-._.- HTTP/1.1
但这是我想要的:
GET http://test.com/page?parameter=%2D%2E%5F%2E%2D HTTP/1.1
[背景是我从第三方获得了一个已签名的网址,我需要按原样使用该网址,且不能转义。我设法用未转义的url找到资源,但是签名检查在另一端失败,因为他们在请求中看到的url不是已签名的url。
我可以将URL粘贴到任何浏览器中并获取资源,但是当我在.Net Core 3.1中以编程方式进行操作时,签名检查失败。
根据documentation on the Uri Class,不可避免的逃生发生:
不转义的转义字符(也称为百分比编码的八位字节)具有保留用途的被解码(也称为未转义)。这些未保留的字符包括大写和小写字母(%41-%5A和%61-%7A),十进制数字(%30-%39),连字符(%2D),句点(%2E),下划线(%5F)和波浪号(%7E)。
我已经尝试了以下问题列出的解决方案:
GETting a URL with an url-encoded slash。但是schemeSetting
似乎不适用于.Net Core 3.1,解决方法ForceCanonicalPathAndQuery
也无效。
How to make System.Uri not to unescape %2f (slash) in path?。同样,schemeSetting
似乎不适用于.Net Core 3.1,解决方法LeaveDotsAndSlashesEscaped
也无效。
所以,有人知道我如何在.Net Core 3.1上原样使用未转义的签名URL?
所以经过一番摆弄之后,我想到了这个:
private static Uri CreateNonUnescapedUri(string url)
{
// Initiate Uri as e.g "http://test.com" so internal flags will indicate that the url does not include characters that needs unescaping
int offset = url.IndexOf("://");
offset = url.IndexOf('/', offset + 4);
var uri = new Uri(url.Substring(0, offset));
// Then replace internal field with complete url that would otherwise be unescaped
typeof(Uri).GetField("_string", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(uri, url);
return uri;
}
我在300个签名的url上进行了测试。
当然,在将来改变Uri的内部状态(5600行纯疯狂状态,注定会失败,但是我需要在星期一之前完成此工作,这就是我所得到的。让我知道是否有人有真正的解决方案。