Когда класс .NET System.Uri
анализирует строки, он выполняет некоторую нормализацию на входе, например, нижнюю оболочку схемы и имя хоста. Он также обрезает периоды возврата из каждого сегмента пути. Эта последняя функция является фатальной для приложений OpenID, потому что некоторые OpenID (например, выпущенные из Yahoo) включают в себя сегменты пути с кодировкой base64, которые могут заканчиваться периодом.
Как отключить это поведение обрезки в классе Uri?
Регистрация моей собственной схемы с помощью UriParser.Register
с синтаксическим анализатором, инициализированным с помощью GenericUriParserOptions.DontCompressPath
, позволяет избежать обрезки периода и некоторых других операций, которые также нежелательны для OpenID. Но я не могу зарегистрировать новый парсер для существующих схем, таких как HTTP и HTTPS, которые я должен сделать для OpenID.
Другой подход, который я пробовал, - это зарегистрировать мою собственную новую схему и программировать пользовательский парсер, чтобы изменить схему на стандартные схемы HTTP (s) как часть разбора:
public class MyUriParser : GenericUriParser
{
private string actualScheme;
public MyUriParser(string actualScheme)
: base(GenericUriParserOptions.DontCompressPath)
{
this.actualScheme = actualScheme.ToLowerInvariant();
}
protected override string GetComponents(Uri uri, UriComponents components, UriFormat format)
{
string result = base.GetComponents(uri, components, format);
// Substitute our actual desired scheme in the string if it in there.
if ((components & UriComponents.Scheme) != 0)
{
string registeredScheme = base.GetComponents(uri, UriComponents.Scheme, format);
result = this.actualScheme + result.Substring(registeredScheme.Length);
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
UriParser.Register(new MyUriParser("http"), "httpx", 80);
UriParser.Register(new MyUriParser("https"), "httpsx", 443);
Uri z = new Uri("httpsx://me.yahoo.com/b./c.#adf");
var req = (HttpWebRequest)WebRequest.Create(z);
req.GetResponse();
}
}
Это практически работает. Экземпляр Uri
сообщает https вместо httpsx всюду - кроме самого свойства Uri.Scheme. Это проблема, когда вы передаете этот экземпляр Uri
в HttpWebRequest
для отправки запроса на этот адрес. По-видимому, он проверяет свойство Scheme и не распознает его как "https", потому что он просто отправляет открытый текст в 443-порт вместо SSL.
Я рад за любое решение, которое:
- Сохраняет конечные периоды в сегментах пути в
Uri.Path
- Включает эти периоды в исходящие HTTP-запросы.
- В идеале работает с поддержкой среднего уровня ASP.NET(но не обязательно).