Compartilhar via


Classe System.Uri

Este artigo fornece comentários complementares à documentação de referência para esta API.

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

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

Os construtores Uri 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 de escape, com todos os caracteres com valores Unicode maiores que 127 substituídos por seus equivalentes hexadecimal. Para colocar o URI em forma canônica, o Uri construtor executa as seguintes etapas:

  • Converte o esquema de URI em letras minúsculas.
  • Converte o nome do host em letras 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 de 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 porcentagem) que não têm uma finalidade reservada são decodificados (também conhecidos como sem escape). Esses 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 bloco (%7E).
  • Canonicaliza o caminho para URIs hierárquicas compactando sequências como /./ e /../, independentemente de a sequência estar ou não escapada. Observe que há alguns esquemas para os quais essas sequências não são compactadas.
  • Para URIs hierárquicas, 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 o RFC 2396. Esse comportamento muda se a análise de Identificadores de Recursos Internacionais ou de Nomes de Domínios Internacionais estiver ativada, caso em que os caracteres reservados no URI são escapados de acordo com a RFC 3986 e a RFC 3987.

Como parte da canonicalização no construtor para alguns esquemas, os segmentos de ponto (/./ e /../) são compactados (em outras palavras, removidos). Os esquemas para os quais Uri compacta segmentos 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 na prática. As sequências com escape são desescapadas, 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 conteúdo da classe Uri de uma referência de URI codificada para escape para uma referência de URI legível usando o método ToString. Observe que alguns caracteres reservados ainda podem ser escapados na saída do método ToString. Isso é para dar suporte à reconstrução inequívoca de um URI do valor retornado por ToString.

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

Observação

A classe URI dá suporte ao uso de endereços IP em quad-notation para protocolo IPv4 e colon-hexadecimal para protocolo IPv6. Lembre-se de colocar o endereço IPv6 entre colchetes, como em http://[::1].

Suporte ao identificador de recursos internacionais

Os endereços da Web normalmente 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 no RFC 2396, RFC 2732, RFC 3986 e RFC 3987 publicados pela IETF (Internet Engineering Task Force).

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 IRIs (Identificadores de Recursos Internacionais). As especificações para IRIs estão documentadas no RFC 3987 publicado pelo IETF. O uso de IRIs permite que uma URL contenha caracteres Unicode.

No .NET Framework 4.5 e versões posteriores, a IRI está sempre habilitada e não pode ser alterada 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 IDN (Nome de Domínio Internacionalizado) 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 em seus equivalentes Punycode. Os nomes punycode contêm apenas caracteres ASCII e sempre começam com o prefixo xn--. O motivo para isso é dar suporte a servidores DNS existentes na Internet, já que a maioria dos servidores DNS dá suporte apenas a caracteres ASCII (consulte RFC 3940).

Habilitar 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 que são usados:

  • idn habilitado = Todos

    Converte todos os nomes de domínio Unicode em seus equivalentes punycode (nomes IDN).

  • idn habilitado = AllExceptIntranet

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

  • idn habilitado = Nenhum

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

A normalização e a verificação de caracteres são feitas de acordo com as regras de IRI mais recentes 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 System.Configuration.IriParsingElement configuração habilita ou desabilita o processamento de IRI na Uri classe. A System.Configuration.IdnElement configuração habilita ou desabilita o processamento de IDN na Uri classe.

A definição da configuração das classes System.Configuration.IriParsingElement e System.Configuration.IdnElement é lida uma vez quando a classe System.Uri é construída pela primeira vez. As alterações nas configurações após esse horário são ignoradas.

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

O tipo GenericUriParserOptions.Idn indica que o analisador oferece suporte à análise de IDN (Internationalized Domain Name) de nomes de host. No .NET 5 e versões posteriores (incluindo .NET Core) e .NET Framework 4.5+, o IDN é sempre usado. Em versões anteriores, uma opção de configuração determina se o IDN é usado.

Suporte ao caminho do arquivo implícito

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 estão em conformidade com a especificação de 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, pois um caminho de arquivo implícito absoluto é indistinguível de um caminho relativo. Quando essa ambiguidade está presente, Uri o padrão é interpretar o caminho como um URI absoluto.

Considerações de segurança

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

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

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\");

Considerações sobre desempenho

Se você usar um arquivo Web.config que contém URIs para inicializar seu aplicativo, será necessário tempo adicional para processar as URIs se os identificadores de esquema não estiverem padrão. Nesse caso, inicialize as partes afetadas do aplicativo quando as URIs forem necessárias, não na hora de início.