Encode URL dalam JavaScript?

2470

Bagaimana cara Anda menyandikan URL menggunakan JavaScript dengan aman sehingga dapat dimasukkan ke dalam string GET?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

Saya berasumsi bahwa Anda perlu menyandikan myUrlvariabel pada baris kedua itu?

nickf
sumber
22
Coba lihat ke encodeURI () dan decodeURI () .
Zack The Human
1
Anda dapat menggunakan alat ini di sini: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Andrew

Jawaban:

2791

Lihat fungsi built-in komponen encodeURIC (str) dan encodeURI (str) .
Dalam kasus Anda, ini harus bekerja:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Buu Nguyen
sumber
12
Bagaimana kalau menambahkan penjelasan yang diberikan @cms? escapejuga merupakan opsi yang valid.
hitautodestruct
11
menurut @CMS encodeURItidak benar-benar aman untuk pengkodean URL.
Ifnot
13
@AnaelFavre karena itu dimaksudkan untuk mengkodekan seluruh URL, yang tidak memungkinkan karakter seperti :, /, @dll ini 2 metode tidak digunakan dipertukarkan, Anda harus tahu apa yang Anda pengkodean menggunakan metode yang tepat.
Buu Nguyen
Sebagaimana disebutkan dalam jawaban lain di halaman ini , situs ini dengan baik merinci alasan untuk menggunakan metode ini
Brad Parks
1522

Anda memiliki tiga opsi:

  • escape() tidak akan menyandikan: @*/+

  • encodeURI() tidak akan menyandikan: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() tidak akan menyandikan: ~!*()'

Tetapi dalam kasus Anda, jika Anda ingin mengirimkan URL ke GETparameter halaman lain, Anda harus menggunakan escapeatau encodeURIComponent, tetapi tidak encodeURI.

Lihat pertanyaan Stack Overflow Praktik terbaik: escape, atau encodeURI / encodeURICon komponen untuk diskusi lebih lanjut.

CMS
sumber
76
Pengkodean karakter yang digunakan dengan escape adalah variabel. Tetap dengan komponen encodeURI dan encodeURIC, yang menggunakan UTF-8.
erickson
6
Hati-hati. Escape itu mengubah karakter non-ASCII menjadi urutan escape Unicode-nya, seperti %uxxx.
opteronn
4
Saya menggunakan komponen encodeURIC dan memperhatikannya tidak akan menyandikan karakter pipa |
kevzettler
15
@kevzettler - mengapa harus melakukan itu? Pipa tidak semantik penting dalam URI.
nickf
4
@GiovanniP: Orang yang mengizinkan karakter Jerman, Prancis, Jepang, Cina, Arab sebagai input dan lulus parameter tesis melalui GET atau POST.
Tseng
180

Tetap dengan encodeURIComponent(). Fungsi encodeURI()ini tidak mengganggu untuk menyandikan banyak karakter yang memiliki kepentingan semantik dalam URL (mis. "#", "?", Dan "&"). escape()sudah tidak digunakan lagi, dan tidak perlu repot untuk menyandikan karakter "+", yang akan ditafsirkan sebagai ruang yang disandikan di server (dan, seperti yang ditunjukkan oleh orang lain di sini, tidak benar menyandi URL karakter non-ASCII).

Ada penjelasan yangencodeURI()encodeURIComponent() bagus tentang perbedaan antara dan di tempat lain. Jika Anda ingin menyandikan sesuatu sehingga bisa dimasukkan dengan aman sebagai komponen URI (misalnya sebagai parameter string kueri), Anda ingin menggunakannya encodeURIComponent().

Mike Brennan
sumber
83

Jawaban terbaik adalah dengan menggunakan encodeURIComponentpada nilai-nilai dalam string (dan tempat lain).

Namun, saya menemukan bahwa banyak API ingin mengganti "" dengan "+" jadi saya harus menggunakan yang berikut:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escapediimplementasikan secara berbeda di browser yang berbeda dan encodeURItidak menyandikan banyak karakter (seperti # dan bahkan /) - itu dibuat untuk digunakan pada URI / URL lengkap tanpa merusaknya - yang tidak super membantu atau aman.

Dan seperti yang ditunjukkan oleh @Jochem di bawah ini, Anda mungkin ingin menggunakan encodeURIComponent()nama folder (masing-masing), tetapi untuk alasan apa pun, API ini sepertinya tidak ingin +dalam nama folder sehingga encodeURIComponentkarya lama yang biasa sangat bagus.

Contoh:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Ryan Taylor
sumber
22
Harap dicatat, Anda hanya harus mengganti% 20 dengan simbol + setelah tanda tanya pertama (yang merupakan bagian 'kueri' dari URL). Katakanlah saya ingin menjelajah http://somedomain/this dir has spaces/info.php?a=this has also spaces. Itu harus dikonversi ke: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacestetapi banyak implementasi memungkinkan '% 20' di querystring digantikan oleh '+'. Namun demikian, Anda tidak dapat mengganti '% 20' dengan '+' di bagian jalur URL, ini akan menghasilkan kesalahan Tidak Ditemukan kecuali Anda memiliki direktori dengan +bukan spasi.
Jochem Kuijpers
@Jochem Kuijpers, pasti, Anda tidak akan menempatkan "+" di direktori. Saya hanya akan menerapkan ini pada nilai parameter kueri sendiri (atau kunci jika diperlukan), bukan seluruh URL, atau bahkan seluruh string kueri.
Ryan Taylor
Saya akan mengganti nilainya daripada dalam hasil pengkodean
njzk2
1
@ njzk2 sayangnya encodeURIComponent('+')akan memberi Anda %2B, jadi Anda harus menggunakan dua ekspresi reguler ... yang saya kira agak mengapa ini berhasil, karena '+' are '' dikodekan secara berbeda pada akhirnya.
Ryan Taylor
Tidak ada alasan untuk menerjemahkan% 20 menjadi "+". Urutan escape yang valid untuk ruang ASCII adalah% 20, bukan "+" yang tidak disebutkan dalam RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" digunakan pada 1990-an; itu sudah usang sekarang dan hanya didukung untuk alasan warisan. Jangan gunakan itu.
xhienne
40

Jika Anda menggunakan jQuery saya akan pergi untuk $.parammetode. Ini menyandikan URL bidang pemetaan objek ke nilai, yang lebih mudah dibaca daripada memanggil metode pelarian pada setiap nilai.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Maksym Kozlenko
sumber
Saya pikir contoh yang diberikan sudah cukup. Jika Anda memerlukan informasi lebih lanjut tentang $ .param
Maksym Kozlenko
Hampir semua orang menggunakan jQuery dan saya memang merasa lebih nyaman dengan ini daripada komponen encoreURICon
Cyril Duchon-Doris
12

encodeURIComponent () adalah caranya.

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

TETAPI Anda harus ingat bahwa ada sedikit perbedaan dari versi php urlencode()dan seperti yang disebutkan oleh @CMS, itu tidak akan menyandikan setiap karakter. Cowok di http://phpjs.org/functions/urlencode/ membuat js setara dengan phpencode():

function urlencode(str) {
  str = (str + '').toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}
Adam Fischer
sumber
10

Untuk menyandikan URL, seperti yang telah dikatakan sebelumnya, Anda memiliki dua fungsi:

encodeURI()

dan

encodeURIComponent()

Alasan keduanya ada adalah bahwa yang pertama mempertahankan URL dengan risiko meninggalkan terlalu banyak hal yang tidak terhindarkan, sedangkan yang kedua mengkodekan semua yang dibutuhkan.

Dengan yang pertama, Anda dapat menyalin URL yang baru saja lolos ke bilah alamat (misalnya) dan itu akan berfungsi. Namun '&' yang tidak terhapus akan mengganggu pembatas bidang, '=' akan mengganggu nama dan nilai bidang, dan '+' akan terlihat seperti spasi. Tetapi untuk data sederhana ketika Anda ingin mempertahankan sifat URL dari apa yang Anda melarikan diri, ini berfungsi.

Yang kedua adalah semua yang perlu Anda lakukan untuk memastikan tidak ada di string Anda yang mengganggu URL. Itu membuat berbagai karakter yang tidak penting tidak terhapus sehingga URL tetap dapat dibaca manusia mungkin tanpa gangguan. URL yang disandikan dengan cara ini tidak akan lagi berfungsi sebagai URL tanpa melepaskannya.

Jadi jika Anda dapat meluangkan waktu, Anda selalu ingin menggunakan encodeURIComponent () - sebelum menambahkan pasangan nama / nilai, enkode nama dan nilai menggunakan fungsi ini sebelum menambahkannya ke string kueri.

Saya mengalami kesulitan menemukan alasan untuk menggunakan encodeURI () - Saya akan menyerahkannya kepada orang yang lebih pintar.

Gerard ONeill
sumber
5

Hal serupa saya coba dengan javascript biasa

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
Narayan Yerrabachu
sumber
5

Cara yang elegan

Menurut pendapat saya yang sederhana cara paling elegan untuk menyandikan params query adalah membuat objek dengan params like

const queryParams = { param1: 'value1', param2: 'value2' }

dan kemudian menyandikannya menggunakan:

const queryString = new URLSearchParams(queryParams).toString()

seperti yang disebutkan dalam jawaban ini: https://stackoverflow.com/a/53171438/7284582

Qback
sumber
4

Untuk mencegah pengkodean ganda, sebaiknya uraikan kode url sebelum melakukan pengkodean (jika Anda berurusan dengan url yang dimasukkan pengguna misalnya, yang mungkin sudah disandikan).

Katakanlah kita memiliki abc%20xyz 123input (satu spasi sudah disandikan):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
serg
sumber
4

Apa itu pengkodean URL:

URL harus dikodekan ketika ada karakter khusus yang terletak di dalam URL. Sebagai contoh:

console.log(encodeURIComponent('?notEncoded=&+'));

Kita dapat mengamati dalam contoh ini bahwa semua karakter kecuali string notEncodeddikodekan dengan tanda%. Pengkodean URL juga dikenal sebagai pengodean persentase karena ia lolos dari semua karakter khusus dengan%. Kemudian setelah tanda% ini setiap karakter khusus memiliki kode unik

Mengapa kami membutuhkan pengodean URL:

Karakter tertentu memiliki nilai khusus dalam string URL. Misalnya,? karakter menunjukkan awal dari string kueri. Agar berhasil menemukan sumber daya di web, perlu dibedakan antara saat karakter dimaksudkan sebagai bagian dari string atau bagian dari struktur url.

Bagaimana kami dapat mencapai penyandian URL di JS:

JS menawarkan banyak fungsi utilitas bawaan yang dapat kita gunakan untuk menyandikan URL dengan mudah. Ini adalah dua opsi yang mudah:

  1. encodeURIComponent(): Mengambil komponen URI sebagai argumen dan mengembalikan string URI yang disandikan.
  2. encodeURI(): Mengambil URI sebagai argumen dan mengembalikan string URI yang disandikan.

Contoh dan peringatan:

Berhati-hatilah untuk tidak meneruskan seluruh URL (termasuk skema, mis. Https: //) ke encodeURIComponent(). Ini sebenarnya dapat mengubahnya menjadi URL yang tidak fungsional. Sebagai contoh:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

Kita dapat mengamati jika kita meletakkan seluruh URL di encodeURIComponentmana garis miring foward (/) juga dikonversi ke karakter khusus. Ini akan menyebabkan URL tidak berfungsi dengan benar lagi.

Karena itu (sesuai namanya) gunakan:

  1. encodeURIComponent pada bagian tertentu dari URL yang ingin Anda enkode.
  2. encodeURI pada keseluruhan URL yang ingin Anda enkode.
Willem van der Veen
sumber
3

Tidak ada yang berhasil untuk saya. Yang saya lihat hanyalah HTML halaman login, kembali ke sisi klien dengan kode 200. (302 pada awalnya tetapi permintaan Ajax yang sama memuat halaman login di dalam permintaan Ajax lain, yang seharusnya menjadi redirect daripada memuat plain teks dari halaman login).

Di pengontrol login, saya menambahkan baris ini:

Response.Headers["land"] = "login";

Dan dalam penangan Ajax global, saya melakukan ini:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

Sekarang saya tidak memiliki masalah, dan itu berfungsi seperti pesona.

Asif Ashraf
sumber
2

Encode URL String

    var url = $ ( lokasi ). attr ( 'href' ); // dapatkan url saat ini // ATAU var url = 'folder / index.html? param = # 23dd & noob = yes' ; // atau sebutkan satu 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string
Shah Sangeet
sumber
2

Berikut ini adalah DEMO LANGSUNG dari encodeURIComponent()dan decodeURIComponent()JS dibangun pada fungsi:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>
Jonathana
sumber
1

Anda dapat menggunakan pustaka esapi dan menyandikan url Anda menggunakan fungsi di bawah ini. Fungsi memastikan bahwa '/' tidak hilang untuk penyandian sementara sisa isi teks dikodekan:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme

Mohith Maratt
sumber
1

Gunakan fixedEncodeURIComponentfungsi untuk sepenuhnya mematuhi RFC 3986 :

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Arthur
sumber
1

Anda tidak boleh menggunakannya encodeURIComponent()secara langsung.

Lihatlah RFC3986: Uniform Resource Identifier (URI): Generic Syntax

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Tujuan dari karakter yang dipesan adalah untuk memberikan serangkaian karakter pembatas yang dapat dibedakan dari data lain dalam URI.

Karakter yang dicadangkan ini dari definisi URI di RFC3986 TIDAK DILAKUKAN oleh encodeURIComponent().

Dokumen Web MDN: komponen encodeURIC ()

Agar lebih ketat dalam mematuhi RFC 3986 (yang mencadangkan!, ', (,), Dan *), meskipun karakter ini tidak memiliki penggunaan pembatas URI yang diformalkan, hal berikut dapat digunakan dengan aman:

Gunakan fungsi MDN Web Documents ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
HoldOffHunger
sumber