Представляет ли `+` в схеме URL / хосте / пути пробел?


224

Мне известно, что +в строке запроса URL-адреса указан пробел. Это также имеет место за пределами области строки запроса? То есть, делает следующий URL:

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

на самом деле представляют:

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

(и, следовательно, должны быть закодированы, если это действительно должно быть +), или это на самом деле представляет a+b/c?



4
Обратите внимание, что в php urldecode декодирует% 2b (кодированный +) в пробел. Чтобы избежать этого использования rawurldecode. Я говорю это здесь для справки, потому что это высокий результат в поиске Google для "php url decode breaks on plus symbol".
danielson317

Ответы:


170
  • Ожидается, что процентное кодирование в разделе пути URL будет декодировано, но
  • любые +символы в компоненте path должны обрабатываться буквально.

Чтобы быть явным: +это только специальный символ в компоненте запроса.


12
+1 К сожалению, многие «URL-кодеры / кодировщики» там в дикой природе не понимают этого. Например, sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy

11
@Stobor: цитата нужна.
Букзор

8
@Stobor Разве RFC когда-либо утверждал, что +символ интерпретируется как пробел в компоненте запроса? Или это просто правило "с дикой природы"?
Pacerier

44
@Pacerier и @bukzor: RFC 1738 (с изменениями 2396 и 3986) определяет компоненты схемы ( http:), Authority ( //server.example.com) и Path ( /myfile/mypage.htm) и не определяет никакого специального значения для +символа. Спецификация HTML определяет компонент запроса как mime-тип application / x-www-form-urlencoded, который определяется как «заменить пробелы +и другие специальные символы, как в RFC1738». Так что это не "из дикой природы", а из принятого (не RFC) стандарта.
Стобор

2
Метод .NET также Server.UrlEncodeошибочно кодирует пробелы как плюсы в части пути, нарушая правила HTTP.
Suncat2000

243

Вы можете найти хороший список соответствующих символов в кодировке URL на W3Schools .

  • + становится %2B
  • пространство становится %20

18
Вполне допустимо, чтобы буквенные символы «+» появлялись в компоненте пути в URL.
Сэм Стейнсби,

4
Чтобы получить литерал +, который будет получен серверной частью (или, по крайней мере, PHP), он должен быть тройным кодированием:%25252B
Umbrella

11
Этот ответ совершенно не имеет отношения к вопросу.
Ниссе Энгстрем

22

Пробел может быть закодирован как «+» только в одном контексте: пары ключ-значение application / x-www-form-urlencoded.

RFC-1866 (спецификация HTML 2.0), пункт 8.2.1. в подпункте 1. говорится: «Имена и значения полей формы экранируются: пробельные символы заменяются на« + », а затем зарезервированные символы экранируются»).

Вот пример такой строки в URL, где RFC-1866 позволяет кодировать пробелы в виде плюсов: « http://example.com/over/there?name=foo+bar ». Таким образом, только после «?» Пробелы можно заменить на плюсы (в других случаях пробелы следует кодировать в% 20). Этот способ кодирования данных формы также приведен в более поздних спецификациях HTML, например, ищите соответствующие параграфы о application / x-www-form-urlencoded в HTML 4.01 Specification и так далее.

Но так как всегда трудно правильно определить контекст, лучше никогда не кодировать пробелы как «+». Лучше кодировать все символы в процентах, кроме «незарезервированных», определенных в RFC-3986, p.2.3. Вот пример кода, который иллюстрирует то, что должно быть закодировано. Он дан на языке программирования Delphi (паскаль), но очень легко понять, как он работает для любого программиста, независимо от того, какой язык он обладает:

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

используйте функцию encodeURIComponent для исправления URL, она работает в браузере и 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
Это не решает вопрос. И неправильно кодирует URL-адреса на определенном языке (JavaScript) - в зависимости от контекста вы, вероятно, не захотите кодировать, где вам нужны специальные (не буквальные) косые черты (/) и двоеточия (:) для работы URL-адреса ,
Гремио

Спасибо, это действительно помогло мне!
19

-2

Попробуйте ниже:

<script type="text/javascript">

function resetPassword() {
   url: "submitForgotPassword.html?email="+fixEscape(Stringwith+char);
}
function fixEscape(str)
{
    return escape(str).replace( "+", "%2B" );
}
</script>

2
Я нахожу очень странным, что два человека проголосовали за этот ответ. Это буквально не имеет ничего общего с вопросом.
Эндрю Барбер

1
Как насчет других символов * @ - _ +. /
Рави

1
@AndrewBarber Почему вы нашли это неуместным? + становится% 2B
Java Guy

Это неправильно по многим причинам ... escapeне рекомендуется, вместо этого вы должны использовать encodeURIили в случае части запроса encodeURIComponent. Также строка параметров должна кодироваться в соответствии с w3c .
Кристоф

-5

Ты всегда будешь кодировать URL.

Вот как Ruby кодирует ваш URL:

irb(main):008:0> CGI.escape "a.com/a+b"
=> "a.com%2Fa%2Bb"

8
Я не уверен, что это правильно. Согласно RFC2396 ( ietf.org/rfc/rfc2396.txt ) плюсы не являются зарезервированными символами в пути (сегментах) URI, а только компонентом запроса. Кажется, это подразумевает, что их не нужно кодировать URL-адресом и, следовательно, не следует интерпретировать их как пробелы в пути, только в запросе.
tlrobinson

3
RFC 1738 однако рассматривает плюсы как пробелы. Все зависит от того, что реализовано вашими функциями кодирования / декодирования. например, в php rawurlencode следует rfc 1738, тогда как urlencode следует rfc 2396.
Джонатан Фингланд

1
Видите, теперь у меня есть дополнительная путаница. В приведенном выше примере a.com% 2Fa% 2Bb - это не то, что я хочу, а по крайней мере a.com/a%2Bb. Это фактический URL, с которым я имею дело, а не URL, передаваемый в качестве параметра в строке запроса. Для небольшого фона, который может помочь прояснить, Mac OS X Finder возвращает мне URL файловой системы. Поэтому, если у меня есть файл с именем «a? + B.txt», он возвращает что-то, похожее на «file: //a%3F+b.txt», НЕ «file: //a%3F%2B.txt» , Является ли искатель неверным или + перед строкой запроса на самом деле плюс?
Франсиско Райан Толмаски I

2
Джонатан: Ты уверен, что 1738 говорит + зарезервировано? Я вижу: safe = "$" | "-" | "_" | "" | "+" не зарезервировано = альфа | цифра | безопасно | дополнительно, а также: Таким образом, только буквенно-цифровые символы, специальные символы "$ -_. +! * '()," и зарезервированные символы, используемые для их зарезервированных целей, могут использоваться в URL-адресе без кодирования.
tlrobinson

2
«Ты всегда избежишь» требует большей квалификации, и ответ в любом случае не имеет отношения к вопросу.
ошибка
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.