Чи "+" у схемі 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 для "перерви декодування URL-адреси URL на плюс".
danielson317

Відповіді:


170
  • Очікується, що відсоткове кодування в розділі шляху URL-адреси буде декодовано, але
  • будь-які +символи в компоненті шляху , як очікується , буде розглядатися в буквальному сенсі.

Щоб бути ясним: +це лише спеціальний символ у компоненті запиту.


12
+1 На жаль, багато "URL-кодери / кодери", що знаходяться там у дикій природі, цього не розуміють. Наприклад, sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy

11
@Stobor: потрібне цитування.
bukzor

8
@Stobor Чи RFC коли-небудь заявляв, що +символ інтерпретується як пробіл у компоненті запиту? Або це просто правило "з дикої природи"?
Pacerier

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

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

243

Ви можете знайти хороший список відповідних символів, кодованих URL- адресами в W3Schools .

  • + стає %2B
  • простір стає %20

18
Цілком законно, щоб буквальні символи "+" відображалися в компоненті шляху в URL-адресі.
Сем Стайнсбі

4
Щоб отримати буквальний +, який буде отриманий заднім кінцем (або, принаймні, PHP), його потрібно потрійно закодувати:%25252B
Парасолька

11
Ця відповідь абсолютно не стосується питання.
Nisse Engström

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 тощо.

Але, оскільки важко завжди правильно визначити контекст, найкраща практика ніколи не кодує пробіли як "+". Краще відсотковим кодуванням всіх символів, крім "незарезервованого", визначеного в RFC-3986, p.2.3. Ось приклад коду, який ілюструє, що слід закодувати. Він наданий мовою програмування Delphi (pascal), але дуже легко зрозуміти, як це працює для будь-якого програміста незалежно від мови, якою він володіє:

(* 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-адреса працювала .
Греміо

Дякую, це мені справді допомогло!
qwsd

-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

Це неправильно через стільки причин ... 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, і тому їх не слід інтерпретувати як пробіли на шляху, лише у запиті.
тлробінсон

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

1
Дивіться, зараз у мене є додаткова плутанина. У прикладі, який ви подали мені вище, a.com% 2Fa% 2Bb - це не те, чого я хочу, принаймні це було б a.com/a%2Bb. Це фактична URL-адреса, з якою я маю справу, а не URL-адреса, яка передається як параметр у рядку запиту. Якщо ви хочете ознайомитись із інформацією про роботу, Mac Find X X Finder повертає мені URL-адреси файлової системи. Отже, якщо у мене є файл під назвою "a? + B.txt", він повертає щось таке, що виглядає як "файл: //a%3F+b.txt", а не "файл: //a%3F%2B.txt" . Чи шукач просто невірний, або + перед рядком запиту насправді є плюсом?
Франсіско Райан Толмаскі I

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

2
"Ти завжди втечеш" потребує більшої кваліфікації, і відповідь на питання все одно не має значення.
помилка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.