¿Un `+` en un esquema de URL / host / ruta representa un espacio?

224

Soy consciente de que un +en la cadena de consulta de una URL representa un espacio. ¿Es este también el caso fuera de la región de la cadena de consulta? Es decir, hace la siguiente URL:

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

en realidad representan:

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

(y, por lo tanto, debe codificarse si realmente debería ser a +), ¿o en realidad representa a+b/c?

Francisco Ryan Tolmasky I
fuente
44
Tenga en cuenta que en php urldecode decodifica% 2b (codificado +) en un espacio. Para evitar este uso rawurldecode. Digo esto aquí como referencia porque este es un resultado de alta calificación en la búsqueda de Google para "php url decode breaks on plus symbol".
danielson317
1
Posible duplicado de Cuándo codificar espacio a más (+) o% 20?
usuario

Respuestas:

170
  • Se espera que se decodifique el porcentaje de codificación en la sección de ruta de una URL, pero
  • cualquier +caracteres en el componente de trazado se espera que sea tratada literalmente.

Para ser explícito: +es solo un carácter especial en el componente de consulta.

Stobor
fuente
12
+1 Desafortunadamente, muchos "codificadores / codificadores de URL" en la naturaleza no entienden esto. Por ejemplo, sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy
11
@Stobor: cita requerida.
bukzor
8
@Stobor ¿El RFC alguna vez declaró que el +carácter se interpreta como un espacio en el componente de consulta? ¿O es simplemente una regla "de la naturaleza"?
Pacerier
44
@Pacerier y @bukzor: RFC 1738 (modificado por 2396 y 3986) define el componente de esquema ( http:), autoridad ( //server.example.com) y ruta ( /myfile/mypage.htm), y no define ningún significado especial para el +personaje. La especificación HTML define el componente de consulta para que sea de tipo mime application / x-www-form-urlencoded, que se define como "reemplazar espacios con +y otros caracteres especiales como en RFC1738". Por lo tanto, no es "de la naturaleza", sino de un estándar aceptado (no RFC).
Stobor
2
El método .NET Server.UrlEncodecodifica erróneamente espacios como ventajas en la porción de ruta también, violando las reglas HTTP.
Suncat2000
243

Puede encontrar una buena lista de caracteres codificados con URL correspondientes en W3Schools .

  • + se convierte %2B
  • el espacio se convierte %20
Niels R.
fuente
18
Es perfectamente legal que aparezcan caracteres '+' literales en el componente de ruta en una URL.
Sam Stainsby
44
Para obtener un + literal para ser recibido por el back-end (o, al menos PHP) tiene que estar codificado triplemente:%25252B
Umbrella
11
Esta respuesta es completamente irrelevante para la pregunta.
Nisse Engström
22

Los caracteres de espacio solo se pueden codificar como "+" en un contexto: pares de clave-valor de application / x-www-form-urlencoded.

El RFC-1866 (especificación HTML 2.0), párrafo 8.2.1. el subpárrafo 1. dice: "Se escapan los nombres y valores de los campos de formulario: los caracteres de espacio se reemplazan por '+', y luego se escapan los caracteres reservados").

Aquí hay un ejemplo de una cadena de este tipo en URL donde RFC-1866 permite codificar espacios como ventajas: " http://example.com/over/there?name=foo+bar ". Por lo tanto, solo después de "?", Los espacios se pueden reemplazar por más (en otros casos, los espacios se deben codificar en% 20). Esta forma de codificar datos de formulario también se proporciona en especificaciones HTML posteriores, por ejemplo, busque párrafos relevantes sobre application / x-www-form-urlencoded en la especificación HTML 4.01, y así sucesivamente.

Pero, dado que es difícil determinar siempre el contexto correctamente, es la mejor práctica nunca codificar espacios como "+". Es mejor codificar en porcentaje todos los caracteres, excepto "sin reservas" definidos en RFC-3986, p.2.3. Aquí hay un ejemplo de código que ilustra lo que debe codificarse. Se administra en lenguaje de programación Delphi (pascal), pero es muy fácil de entender cómo funciona para cualquier programador, independientemente del lenguaje que posea:

(* 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
fuente
0

use la función encodeURIComponent para corregir la URL, funciona en el navegador y 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
fuente
1
Esto no aborda la pregunta. Y codifica incorrectamente las URL con un lenguaje específico (JavaScript); según el contexto, es probable que no desee codificar donde necesita barras especiales (/ no literales) y / dos puntos (:) para que la URL funcione .
Gremio
Gracias, realmente me ayudó!
qwsd
-2

Prueba a continuación:

<script type="text/javascript">

function resetPassword() {
   url: "submitForgotPassword.html?email="+fixEscape(Stringwith+char);
}
function fixEscape(str)
{
    return escape(str).replace( "+", "%2B" );
}
</script>
El chico java
fuente
2
Me parece muy extraño que dos personas votaron esta respuesta. Literalmente no tiene nada que ver con la pregunta.
Andrew Barber
1
¿Qué tal para otros personajes * @ - _ +. /
Ravi
1
@AndrewBarber ¿Por qué lo encontraste irrelevante? + se convierte en% 2B
The Java Guy
Esto está mal por muchas razones ... escapeestá en desuso, en su lugar, debe usar encodeURIo en el caso de la parte de consulta encodeURIComponent. Además, la cadena de parámetros debe codificar de acuerdo con w3c .
Christoph
-5

Siempre codificarás las URL.

Así es como Ruby codifica su URL:

irb(main):008:0> CGI.escape "a.com/a+b"
=> "a.com%2Fa%2Bb"
Lennart Koopmann
fuente
8
No estoy seguro de que sea correcto. De acuerdo con RFC2396 ( ietf.org/rfc/rfc2396.txt ) los más no son caracteres reservados en la ruta (segmentos) del URI, solo el componente de consulta. Eso parece implicar que no es necesario que estén codificados en URL y, por lo tanto, no deben interpretarse como espacios en la ruta, solo en la consulta.
tlrobinson
3
Sin embargo, el rfc 1738 trata las ventajas como espacios. Todo depende de cuál sea implementado por sus funciones de codificación / decodificación. por ejemplo, en php, rawurlencode sigue rfc 1738 mientras que urlencode sigue rfc 2396.
Jonathan Fingland
1
Mira, ahora tengo algo de confusión adicional. En el ejemplo que me diste arriba, a.com% 2Fa% 2Bb no es lo que quiero, al menos sería a.com/a%2Bb. Esta es una URL real con la que estoy tratando, no una URL que se pasa como parámetro en una cadena de consulta. Para obtener un poco de información que pueda ayudar a aclarar, Mac OS X Finder me devuelve las URL del sistema de archivos. Entonces, si tengo un archivo llamado "a? + B.txt", devuelve algo que se parece a "file: //a%3F+b.txt", NO a "file: //a%3F%2B.txt" . ¿El buscador es incorrecto o es un + antes de la cadena de consulta realmente un plus?
Francisco Ryan Tolmasky I
2
Jonathan: ¿Estás seguro de que 1738 dice que + está reservado? Ya veo: seguro = "$" | "-" | "_" | "." El | "+" sin reservar = alfa | dígito | seguro | extra así como: Por lo tanto, solo los caracteres alfanuméricos, los caracteres especiales "$ -_. +! * '()," y los caracteres reservados utilizados para sus fines reservados pueden usarse sin codificar dentro de una URL.
tlrobinson
2
"Siempre escaparás" necesita más calificación, y la respuesta es irrelevante para la pregunta de todos modos.
error