ПОЛУЧЕНИЕ 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, а не '/', чтобы быть совместимым.
РЕДАКТИРОВАТЬ:
Вот соответствующая часть стандарта протокола OCSP ( RFC 2560, Приложение A.1.1):
Запрос OCSP с использованием метода GET строится следующим образом:
GET {url} / {url-кодировка кодировки base-64 кодировки DER для OCSPRequest}
Я очень открыт для других прочтений этого, но я не могу понять, что еще можно сказать.
4 ответа
По умолчанию 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>
(Перепечатано с /questions/934549/c-webrequestgetresponse-400-nevernyij-zapros/934555#934555 потому что это "официальный" способ избежать этой ошибки без использования отражения для изменения приватных полей.)
Изменить: отчет об ошибке подключения больше не отображается, но документация для <schemeSettings>
рекомендует этот подход, чтобы разрешить сбежал /
символы в URI. Обратите внимание (согласно этой статье), что могут быть последствия для безопасности компонентов, которые неправильно обрабатывают экранированные косые черты.
Это ужасный хак, неизбежно несовместимый с будущими версиями фреймворка и так далее.
Но это работает!
(на моей машине...)
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);
}
Обновление: похоже, поведение класса 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 фактически был неэкранированным, как ожидалось.
Тем не менее, в.NET 4.5 / 4.5.1 вы можете видеть, что%2F не был неэкранированным (обратите внимание на GET /%2F)
Теперь вы можете даже использовать ToString() в Uri, и вы получите тот же результат.
Итак, в заключение, кажется, что если вы используете.NET >= .NET 4.5, то все будет вести себя так, как должно соответствовать RFC.
Я только что попытался использовать тот же подход, работая с Mono. Я отправил свой вопрос о подходе здесь: Получение Uri с экранированными косыми чертами на моно
Как упоминалось в моем комментарии к ответу, опубликованному Рамусом, для.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);
}
Двойное кодирование: % 252F
Но также, если вы используете HttpWebRequest, вы можете запретить кодировать URL-адрес, так как он должен работать.
Кроме того, если WebClient принимает URI, вы можете создать новый URI и установить его, чтобы он не кодировался.