Um `+` em um esquema de URL / host / caminho representa um espaço?

224

Estou ciente de que um +na cadeia de consulta de um URL representa um espaço. Este também é o caso fora da região da string de consulta? Ou seja, faz o seguinte URL:

http://a.com/a+b/c

realmente representam:

http://a.com/a b/c

(e, portanto, precisa ser codificado se realmente for a +), ou será que realmente representa a+b/c?

Francisco Ryan Tolmasky I
fonte
4
Note que no php urldecode decodifica o% 2b (codificado +) para um espaço. Para evitar esse uso rawurldecode. Digo isso aqui para referência, porque este é um resultado bem classificado na pesquisa do google por "php url decode breaks on plus symbol".
Danielson317 31/03
1
Possível duplicata de Quando codificar espaço para mais (+) ou% 20?
usuário

Respostas:

170
  • A porcentagem de codificação na seção de caminho de um URL deve ser decodificada, mas
  • +espera-se que qualquer caractere no componente de caminho seja tratado literalmente.

Para ser explícito: +é apenas um caractere especial no componente de consulta.

Stobor
fonte
12
+1 Infelizmente, muitos "codificadores / codificadores de URL" disponíveis no mercado não entendem isso. Por exemplo, sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy
11
@ Stobor: citação necessária.
bukzor
8
@Stobor O RFC já declarou que o +caractere é interpretado como um espaço no componente de consulta? Ou é simplesmente uma regra "do nada"?
Pacerier
44
@Pacerier e @bukzor: a RFC 1738 (modificada por 2396 e 3986) define o esquema ( http:), a autoridade ( //server.example.com) e o caminho ( /myfile/mypage.htm), e não define nenhum significado especial para o +personagem. A especificação HTML define o componente de consulta como tipo mime application / x-www-form-urlencoded, que é definido como "substituir espaços por +e outros caracteres especiais como no RFC1738". Portanto, não é "do nada", mas é de um padrão aceito (não RFC).
Stobor
2
O método .NET Server.UrlEncodecodifica erroneamente os espaços como pontos positivos na parte do caminho, violando as regras HTTP.
Suncat2000
243

Você pode encontrar uma boa lista de caracteres codificados em URL correspondentes no W3Schools .

  • + torna-se %2B
  • o espaço se torna %20
Niels R.
fonte
18
É perfeitamente legal que caracteres '+' literais apareçam no componente do caminho em uma URL.
Sam Stainsby
4
Para que um + literal seja recebido pelo back-end (ou pelo menos PHP), ele deve ser codificado três vezes:%25252B
Umbrella
11
Esta resposta é completamente irrelevante para a pergunta.
Nisse Engström
22

Os caracteres de espaço podem ser codificados apenas como "+" em um contexto: pares de valores-chave application / x-www-form-urlencoded.

A RFC-1866 (especificação HTML 2.0), parágrafo 8.2.1. o parágrafo 1. diz: "Os nomes e valores dos campos do formulário são escapados: caracteres de espaço são substituídos por` + 'e caracteres reservados são escapados ").

Aqui está um exemplo de uma string no URL em que o RFC-1866 permite espaços de codificação como vantagens: " http://example.com/over/there?name=foo+bar ". Portanto, somente após "?", Os espaços podem ser substituídos por vantagens (em outros casos, os espaços devem ser codificados para% 20). Essa maneira de codificar dados de formulário também é fornecida em especificações HTML posteriores, por exemplo, procure parágrafos relevantes sobre application / x-www-form-urlencoded na especificação HTML 4.01 e assim por diante.

Mas, como é difícil sempre determinar corretamente o contexto, é a melhor prática nunca codificar espaços como "+". É melhor codificar em porcentagem todos os caracteres, exceto "não reservado", definido na RFC-3986, p.2.3. Aqui está um exemplo de código que ilustra o que deve ser codificado. É fornecida na linguagem de programação Delphi (pascal), mas é muito fácil entender como funciona para qualquer programador, independentemente da linguagem possuída:

(* percent-encode all unreserved characters as defined in RFC-3986, p.2.3 *)
function UrlEncodeRfcA(const S: AnsiString): AnsiString;
const    
  HexCharArrA: array [0..15] of AnsiChar = '0123456789ABCDEF';
var
  I: Integer;
  c: AnsiChar;
begin
 // percent-encoding, see RFC-3986, p. 2.1
  Result := S;
  for I := Length(S) downto 1 do
  begin
    c := S[I];
    case c of
      'A' .. 'Z', 'a' .. 'z', // alpha
      '0' .. '9',             // digit
      '-', '.', '_', '~':;    // rest of unreserved characters as defined in the RFC-3986, p.2.3
      else
        begin
          Result[I] := '%';
          Insert('00', Result, I + 1);
          Result[I + 1] := HexCharArrA[(Byte(C) shr 4) and $F)];
          Result[I + 2] := HexCharArrA[Byte(C) and $F];
        end;
    end;
  end;
end;

function UrlEncodeRfcW(const S: UnicodeString): AnsiString;
begin
  Result := UrlEncodeRfcA(Utf8Encode(S));
end;
Maxim Masiutin
fonte
0

use a função encodeURIComponent para corrigir o URL, ele funciona no navegador e no node.js

res.redirect("/signin?email="+encodeURIComponent("[email protected]"));


> encodeURIComponent("http://a.com/a+b/c")
'http%3A%2F%2Fa.com%2Fa%2Bb%2Fc'
Baryon Lee
fonte
1
Isso não aborda a questão. E, codifica incorretamente URLs, com um idioma específico (JavaScript) - dependendo do contexto, você provavelmente não deseja codificar onde precisa de barras especiais (não literais) (/) e dois pontos (:) para que o URL funcione .
Gremio
Graças realmente me ajudou!
Qwsd
-2

Tente abaixo:

<script type="text/javascript">

function resetPassword() {
   url: "submitForgotPassword.html?email="+fixEscape(Stringwith+char);
}
function fixEscape(str)
{
    return escape(str).replace( "+", "%2B" );
}
</script>
The Java Guy
fonte
2
Acho muito estranho que duas pessoas votem nessa resposta. Literalmente, nada tem a ver com a pergunta.
Andrew Barber
1
Que tal para outros caracteres * @ - _ +. /
Ravi
1
@AndrewBarber Por que você achou irrelevante? + torna-se% 2B
O cara Java
Isso está errado por muitos motivos ... escapeestá obsoleto. Em vez disso, você deve usar encodeURIou no caso da parte da consulta encodeURIComponent. Além disso, a cadeia de parâmetros deve codificar de acordo com w3c .
Christoph
-5

Você sempre deve codificar URLs.

Aqui está como o Ruby codifica seu URL:

irb(main):008:0> CGI.escape "a.com/a+b"
=> "a.com%2Fa%2Bb"
Lennart Koopmann
fonte
8
Não tenho certeza se está certo. De acordo com o RFC2396 ( ietf.org/rfc/rfc2396.txt ), os pontos positivos não são caracteres reservados no caminho (segmentos) do URI, apenas o componente de consulta. Isso parece implicar que eles não precisam ser codificados por URL e, portanto, não devem ser interpretados como espaços no caminho, apenas na consulta.
tlrobinson
3
A RFFC 1738, no entanto, trata vantagens como espaços. Tudo depende do que é implementado pelas suas funções de codificação / decodificação. por exemplo, em php, rawurlencode segue RFC 1738 enquanto urlencode segue RFC 2396.
Jonathan Fingland
1
Veja, agora eu tenho alguma confusão adicional. No exemplo que você me deu acima, a.com% 2Fa% 2Bb não é o que eu quero, seria no mínimo a.com/a%2Bb. Este é um URL real com o qual estou lidando, e não um URL que está sendo passado como parâmetro em uma string de consulta. Para um pouco de esclarecimento que pode ajudar a esclarecer, o Mac OS X Finder está retornando os URLs do sistema de arquivos para mim. Portanto, se eu tiver um arquivo chamado "a? + B.txt", ele retornará algo parecido com "file: //a%3F+b.txt", NOT "file: //a%3F%2B.txt" . O localizador está incorreto ou é um + antes da string de consulta realmente um plus?
Francisco Ryan Tolmasky I
2
Jonathan: Você tem certeza que 1738 diz que + está reservado? Entendo: safe = "$" | "-" "_" "." | "+" não reservado = alfa | dígito | seguro | extra e também: portanto, apenas alfanuméricos, os caracteres especiais "$ -_. +! * '()" e os caracteres reservados usados ​​para fins reservados podem ser usados ​​sem codificação em um URL.
tlrobinson
2
"Sempre escaparás" precisa de mais qualificação, e a resposta é irrelevante para a pergunta de qualquer maneira.
bug