Apakah `+` dalam skema URL / host / jalur mewakili spasi?

224

Saya menyadari bahwa +dalam string kueri URL mewakili spasi. Apakah ini juga kasus di luar wilayah string kueri? Artinya, apakah URL berikut:

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

sebenarnya mewakili:

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

(dan dengan demikian perlu dikodekan jika harus benar-benar a +), atau apakah sebenarnya mewakili a+b/c?

Francisco Ryan Tolmasky I
sumber
4
Perhatikan bahwa dalam php urldecode menerjemahkan% 2b (disandikan +) ke spasi. Untuk menghindari penggunaan ini rawurldecode. Saya mengatakan ini di sini untuk referensi karena ini adalah hasil nilai tinggi di pencarian google untuk "php url decode breaks on plus symbol".
danielson317
1
Kemungkinan rangkap dari Kapan untuk menyandikan ruang ke plus (+) atau% 20?
pengguna

Jawaban:

170
  • Pengkodean persen di bagian jalur URL diharapkan diterjemahkan, tetapi
  • setiap +karakter dalam komponen path diharapkan diperlakukan secara literal.

Secara eksplisit: +hanya karakter khusus dalam komponen permintaan.

Stobor
sumber
12
+1 Sayangnya, banyak "pembuat kode URL / pembuat enkode" di luar sana tidak memahami hal ini. Misalnya sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy
11
@Stobor: kutipan diperlukan.
bukzor
8
@Stobor Apakah RFC pernah menyatakan bahwa +karakter ditafsirkan sebagai spasi dalam komponen kueri? Atau itu hanya aturan "dari alam"?
Pacerier
44
@Pacerier dan @bukzor: RFC 1738 (sebagaimana dimodifikasi oleh 2396 dan 3986) mendefinisikan komponen skema ( http:), authority ( //server.example.com), dan path ( /myfile/mypage.htm), dan tidak mendefinisikan makna khusus untuk +karakter tersebut. Spesifikasi HTML mendefinisikan komponen permintaan menjadi aplikasi tipe mime / x-www-form-urlencoded yang didefinisikan sebagai "ganti spasi dengan +dan karakter khusus lainnya seperti dalam RFC1738". Jadi ini bukan "dari alam", tetapi dari standar yang diterima (non-RFC).
Stobor
2
Metode .NET Server.UrlEncodekeliru mengkode spasi sebagai plusses di bagian path juga, melanggar aturan HTTP.
Suncat2000
243

Anda dapat menemukan daftar karakter berkode URL yang sesuai di W3Schools .

  • + menjadi %2B
  • ruang menjadi %20
Niels R.
sumber
18
Sangat sah untuk karakter '+' literal muncul di komponen jalur pada URL.
Sam Stainsby
4
Untuk mendapatkan tanda literal + yang akan diterima pada bagian belakang (atau, setidaknya PHP), kata itu harus tiga kali dikodekan:%25252B
Payung
11
Jawaban ini sama sekali tidak relevan dengan pertanyaan.
Nisse Engström
22

Karakter spasi hanya dapat dikodekan sebagai "+" dalam satu konteks: application / x-www-form-urlencoded pasangan nilai kunci.

RFC-1866 (spesifikasi HTML 2.0), paragraf 8.2.1. subparagraf 1. mengatakan: "Nama-nama bidang nilai-nilai dan melarikan diri: karakter spasi diganti dengan` + ', dan kemudian karakter yang dipesan melarikan diri ").

Berikut adalah contoh string di URL di mana RFC-1866 memungkinkan ruang pengkodean sebagai plus: " http://example.com/over/there?name=foo+bar ". Jadi, hanya setelah "?", Spasi dapat diganti dengan plus (dalam kasus lain, spasi harus dikodekan ke% 20). Cara pengkodean data formulir ini juga diberikan dalam spesifikasi HTML nanti, misalnya, cari paragraf yang relevan tentang aplikasi / x-www-form-urlencoded dalam Spesifikasi HTML 4.01, dan seterusnya.

Tapi, karena sulit untuk selalu menentukan konteks dengan benar, itu praktik terbaik untuk tidak pernah menyandikan spasi sebagai "+". Lebih baik untuk meng-enkode semua karakter kecuali "tanpa cadangan" yang didefinisikan dalam RFC-3986, hal.2.3. Berikut adalah contoh kode yang menggambarkan apa yang harus dikodekan. Itu diberikan dalam bahasa pemrograman Delphi (pascal), tetapi sangat mudah untuk memahami cara kerjanya untuk setiap programmer terlepas dari bahasa yang dimiliki:

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

menggunakan fungsi komponen encodeURICon untuk memperbaiki url, ini berfungsi pada Browser dan 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
sumber
1
Ini tidak menjawab pertanyaan. Dan, menyandikan URL dengan salah, dengan bahasa tertentu (JavaScript) - tergantung pada konteksnya, Anda mungkin tidak ingin menyandikan di mana Anda memerlukan garis miring khusus (bukan literal) (/) dan titik dua (:) agar URL berfungsi) .
Gremio
Terima kasih itu sangat membantu saya!
qwsd
-2

Coba di bawah ini:

<script type="text/javascript">

function resetPassword() {
   url: "submitForgotPassword.html?email="+fixEscape(Stringwith+char);
}
function fixEscape(str)
{
    return escape(str).replace( "+", "%2B" );
}
</script>
Orang Jawa
sumber
2
Saya merasa sangat aneh bahwa dua orang memilih jawaban ini. Secara harfiah tidak ada hubungannya dengan pertanyaan.
Andrew Barber
1
Bagaimana dengan karakter lain * @ - _ +. /
Ravi
1
@AndrewBarber Mengapa Anda merasa itu tidak relevan? + menjadi% 2B
The Java Guy
Ini salah karena banyak alasan ... escapesudah usang, alih-alih Anda harus menggunakan encodeURIatau dalam kasus bagian permintaan encodeURIComponent. Juga string parameter harus dikodekan sesuai dengan w3c .
Christoph
-5

Anda harus selalu menyandikan URL.

Berikut ini cara Ruby menyandikan URL Anda:

irb(main):008:0> CGI.escape "a.com/a+b"
=> "a.com%2Fa%2Bb"
Lennart Koopmann
sumber
8
Saya tidak yakin itu benar. Menurut RFC2396 ( ietf.org/rfc/rfc2396.txt ) plusses bukan karakter yang dicadangkan di jalur (segmen) URI, hanya komponen kueri. Itu tampaknya menyiratkan bahwa mereka tidak perlu dikodekan URL dan dengan demikian tidak boleh ditafsirkan sebagai spasi di jalur, hanya dalam kueri.
tlrobinson
3
rfc 1738 memperlakukan plus sebagai spasi. Itu semua tergantung pada yang diterapkan oleh fungsi encode / decode Anda. misalnya, dalam php, rawurlencode mengikuti rfc 1738 sedangkan urlencode mengikuti rfc 2396.
Jonathan Fingland
1
Lihat, sekarang saya memiliki beberapa kebingungan tambahan. Pada contoh yang Anda berikan kepada saya di atas, a.com% 2Fa% 2Bb bukan yang saya inginkan, setidaknya a.com/a%2Bb. Ini adalah URL aktual yang saya tangani, bukan URL yang diteruskan sebagai parameter dalam string kueri. Untuk sedikit latar belakang yang dapat membantu memperjelas, Mac OS X Finder mengembalikan URL sistem file kepada saya. Jadi jika saya memiliki file bernama "a? + B.txt", itu mengembalikan sesuatu yang tampak seperti "file: //a%3F+b.txt", BUKAN "file: //a%3F%2B.txt" . Apakah pencari hanya salah, atau + sebelum string query sebenarnya plus?
Francisco Ryan Tolmasky Saya
2
Jonathan: Apakah Anda yakin 1738 mengatakan + dicadangkan? Saya melihat: safe = "$" | "-" | "_" | "." | "+" tanpa syarat = alpha | digit | aman | ekstra juga: Dengan demikian, hanya alfanumerik, karakter khusus "$ -_. +! * '(),", dan karakter yang dipesan yang digunakan untuk keperluan yang dipesan dapat digunakan tanpa kode dalam URL.
tlrobinson
2
"Kamu akan selalu lolos" membutuhkan lebih banyak kualifikasi, dan jawabannya tidak relevan dengan pertanyaan itu.
bug