Как создать экземпляр Uri, проанализированный с GenericUriParserOptions. DontCompressPath

Когда.NET System.Uri класс анализирует строки, он выполняет некоторую нормализацию на входе, таком как печатание строчными литерами схемы и имени хоста. Это также обрезает запаздывание периодов от каждого сегмента контура. Эта последняя функция является фатальной для приложений OpenID, потому что некоторые OpenIDs (как выпущенные от Yahoo) включают закодированные сегменты контура base64, которые могут закончиться периодом.

Как я могу отключить это обрезающее период поведение класса Uri?

Регистрация моего собственного использования схемы UriParser.Register с синтаксическим анализатором, инициализированным с GenericUriParserOptions.DontCompressPath избегает периода, обрезая и некоторых других операций, которые являются также нежелательным для OpenID. Но я не могу зарегистрировать новый синтаксический анализатор для существующих схем как HTTP и HTTPS, который я должен сделать для OpenIDs.

Другой подход, который я попробовал, регистрировал мою собственную новую схему и программировал пользовательский синтаксический анализатор для возврата схемы к стандартным схемам HTTP как часть парсинга:

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's 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.

Я рад за любое решение что:

  1. Сохраняет запаздывание периодов в сегментах контура в Uri.Path
  2. Включает эти периоды в исходящие Запросы HTTP.
  3. Идеально работы с под доверием носителя ASP.NET (но не абсолютно необходимый).
17
задан Andrew Arnott 25 March 2010 в 13:39
поделиться

4 ответа

Microsoft заявляет, что это будет исправлено в .NET 4.0 (хотя из комментариев видно, что это еще не исправлено)

https: // connect.microsoft.com/VisualStudio/feedback/details/386695/system-uri-incorrectly-strips-trailing-dots?wa=wsignin1.0#tabs

Однако на этой странице есть обходной путь. Однако он включает использование отражения для изменения параметров, поэтому он может не соответствовать требованию среднего доверия. Просто прокрутите вниз и нажмите вкладку «Временные решения».

Спасибо jxdavis и Google за этот ответ:

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/5206beca-071f-485d-a2bd-657d635239c9

5
ответ дан 30 November 2019 в 14:38
поделиться

Мне любопытно, если часть проблемы заключается в том, что вы учитываете только «не сжимать путь», вместо всех значений по умолчанию базового парсера HTTP: (включая UnEscapeDotsAndSlashes)

  private const UriSyntaxFlags HttpSyntaxFlags = (UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.AllowIdn | UriSyntaxFlags.UnEscapeDotsAndSlashes | UriSyntaxFlags.CanonicalizeAsFilePath | UriSyntaxFlags.CompressPath | UriSyntaxFlags.ConvertPathSlashes | UriSyntaxFlags.PathIsRooted | UriSyntaxFlags.AllowAnInternetHost | UriSyntaxFlags.AllowUncHost | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHavePath | UriSyntaxFlags.MayHavePort | UriSyntaxFlags.MayHaveUserInfo | UriSyntaxFlags.MustHaveAuthority);

Это в отличие от новостей, в которых есть флаги (например):

 private const UriSyntaxFlags NewsSyntaxFlags = (UriSyntaxFlags.AllowIriParsing | UriSyntaxFlags.MayHaveFragment | UriSyntaxFlags.MayHavePath);

Черт, Брэндон Блэк опередил меня, пока я печатал что-то вверх ...

Это может улучшить читаемость кода:

namespace System 
{
    [Flags]
    internal enum UriSyntaxFlags
    {
        AllowAnInternetHost = 0xe00,
        AllowAnyOtherHost = 0x1000,
        AllowDnsHost = 0x200,
        AllowDOSPath = 0x100000,
        AllowEmptyHost = 0x80,
        AllowIdn = 0x4000000,
        AllowIPv4Host = 0x400,
        AllowIPv6Host = 0x800,
        AllowIriParsing = 0x10000000,
        AllowUncHost = 0x100,
        BuiltInSyntax = 0x40000,
        CanonicalizeAsFilePath = 0x1000000,
        CompressPath = 0x800000,
        ConvertPathSlashes = 0x400000,
        FileLikeUri = 0x2000,
        MailToLikeUri = 0x4000,
        MayHaveFragment = 0x40,
        MayHavePath = 0x10,
        MayHavePort = 8,
        MayHaveQuery = 0x20,
        MayHaveUserInfo = 4,
        MustHaveAuthority = 1,
        OptionalAuthority = 2,
        ParserSchemeOnly = 0x80000,
        PathIsRooted = 0x200000,
        SimpleUserSyntax = 0x20000,
        UnEscapeDotsAndSlashes = 0x2000000,
        V1_UnknownUri = 0x10000
    }
}
2
ответ дан 30 November 2019 в 14:38
поделиться

Это работает?

public class MyUriParser : UriParser
{
private string actualScheme;

public MyUriParser(string actualScheme)
{
    Type type = this.GetType();
    FieldInfo fInfo = type.BaseType.GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
    fInfo.SetValue(this, 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's in there. 
    if ((components & UriComponents.Scheme) != 0)
    {
        string registeredScheme = base.GetComponents(uri, UriComponents.Scheme, format);
        result = this.actualScheme + result.Substring(registeredScheme.Length);
    }

    return result;
}}
1
ответ дан 30 November 2019 в 14:38
поделиться

Вы должны быть в состоянии избежать "." используя "% 2E", но это дешевый и грязный выход.

Вы можете попробовать немного поиграть с опцией dontEscape , и это может изменить то, как Ури обращается с этими персонажами.

Дополнительная информация здесь: http://msdn.microsoft.com/en-us/library/system.uri.aspx

Также проверьте следующее (см. DontUnescapePathDotsAndSlashes): { {1}} http: // msdn.microsoft.com/en-us/library/system.genericuriparseroptions.aspx

1
ответ дан 30 November 2019 в 14:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: