Получение URL-адреса с косой чертой с URL-адресом
Я хочу отправить HTTP GET на http://example.com/%2F
. Мое первое предположение было бы примерно таким:
using (WebClient webClient = new WebClient())
{
webClient.DownloadData("http://example.com/%2F");
}
К сожалению, я вижу, что на самом деле отправлено на провод:
GET // HTTP/1.1
Host: example.com
Connection: Keep-Alive
Итак http://example.com/%2F переводится в http://example.com// перед ее передачей.
Есть ли способ отправить этот GET-запрос?
Протокол OCSP обязывает отправлять url-кодировку кодировки base-64 при использовании OCSP через HTTP/GET, поэтому необходимо отправить фактический% 2F, а не "/", который должен быть совместимым.
EDIT:
Вот соответствующая часть стандарта протокола OCSP (RFC 2560 Приложение A.1.1):
Запрос OCSP с использованием метода GET строится следующим образом:
GET {url}/{url-кодирование кодировки базового 64 кодирования DER для OCSPRequest}
Я очень открыт для других чтений этого, но я не вижу, что еще можно сказать.
Ответы
Ответ 1
По умолчанию класс Uri
не разрешает экранированный символ /
(%2f
) в URI (даже если это выглядит допустимым в моем чтении RFC 3986).
Uri uri = new Uri("http://example.com/%2F");
Console.WriteLine(uri.AbsoluteUri); // prints: http://example.com//
(Примечание: не используйте Uri.ToString для печати URI.)
Согласно отчету об ошибке для этой проблемы в Microsoft Connect, такое поведение является заданным, но вы можете обойти это, добавив следующее в файл app.config или web.config:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
(Перенесено из fooobar.com/questions/92315/..., потому что это "официальный" способ избежать этой ошибки без использования отражения для изменения приватных полей.)
Изменить: Отчет об ошибке подключения больше не отображается, но в документации для <schemeSettings>
рекомендуется использовать этот подход, чтобы разрешить экранированные символы /
в URI. Обратите внимание (согласно этой статье), что могут быть последствия для безопасности для компонентов, которые неправильно обрабатывают экранированные косые черты.
Ответ 2
Это ужасный хак, который должен быть несовместим с будущими версиями фреймворка и так далее.
Но это работает!
(на моей машине...)
Uri uri = new Uri("http://example.com/%2F");
ForceCanonicalPathAndQuery(uri);
using (WebClient webClient = new WebClient())
{
webClient.DownloadData(uri);
}
void ForceCanonicalPathAndQuery(Uri uri){
string paq = uri.PathAndQuery; // need to access PathAndQuery
FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
flags &= ~((ulong) 0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
flagsFieldInfo.SetValue(uri, flags);
}
Ответ 3
Обновление по этому вопросу: похоже, что поведение по умолчанию класса Uri на самом деле было изменено в .NET 4.5, и теперь вы можете использовать сбегающие косые черты, и они не будут затронуты.
Я выполнил следующий код в .NET 3.5,.NET 4.0,.NET 4.5/4.5.1
static void Main(string[] args)
{
var uri = new Uri("http://www.yahooo.com/%2F");
var client = new WebClient();
client.DownloadString(uri);
}
В .NET 3.5/4.0 трассировка показывает, что% 2F фактически не был отображен, как ожидалось.
![Fiddler trace]()
Однако, в .NET 4.5/4.5.1 вы можете видеть, что% 2F не был unescaped (обратите внимание на GET/% 2F)
![Fiddler trace]()
Вы можете даже использовать ToString() теперь на Uri, и вы получите тот же результат.
Итак, в заключение, оно появляется, если вы используете .NET > =.NET 4.5, тогда все будет вести себя так, как они должны встраиваться в RFC.
Я просто изучил попытку добиться того же подхода, который работал над Mono. Я разместил свой вопрос о подходе здесь: Получение Uri с экранированными косыми чертами в моно
Ответ 4
Как упомянуто в моем комментарии к ответу, опубликованному Рамусом, для того, чтобы .Net Standard (и, возможно, более поздние версии .Net Framework), чтобы этот взлом работал, требуется следующее:
Uri uri = new Uri("http://example.com/%2F");
ForceCanonicalPathAndQuery(uri);
using (WebClient webClient = new WebClient())
{
webClient.DownloadData(uri);
}
void ForceCanonicalPathAndQuery(Uri uri){
string paq = uri.PathAndQuery; // need to access PathAndQuery
FieldInfo flagsFieldInfo = typeof(Uri).GetField("_flags", BindingFlags.Instance | BindingFlags.NonPublic);
ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
flags &= ~((ulong) 0xC30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
flagsFieldInfo.SetValue(uri, flags);
}
Ответ 5
Двойной код: % 252F
Но также, если вы используете HttpWebRequest, вы можете сказать не кодировать URL-адрес, как он должен работать.
Также, если WebClient принимает URI, вы можете создать новый URI, и вы можете установить его, чтобы он не кодировался.