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?



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

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.


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

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;

0

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

res.redirect("/signin?email="+encodeURIComponent("aaa+bbb-ccc@example.com"));


> encodeURIComponent("http://a.com/a+b/c")
'http%3A%2F%2Fa.com%2Fa%2Bb%2Fc'

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>

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"

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.