Caracteres seguros para o URL amigável [fechado]

168

Preciso criar um site que contenha artigos e gostaria de criar URLs amigáveis, como o URL da página com

Título: Artigo Teste

deve tornar-se: http://www.example.com/articles/article_test.

É claro que preciso remover alguns caracteres do título, como ?or #, mas não tenho certeza de quais remover.

Alguém pode me dizer quais caracteres são seguros para manter?

Paulo
fonte
Havia uma pergunta semelhante aqui . Confira, você pode encontrar algumas respostas úteis também (existem muitas).
Rook

Respostas:

210

Para citar a seção 2.3 da RFC 3986 :

"Os caracteres permitidos em um URI, mas que não têm um objetivo reservado, são chamados sem reserva. Eles incluem letras maiúsculas e minúsculas, dígitos decimais, hífen, ponto, sublinhado e til."

ALPHA  DIGIT  "-" / "." / "_" / "~"

Observe que o RFC 3986 lista menos sinais de pontuação reservados que o RFC 2396 mais antigo .

Pular Cabeça
fonte
@Skip Head, "caracteres" incluem caracteres latinos codificados como çe õ?
Mohamad
6
@ Mohamad: Não, apenas ASCII, embora o suporte ao UTF-8 esteja melhorando.
Dietrich Epp
@ Dietrich Epp, obrigado. Eu acho que não importa se o URL é para decoração e SEO fins, como: www.mysite.com/[postId]/post-title-with-ç-and-õ
Mohamad
1
@ Mohamad: A última parte será alterada para baixo post-title-with-%C3%A7-and-%C3%B5, mas ainda será exibida na barra de localização do usuário como post-title-with-ç-and-õ.
precisa
7
Seus leitores são portugueses, portanto, use caracteres portugueses.
Dietrich Epp
107

Há dois conjuntos de caracteres que você precisa observar: reservado e não seguro .

Os caracteres reservados são:

  • e comercial ("&")
  • dólar ("$")
  • sinal de adição ("+")
  • vírgula (",")
  • barra ("/")
  • dois pontos (":")
  • ponto e vírgula (";")
  • igual a ("=")
  • ponto de interrogação ("?")
  • Símbolo 'At' ("@")
  • libra ("#").

Os personagens geralmente considerados inseguros são:

  • espaço ("")
  • menor que e maior que ("<>")
  • abrir e fechar colchetes ("[]")
  • abrir e fechar chaves ("{}")
  • pipe ("|")
  • barra invertida ("\")
  • acento circunflexo ("^")
  • por cento ("%")

Eu posso ter esquecido um ou mais, o que me leva a ecoar a resposta de Carl V. A longo prazo, provavelmente é melhor usar uma "lista branca" de caracteres permitidos e depois codificar a sequência em vez de tentar ficar a par dos caracteres que não são permitidos pelos servidores e sistemas.

Gary.Ray
fonte
#é um caractere reservado usado para indicadores em uma página específica, criado por ter um elemento HTML com um atributo de nome ou atributo de id correspondente (sans- #symbol).
TheLonelyGhost
Obrigado - atualizei a resposta.
precisa saber é o seguinte
Ponto de interrogação aparece aqui como tanto reservado e inseguro - Penso nele como só reservado, mas posso estar errado
Jonathan Basile
6
Outros parecem discordar de que o til ~é inseguro. Você tem certeza que é?
DRS
3
A lista de permissões não é tão boa se estiver lidando com idiomas diferentes do inglês. O Unicode apenas possui muitos pontos de código OK. Portanto, a lista negra dos inseguros provavelmente será a mais fácil de implementar em expressões regulares.
Patanjali
41

É melhor manter apenas alguns caracteres (lista de permissões) em vez de remover determinados caracteres (lista negra).

Tecnicamente, você pode permitir qualquer caractere, desde que o codifique corretamente. Mas, para responder no espírito da pergunta, você deve permitir apenas esses caracteres:

  1. Letras minúsculas (converter maiúsculas em minúsculas)
  2. Números, 0 a 9
  3. Um traço - ou sublinhado _
  4. Tilde ~

Tudo o resto tem um significado potencialmente especial. Por exemplo, você pode pensar que pode usar +, mas pode ser substituído por um espaço. & também é perigoso, especialmente se estiver usando algumas regras de reescrita.

Como nos outros comentários, consulte os padrões e especificações para obter detalhes completos.

carl
fonte
15
Um pré-período, descobri hoje, é uma má escolha de caractere para usar em um codificador Base64 seguro para URL, porque haverá aqueles casos raros em que seus dados codificados podem produzir dois pontos consecutivos (".."), o que é significativo em que se refere ao diretório pai.
pohl
5
@pohl: isso é apenas um problema se o seu URL for usado como um caminho de arquivo, no seu código ou se o servidor da Web tentar mapear o URL para os arquivos antes de encaminhar a solicitação para um script (infelizmente muito comum).
André Caron
4
Na verdade, no nosso caso, usá-lo como um caminho de arquivo seria bom, já que nos arquivos unix é permitido ter vários e até consecutivos pontos em seus nomes. Para nós, o problema surgiu em uma ferramenta de monitoramento chamada Site Scope, que possui um bug (talvez um regex ingênuo) e estava relatando falsos períodos de inatividade falsos. Para nós, estamos presos a uma versão antiga do Site Scope, a equipe de administração se recusa a pagar por uma atualização e um cliente muito importante tem o Site Scope (não equivalente) escrito em seu contrato. É certo que a maioria não se encontra no meu lugar.
Pohl
8
Graças a Deus que alguém postou uma lista sem muita tagarelice. Quanto ao ponto (.) - como o @pohl disse, não o use! Aqui está outro caso estranho no IIS (não sei se isso acontece em outros servidores da Web): se estiver no final do seu URL, você provavelmente receberá um erro 404 (ele tentará procurar por [/ pagename] )
nikib3ro
34

Sempre seguro

Estes são seguros (em teoria / especificação), basicamente em qualquer lugar, exceto no nome de domínio.
Codifique por cento tudo o que não estiver listado e você estará pronto.

    A-Z a-z 0-9 - . _ ~ ( ) ' ! * : @ , ;

Às vezes seguro

Somente seguro quando usado em componentes de URL específicos; use com cuidado.

    Paths:     + & =
    Queries:   ? /
    Fragments: ? / # + & =
    

Never Safe

De acordo com a especificação do URI (RFC 3986), todos os outros caracteres devem ser codificados em porcentagem. Isso inclui:

    <space> <control-characters> <extended-ascii> <unicode>
    % < > [ ] { } | \ ^
    

Se a compatibilidade máxima for uma preocupação, limite o conjunto de caracteres para AZ az 0-9 - _.
(com pontos apenas para extensões de nome de arquivo).

Mantenha o contexto em mente

Mesmo se válido por especificação, um URL ainda pode ser "inseguro", dependendo do contexto. Como um arquivo: /// URL que contém caracteres de nome de arquivo inválidos ou um componente de consulta que contém "?", "=" E "&" quando não usado como delimitador. O tratamento correto desses casos geralmente depende de seus scripts e pode ser contornado, mas é algo a ter em mente.

Beejor
fonte
Você poderia fornecer alguma fonte para sua segunda reivindicação ("Às vezes segura")? Em particular, acredito que você está errado ao dizer que =não é seguro para consultas. Por exemplo, o FIQL aceita sinais de igual e se descreve como "amigável ao URI" e "otimizado e destinado ao uso no componente de consulta". Na minha interpretação, o RFC 3986 permite explicitamente "=", "&", "+" e outros em consultas.
26419 DanielM
@DanielM "?", "=" E "&" são válidos em consultas por especificação, embora na prática sejam amplamente utilizados para analisar pares nome-valor na consulta. Portanto, eles podem ser inseguros como parte dos próprios nomes / valores. Se isso constitui ou não "inseguro" pode ser uma questão de opinião.
Beejor
Algumas fontes, conforme solicitado. (1) RFC 3986, Seção 3.4: "os [...] componentes de consulta costumam ser usados ​​para transportar informações de identificação na forma de pares 'chave = valor'" [...] "(2) WhatWG URL Spec, Sec. 6.2: "Construir e restringir um objeto URLSearchParams é bastante simples: [...] params.toString() // "key=730d67"" (3) Manual do PHP, http-build-query: "Gere uma string de consulta codificada em URL. [...] O exemplo acima mostrará: 0=foo&1=bar[...]"(4) J. Starr, Perishable Press:" Ao criar páginas da Web, muitas vezes é necessário adicionar links que exijam cadeias de consulta parametrizadas. "
Beejor
@ Bee: estou construindo um URL e uso '-' e ';' durante a construção. Não é um aplicativo da web, mas um aplicativo móvel. Não sou desenvolvedor da Web e, portanto, eu estaria seguro se usasse os dois caracteres acima na propriedade Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Esses são caracteres de URL válidos. Embora se usado para fazer referência a caminhos em um sistema de arquivos local, lembre-se de que alguns sistemas não permitem certos caracteres nos nomes de arquivos. Por exemplo, "arquivo: /// caminho / para / meu: arquivo.ext" seria inválido no Mac.
Beejor
17

Olhando para RFC3986 - Identificador Uniforme de Recursos (URI): sintaxe genérica , sua pergunta gira em torno do componente de caminho de um URI.

    foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
      |   _____________________|__
     / \ /                        \
     urn:example:animal:ferret:nose

Citando a seção 3.3, os caracteres válidos para um URI segmentsão do tipo pchar:

pchar = não reservado / codificado em pct / subdimensões / ":" / "@"

Que se divide em:

ALPHA / DIGIT / "-" / "." / "_" / "~"

pct-encoded

"!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

":" / "@"

Ou em outras palavras: Você pode usar qualquer caractere (não-controle-) da tabela ASCII , exceto / , ?, #, [e ].

Esse entendimento é apoiado pelo RFC1738 - URLs (Uniform Resource Locators) .

Philzen
fonte
2
Este é um ótimo exemplo de uma resposta teoricamente correta, que causa problemas quando aplicada ao mundo real em que realmente vivemos. É verdade que a maioria desses personagens não causará problemas na maioria das vezes. Mas existem no mundo real coisas como proxies, roteadores, gateways, relés etc., todos os quais "adoram" inspecionar e interagir com URLs de maneiras que desconsideram o padrão teórico. Para evitar essas armadilhas, você se limita a escapar de tudo, exceto alfanuméricos, traço, sublinhado e ponto final.
deltamind106
1
@ deltamind106 Você pode fornecer exemplos e / ou referências para esclarecer quais desses caracteres são seguros de acordo com as RFCs? Prefiro me ater aos fatos apoiados pelos padrões em minha resposta, e fico feliz em atualizar minha resposta se você puder identificar quaisquer fatos que eu possa ter negligenciado.
Philzen
2
@ deltamind106 Eu sugiro que tentemos fazer com que os produtos sigam os padrões, em vez de dizer aos desenvolvedores que não sigam. Considero seu aviso merecido, mas devemos fazer a nossa parte no relatório de não conformidade aos fornecedores, se necessário.
Lo-Tan
@ Philzen: Estou construindo uma URL e uso '-' e ';' durante a construção. Não é um aplicativo da web, mas um aplicativo móvel. Não sou desenvolvedor da Web e, portanto, eu estaria seguro se usasse os dois caracteres acima na propriedade Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@ karsnen Sim, é claro -e ;é seguro, é isso que minha resposta e a RFC afirma claramente.
Philzen
12

não reservado = ALPHA / DIGIT / "-" / "." / "_" / "~"

LKK
fonte
3
"ALPHA" não implica "DIGIT"? Presumo que ALPHA é a abreviação de "alfanumérico" e alfanumérico significa maiúsculas, minúsculas e dígitos.
Luc
11
Na verdade, alfa não implica alfanumérico. Alfa e numérico são duas coisas distintas e alfanumérico é a combinação dessas coisas. Ele poderia ter escrito sua resposta assim: ALPHANUMERIC / "-" / "." / "_" / "~"
MacroMan
1
A notação ABNF para 'não reservado' no RFC 3986 os lista separadamente.
Patanjali
11

No contexto que você descreve, suspeito que o que você está realmente tentando fazer é algo chamado de 'lesma de SEO'. A melhor prática conhecida geral para aqueles é:

  1. Converter em minúsculas
  2. Converter seqüências inteiras de caracteres que não sejam az e 0-9 em um hífen (-) (não sublinhado)
  3. Remova 'stop words' do URL, ou seja, palavras não indexáveis ​​como 'a', 'an' e 'the'; Google 'stop words' para listas extensas

Assim, como exemplo, um artigo intitulado "O uso de! @% $ * Para representar palavrões nos quadrinhos" receberia uma porção de "uso-representa-palavrões-quadrinhos".

caos
fonte
É realmente uma boa abordagem remover essas "palavras de parada" do URL? Os mecanismos de pesquisa penalizariam um site por causa disso?
Paulo
Acredita-se que os mecanismos de pesquisa geralmente reconheçam apenas uma parte do URL e / ou reduzam o significado a partes posteriores. Portanto, ao remover palavras de parada, o que você está fazendo é maximizar o número de palavras-chave incorporadas ao URL e ter a chance de realmente classificar.
caos
1
@chaos Você ainda recomenda remover o StopWord, se levar em conta o seguinte: seobythesea.com/2008/08/google-stopword-patent Além disso, você pode recomendar uma boa lista de palavras irrelevantes ? Esta é a melhor lista que eu encontrei até agora - link-assistant.com/seo-stop-words.html
nikib3ro
@ kape123 Isso não parece uma lista muito boa para mim. "c" e "d" são linguagens de programação, e muitas dessas outras palavras também parecem significativas. Eu provavelmente tiraria os básicos: a, e, é, on, of, or, the, with.
MPEN
6

O formato para um URI é definido no RFC 3986 . Veja a seção 3.3 para detalhes.

joschi
fonte
6

De uma perspectiva de SEO, os hífens são preferidos aos sublinhados. Converta em minúsculas, remova todos os apóstrofos e substitua todas as seqüências de caracteres não alfanuméricas por um único hífen. Apare o excesso de hífens no início e no final.

mpen
fonte
3

Eu tive um problema semelhante, queria ter urls bonitos e cheguei à conclusão de que tenho de permitir apenas letras, dígitos e _ e urls. Tudo bem, então eu escrevi um bom regex e percebi que ele reconhece que todos os caracteres UTF8 não são letras no .NET e foi ferrado. Este parece ser um problema conhecido para o mecanismo de regex do .NET. Então eu cheguei a esta solução:

private static string GetTitleForUrlDisplay(string title)
{
    if (!string.IsNullOrEmpty(title))
    {
        return Regex.Replace(Regex.Replace(title, @"[^A-Za-z0-9_-]", new MatchEvaluator(CharacterTester)).Replace(' ', '-').TrimStart('-').TrimEnd('-'), "[-]+", "-").ToLower();
    }
    return string.Empty;
}


/// <summary>
/// All characters that do not match the patter, will get to this method, i.e. useful for unicode chars, because
/// .NET impl of regext do not handle unicode chars. So we use char.IsLetterOrDigit() which works nicely and we 
/// return what we approve and return - for everything else.
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
private static string CharacterTester(Match m)
{
    string x = m.ToString();
    if (x.Length > 0 && char.IsLetterOrDigit(x[0]))
    {
        return x.ToLower();
    }
    else
    {
        return "-";
    }
}
Lubomir Toshev
fonte
3
Regexes .NET suportam unicode muito bem, na verdade. Você precisa usar classes de caracteres unicode, por exemplo, \ p {L} para todas as letras. Consulte msdn.microsoft.com/en-us/library/20bw873z.aspx#CategoryOrBlock
TheCycoONE
1

Achei muito útil codificar meu URL para um URL seguro quando eu retornava um valor através do ajax / php para um URL que era lido pela página novamente.

Saída PHP com codificador de URL para o caractere especial &

//PHP returning the sucess info of ajax request
echo "".str_replace('&','%26',$_POST['name'])." category was changed";

//javascript sending the value to url
window.location.href='time.php?return=updated&val='+msg;

//javascript/php executing the function printing the value of the url,
//now with the text normally lost in space because of the reserved & character.

setTimeout("infoApp('updated','<?php echo $_GET['val'];?>');",360);

Espero que alguém ache meu pequeno extrato de código útil! :)

DIY-Forum
fonte
0

Acho que você está procurando algo como "Codificação de URL" - codificando um URL para que seja "seguro" usar na Web:

Aqui está uma referência para isso. Se você não deseja caracteres especiais, basta remover os que requerem codificação de URL:

http://www.w3schools.com/TAGS/ref_urlencode.asp

Andy White
fonte
-4

Entre 3-50 caracteres. Pode conter letras minúsculas, números e caracteres especiais - ponto (.), Traço (-), sublinhado (_) e com a taxa (@).

Ramji
fonte
4
Alguma referência para isso?
dakab 23/02