Classe System.Uri

Observação

Este artigo fornece observações complementares à documentação de referência para esta API.

Um identificador de recurso uniforme (URI) é uma representação compacta de um recurso disponível para seu aplicativo na intranet ou na Internet. A Uri classe define as propriedades e os métodos para manipular URIs, incluindo análise, comparação e combinação. As propriedades da classe Uri são somente de leitura; para criar um objeto modificável, use a classe UriBuilder.

Os URIs relativos (por exemplo, "/new/index.htm") devem ser expandidos em relação a um URI de base para que sejam absolutos. O MakeRelativeUri método é fornecido para converter URIs absolutos em URIs relativos quando necessário.

Os Uri construtores não escapam de cadeias de caracteres de URI se a cadeia de caracteres for um URI bem formado, incluindo um identificador de esquema.

As Uri propriedades retornam uma representação de dados canônica na codificação com escape, com todos os caracteres com valores Unicode maiores que 127 substituídos por seus equivalentes hexadecimais. Para colocar o URI na forma canônica, o Uri construtor executa as seguintes etapas:

  • Converte o esquema de URI em minúsculas.
  • Converte o nome do host em minúsculas.
  • Se o nome do host for um endereço IPv6, o endereço IPv6 canônico será usado. ScopeId e outros dados IPv6 opcionais são removidos.
  • Remove números de porta padrão e vazios.
  • Converte caminhos de arquivo implícitos sem o esquema file:// (por exemplo, "C:\my\file") em caminhos de arquivo explícitos com o esquema file://.
  • Os caracteres com escape (também conhecidos como octetos codificados por percentagem) que não têm uma finalidade reservada são descodificados (também conhecidos como não escapados). Estes caracteres não reservados incluem letras maiúsculas e minúsculas (%41-%5A e %61-%7A), dígitos decimais (%30-%39), hífen (%2D), ponto (%2E), sublinhado (%5F) e til (%7E).
  • Canonicaliza o caminho para URIs hierárquicas compactando sequências como /./ e /../ (quer a sequência esteja escapada ou não). Observe que existem alguns esquemas para os quais essas sequências não são compactadas.
  • Para URIs hierárquicos, se o host não for encerrado com uma barra (/), uma será adicionada.
  • Por padrão, todos os caracteres reservados no URI são escapados de acordo com a RFC 2396. Esse comportamento muda se os identificadores de recursos internacionais ou a análise de nome de domínio internacional estiverem habilitados, caso em que os caracteres reservados no URI são codificados de acordo com as RFCs 3986 e 3987.

Como parte da canonicalização no construtor para alguns esquemas, os segmentos de pontos (/./ e /../) são compactados (em outras palavras, eles são removidos). Os esquemas para os quais os segmentos de Uri são compactados incluem http, https, tcp, net.pipe e net.tcp. Para alguns outros esquemas, essas sequências não são compactadas. O trecho de código a seguir mostra como a compactação parece na prática. As sequências escapadas são desfeitas, se necessário, e depois compactadas.

var uri = new Uri("http://myUrl/../.."); // http scheme, unescaped
OR
var uri = new Uri("http://myUrl/%2E%2E/%2E%2E"); // http scheme, escaped
OR
var uri = new Uri("ftp://myUrl/../.."); // ftp scheme, unescaped
OR
var uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E"); // ftp scheme, escaped

Console.WriteLine($"AbsoluteUri: {uri.AbsoluteUri}");
Console.WriteLine($"PathAndQuery: {uri.PathAndQuery}");

Quando esse código é executado, ele retorna uma saída semelhante ao texto a seguir.

AbsoluteUri: http://myurl/
PathAndQuery: /

Você pode transformar o Uri conteúdo da classe de uma referência de URI codificada de escape para uma referência de URI legível usando o ToString método. Observe que alguns caracteres reservados ainda podem ser escapados na saída do ToString método. Isso é para dar suporte à reconstrução inequívoca de um URI a partir do valor retornado pelo ToString.

Alguns URIs incluem um identificador de fragmento ou uma consulta ou ambos. Um identificador de fragmento é qualquer texto que segue um sinal numérico (#), não incluindo o sinal numérico; O texto do fragmento Fragment é armazenado na propriedade. As informações da consulta são qualquer texto que segue um ponto de interrogação (?) no URI; o texto da consulta é armazenado na propriedade Query.

Observação

A classe URI suporta o uso de endereços IP em notação quad para protocolo IPv4 e dois pontos-hexadecimais para protocolo IPv6. Lembre-se de colocar o endereço IPv6 entre colchetes, como em http://[::1].

Suporte a identificadores de recursos internacionais

Os endereços da Web geralmente são expressos usando URIs que consistem em um conjunto muito restrito de caracteres:

  • Letras ASCII maiúsculas e minúsculas do alfabeto inglês.
  • Dígitos de 0 a 9.
  • Um pequeno número de outros símbolos ASCII.

As especificações para URIs estão documentadas em RFC 2396, RFC 2732, RFC 3986 e RFC 3987 publicadas pela Internet Engineering Task Force (IETF).

Os identificadores que facilitam a necessidade de identificar recursos usando idiomas diferentes do inglês e permitem caracteres não-ASCII (caracteres no conjunto de caracteres Unicode/ISO 10646) são conhecidos como Identificadores de Recursos Internacionais (IRIs). As especificações para IRIs estão documentadas no RFC 3987 publicado pela IETF. O uso de IRIs permite que uma URL contenha caracteres Unicode.

No .NET Framework 4.5 e versões posteriores, o IRI está sempre habilitado e não pode ser alterado usando uma opção de configuração. Você pode definir uma opção de configuração no machine.config ou no arquivo app.config para especificar se deseja que a análise de nome de domínio internacionalizado (IDN) seja aplicada ao nome de domínio. Por exemplo:

<configuration>
  <uri>
    <idn enabled="All" />
  </uri>
</configuration>

Habilitar o IDN converte todos os rótulos Unicode em um nome de domínio para seus equivalentes Punycode. Os nomes Punycode contêm apenas caracteres ASCII e sempre começam com o prefixo xn-. A razão para isso é suportar servidores DNS existentes na Internet, uma vez que a maioria dos servidores DNS suporta apenas caracteres ASCII (consulte RFC 3940).

A ativação do IDN afeta o valor da propriedade Uri.DnsSafeHost. Habilitar o IDN também pode alterar o comportamento dos métodos Equals, OriginalString, GetComponents e IsWellFormedOriginalString.

Há três valores possíveis para IDN, dependendo dos servidores DNS usados:

  • IDN ativado = Todos

    Converte quaisquer nomes de domínio Unicode para seus equivalentes Punycode (nomes IDN).

  • idn ativado = AllExceptIntranet

    Converte todos os nomes de domínio Unicode que não estão na Intranet local para usar os equivalentes Punycode (nomes IDN). Nesse caso, para lidar com nomes internacionais na Intranet local, os servidores DNS usados para a Intranet devem oferecer suporte à resolução de nomes Unicode.

  • idn ativado = Não

    Nenhum nome de domínio Unicode é convertido para usar Punycode. Este é o valor padrão.

A normalização e a verificação de caracteres são feitas de acordo com as regras mais recentes do IRI no RFC 3986 e RFC 3987.

O processamento de IRI e IDN na classe Uri também pode ser controlado usando as classes de configuração System.Configuration.IriParsingElement, System.Configuration.IdnElement e System.Configuration.UriSection. A definição System.Configuration.IriParsingElement ativa ou desativa o processamento de IRI na classe Uri. A configuração System.Configuration.IdnElement habilita ou desativa o processamento de IDN na classe Uri.

A definição de configuração para o System.Configuration.IriParsingElement e System.Configuration.IdnElement são lidas uma vez quando a primeira classe System.Uri é instanciada. As alterações nas definições de configuração após esse período são ignoradas.

A System.GenericUriParser classe também foi estendida para permitir a criação de um analisador personalizável que suporta IRI e IDN. O comportamento de um objeto System.GenericUriParser é especificado passando uma combinação bit a bit dos valores disponíveis na enumeração System.GenericUriParserOptions para o construtor System.GenericUriParser. O GenericUriParserOptions.IriParsing tipo indica que o analisador suporta as regras de análise especificadas no RFC 3987 for International Resource Identifiers (IRI).

O GenericUriParserOptions.Idn tipo indica que o analisador suporta a análise de nomes de anfitrião em domínios internacionalizados (IDN). No .NET 5 e versões posteriores (incluindo o .NET Core) e no .NET Framework 4.5+, o IDN é sempre usado. Em versões anteriores, uma opção de configuração determina se o IDN é usado.

Suporte implícito a caminhos de arquivos

Uri também pode ser usado para representar caminhos do sistema de arquivos local. Esses caminhos podem ser representados explicitamente em URIs que começam com o esquema file:// e implicitamente em URIs que não têm o esquema file://. Como um exemplo concreto, os dois URIs a seguir são válidos e representam o mesmo caminho de arquivo:

Uri uri1 = new Uri("C:/test/path/file.txt") // Implicit file path.
Uri uri2 = new Uri("file:///C:/test/path/file.txt") // Explicit file path.

Esses caminhos de arquivo implícitos não são compatíveis com a especificação URI e devem ser evitados quando possível. Ao usar o .NET Core em sistemas baseados em Unix, os caminhos de arquivo implícitos podem ser especialmente problemáticos, porque um caminho de arquivo implícito absoluto é indistinguível de um caminho relativo. Quando essa ambiguidade estiver presente, Uri o padrão será interpretar o caminho como um URI absoluto.

Considerações de segurança

Devido a preocupações de segurança, seu aplicativo deve ter cuidado ao aceitar Uri instâncias de fontes não confiáveis e com dontEscape definido como true no construtor. Você pode verificar a validade de uma cadeia de caracteres URI chamando o IsWellFormedOriginalString método.

Ao lidar com entradas de usuário não confiáveis, confirme as suposições sobre a instância recém-criada Uri antes de confiar em suas propriedades. Isto pode ser feito da seguinte forma:

string userInput = ...;

Uri baseUri = new Uri("https://myWebsite/files/");

if (!Uri.TryCreate(baseUri, userInput, out Uri newUri))
{
    // Fail: invalid input.
}

if (!baseUri.IsBaseOf(newUri))
{
    // Fail: the Uri base has been modified - the created Uri is not rooted in the original directory.
}

Essa validação pode ser usada em outros casos, como ao lidar com caminhos UNC, simplesmente alterando o baseUri:

Uri baseUri = new Uri(@"\\host\share\some\directory\name\");

Para mais detalhes sobre as considerações de design e segurança de Uri e UriBuilder, consulte os seguintes documentos de modelos de ameaça:

Considerações sobre desempenho

Se você usar um arquivo Web.config que contenha URIs para inicializar seu aplicativo, será necessário tempo adicional para processar os URIs se seus identificadores de esquema não forem padrão. Nesse caso, inicialize as partes afetadas da sua aplicação quando os identificadores URI forem necessários, não ao iniciar a aplicação.