Получение 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, и вы можете установить его, чтобы он не кодировался.