Apakah valid untuk mengganti http: // dengan // di <script src = “http: // ...”>?

458

Saya memiliki elemen berikut:

<script type="text/javascript" src="https://cdn.example.com/js_file.js"></script>

Dalam hal ini situs tersebut adalah HTTPS, tetapi situs tersebut mungkin juga hanya HTTP. (File JS ada di domain lain.) Saya ingin tahu apakah valid untuk melakukan hal berikut demi kenyamanan:

<script type="text/javascript" src="//cdn.example.com/js_file.js"></script>

Saya ingin tahu apakah ini valid untuk menghapus http:atau https:?

Tampaknya berfungsi di mana pun saya telah menguji, tetapi apakah ada kasus di mana tidak berfungsi?

Darryl Hein
sumber
2
Bisakah "sepertinya berfungsi di mana-mana" digeneralisasikan ke gambar, iframe, tautan-rel dll.? Ini hal yang menarik, jika demikian.
12345
Ya, itu harus bekerja di tempat yang membutuhkan URI: gambar, tautan, dll. Mungkin jarang melihat ini digunakan, tetapi ini benar-benar valid.
Jeff
1
Ada apa dengan semua orang upvoting instan itu? Bukan karena pertanyaannya buruk atau apa, saya hanya ingin tahu. Tapi saya yakin reputasi awal Chris punya pengaruh.
Frederik Wordenskjold
13
@Frederik: Karena ini adalah trik yang menarik dan berguna yang kebanyakan orang tidak sadari.
SLaks
8
@Frederik: Apa?
SLaks

Jawaban:

387

URL relatif tanpa skema (http: atau https :) valid, per RFC 3986: "Uniform Resource Identifier (URI): Generic Syntax", Bagian 4.2 . Jika klien tersedak, maka itu adalah kesalahan klien karena mereka tidak mematuhi sintaks URI yang ditentukan dalam RFC.

Contoh Anda valid dan harus bekerja. Saya telah menggunakan metode URL relatif itu sendiri di situs-situs yang sangat diperdagangkan dan tidak memiliki keluhan. Kami juga menguji situs kami di Firefox, Safari, IE6, IE7 dan Opera. Semua browser ini memahami format URL itu.

Jeff
sumber
30
"Jika klien tersedak, maka itu adalah kesalahan klien karena mereka tidak mematuhi sintaks URI yang ditentukan dalam RFC." - Saya pikir ini adalah pertanyaan yang menarik - tetapi apakah klien mengikuti "spesifikasi" itu hampir tidak merupakan standar yang baik untuk menentukan apakah bijaksana untuk melakukannya dalam aplikasi web.
Matt Howell
6
Meskipun teknik ini tampaknya kurang dikenal, itu didukung di semua browser web. Ini bekerja sangat baik.
Ned Batchelder
8
Saya heran mengapa google tidak menggunakan ini untuk analitik. Mereka menggunakan metode document.location.protocol.
Darryl Hein
5
@ Darryl Hein Saya percaya google menggunakan metode document.location.protocol karena ia juga memodifikasi url, tidak hanya skema. Mereka pergi ke SSL.google-analytics.com jika dokumen tersebut menggunakan skema https.
Nick Meldrum
18
Google tidak menggunakan ini karena tumpukan jaringan Windows XP tidak mendukung SNI. Lihat di sini: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Karenanya memungkinkan skrip analitik google dimuat melalui https pada IE6 akan menghasilkan kesalahan sertifikat.
Eilistraee
152

Dijamin bekerja di semua browser arus utama (Saya tidak mempertimbangkan browser dengan pangsa pasar kurang dari 0,05%). Heck, itu bekerja di Internet Explorer 3.0.

RFC 3986 mendefinisikan URI sebagai terdiri dari bagian-bagian berikut:

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment

Saat mendefinisikan URI relatif ( Bagian 5.2 ), Anda dapat menghilangkan bagian mana saja, selalu dimulai dari kiri. Dalam pseudo-code, tampilannya seperti ini:

 result = ""

  if defined(scheme) then
     append scheme to result;
     append ":" to result;
  endif;

  if defined(authority) then
     append "//" to result;
     append authority to result;
  endif;

  append path to result;

  if defined(query) then
     append "?" to result;
     append query to result;
  endif;

  if defined(fragment) then
     append "#" to result;
     append fragment to result;
  endif;

  return result;

URI yang Anda gambarkan adalah URI relatif tanpa skema.

Andrew Moore
sumber
1
Ya saya kira saya pikir skema dan otoritas selalu saling tergantung. Masuk akal kalau tidak, tapi itu bukan sesuatu yang saya temui sampai baru-baru ini.
Chris
1
Itu tidak dijamin untuk bekerja di browser apa pun. Dijamin hanya berfungsi di browser yang mengikuti RFC.
2
@Roger Pate: Saya belum melihat browser belum mengikuti RFC untuk URI. Standar khusus itu sudah ada sejak lama ... Saya baru saja mengujinya di IE3.0 dan sangat mengerti. Jika Anda menggunakan peramban yang tidak memahami tautan tersebut, kemungkinan itu adalah peramban marginal yang tidak masalah.
Andrew Moore
1
@ Andrew: Mungkin Anda berbeda dari saya, tetapi ketika saya mengatakan "jaminan" dalam konteks pemrograman, saya benar-benar mengatakan "tidak mungkin ini bisa, pernah gagal," bukan hanya "itu hanya bekerja di implementasi populer yang saya ' sudah diuji. " Saya tidak bermaksud membuat masalah besar dari itu, tetapi tampaknya cukup penting untuk disebutkan.
4
@Roger: Ya, tetapi dalam konteks pengembangan web, browser marginal (<0,01% pangsa pasar) tidak dipertimbangkan. Ini seperti mengatakan bahwa API hadir di semua versi Windows dan kemudian seseorang datang untuk mengatakan bahwa itu mungkin tidak didukung dalam Wine ...
Andrew Moore
79

Adakah kasus yang tidak berfungsi?

Jika halaman induk diambil dari file://, maka itu mungkin tidak berfungsi (itu akan mencoba untuk mendapatkannya file://cdn.example.com/js_file.js, yang tentu saja Anda bisa berikan secara lokal juga).

Thilo
sumber
19
A must know for guys menguji html di mesin lokal!
Philip007
argh ... tidak heran saya script src="//..."tidak bekerja! Saya membuka file html secara lokal!
wisbucky
Adakah yang tahu cara mengatasinya?
km6zla
@ ogc-nick: Anda dapat menjalankan server web lokal. Banyak pilihan hari ini, dengan konfigurasi nol. Anda tetap menginginkannya, karena banyak hal lain (seperti XHR atau pekerja web juga tidak bekerja untuk file: domain)
Thilo
@ Thilo Itu telah bekerja sementara untuk saya, tetapi saya membuat aplikasi dengan Github's Electron dan itu menjadi sedikit lebih rumit.
km6zla
41

Banyak orang menyebutnya URL Relatif Protokol.

Ini menyebabkan pengunduhan dua kali file CSS di IE 7 & 8 .

Slaks
sumber
@AndrewMoore Karena "hal" yang dikecualikan menunjukkan protokol web, menyebutnya "protokol relatif" lebih masuk akal. Saya belum pernah mendengar tentang ftp atau http disebut "skema" ...
Cerin
25

Di sini saya menggandakan jawabannya dalam fitur Tersembunyi dari HTML :

Menggunakan jalur absolut independen-protokol:

<img src="//domain.com/img/logo.png"/>

Jika browser melihat halaman dalam SSL melalui HTTPS, maka browser akan meminta aset itu dengan protokol https, jika tidak maka akan memintanya dengan HTTP.

Ini mencegah pesan galat "Halaman ini berisi item aman dan tidak aman" di IE, menjaga semua permintaan aset Anda dalam protokol yang sama.

Peringatan: Ketika digunakan pada <link>atau @import untuk stylesheet, IE7 dan IE8 mengunduh file dua kali . Namun, semua kegunaan lain baik-baik saja.

kennytm
sumber
17

Sangat valid untuk meninggalkan protokol. URL spec sudah sangat jelas tentang hal ini selama bertahun-tahun, dan saya belum menemukan browser yang tidak memahaminya. Saya tidak tahu mengapa teknik ini tidak lebih dikenal; itu solusi sempurna untuk masalah pelik batas HTTP / HTTPS. Lebih lanjut di sini: Transisi Http-https dan URL relatif

Ned Batchelder
sumber
7

Adakah kasus yang tidak berfungsi?

Hanya dengan melempar ini dalam campuran, jika Anda mengembangkan pada server lokal, itu mungkin tidak berfungsi. Anda harus menentukan skema, jika tidak browser mungkin menganggap bahwa src="//cdn.example.com/js_file.js"adalah src="file://cdn.example.com/js_file.js", yang akan memecah karena Anda tidak hosting sumber daya ini secara lokal.

Microsoft Internet Explorer tampaknya sangat sensitif terhadap ini, lihat pertanyaan ini: Tidak dapat memuat jQuery di Internet Explorer di localhost (WAMP)

Anda mungkin akan selalu berusaha menemukan solusi yang berfungsi di semua lingkungan Anda dengan jumlah modifikasi paling sedikit yang diperlukan.

Solusi yang digunakan oleh HTML5Boilerplate adalah memiliki cadangan ketika sumber daya tidak dimuat dengan benar, tetapi itu hanya bekerja jika Anda memasukkan tanda centang:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- If jQuery is not defined, something went wrong and we'll load the local file -->
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>

UPDATE: HTML5Boilerplate sekarang digunakan <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jssetelah memutuskan untuk mencabut URL relatif protokol, lihat [di sini] [3].

bg17aw
sumber
4

Mengikuti referensi gnud, RFC 3986 bagian 5.2 mengatakan:

Jika komponen skema didefinisikan, menunjukkan bahwa referensi dimulai dengan nama skema, maka referensi ditafsirkan sebagai URI absolut dan kita selesai. Jika tidak, skema referensi URI diwarisi dari komponen dasar skema URI .

Jadi //benar :-)

Pablo Torrecilla
sumber
3

Ya, ini didokumentasikan dalam RFC 3986 , bagian 5.2:

(edit: Ups, referensi RFC saya sudah usang).

Agak
sumber
3

Memang benar, seperti jawaban lain telah menyatakan. Anda harus mencatat, bahwa beberapa perayap web akan memulai 404 untuk ini dengan meminta mereka di server Anda seolah-olah URL lokal. (Mereka mengabaikan tebasan ganda dan memperlakukannya sebagai tebasan tunggal).

Anda mungkin ingin mengatur aturan di server web Anda untuk menangkap dan mengarahkannya.

Misalnya, dengan Nginx, Anda akan menambahkan sesuatu seperti:

location ~* /(?<redirect_domain>((([a-z]|[0-9]|\-)+)\.)+([a-z])+)/(?<redirect_path>.*) {
  return 301 $scheme:/$redirect_domain/$redirect_path;
}

Namun perlu dicatat, bahwa jika Anda menggunakan periode di URI, Anda harus meningkatkan kekhususan atau akhirnya akan mengarahkan ulang halaman tersebut ke domain yang tidak ada.

Juga, ini adalah regex yang agak masif untuk dijalankan untuk setiap permintaan - menurut pendapat saya, layak untuk menghukum browser yang tidak patuh dengan 404s atas (sedikit) pencapaian kinerja pada sebagian besar browser yang patuh.

Jlovison
sumber
3

Kami melihat 404 kesalahan dalam log kami ketika menggunakan //somedomain.com sebagai referensi ke file JS.

Referensi yang menyebabkan 404 keluar tampak seperti ini: ref:

<script src="//somedomain.com/somescript.js" />

404 permintaan:

http://mydomain.com//somedomain.com/somescript.js

Dengan ini muncul secara teratur di log server web kami, aman untuk mengatakan bahwa: Semua browser dan Bot TIDAK menghormati RFC 3986 bagian 4.2. Taruhan paling aman adalah memasukkan protokol jika memungkinkan.

Lemiarty
sumber
Ya, saya sudah agak beralih darinya, tetapi bukan karena 404-an (Saya belum pernah melihat 404-an ... jika bot tidak menghormatinya, saya tidak peduli) - karena saya tidak lagi memuat sumber daya dari CDN lain jadi saya tidak perlu melakukan ini (sebagai gantinya saya memperkecil sebanyak mungkin menjadi 1 atau 2 file).
Darryl Hein
1
Harap sertakan protokolnya. Istirahat tanpa protokol di aplikasi Cordova saya
pgorsira
3

1. Ringkasan

Jawaban untuk 2019: Anda masih dapat menggunakan URL relatif protokol, tetapi teknik ini anti-pola .

Juga:

  1. Anda mungkin memiliki masalah dalam pengembangan.
  2. Beberapa alat pihak ketiga mungkin tidak mendukungnya.

Bermigrasi dari URL protokol-relatif ke https://itu akan menyenangkan.


2. Relevansi

Jawaban ini relevan untuk Januari 2019. Di masa mendatang, data dari jawaban ini mungkin sudah usang.


3. Anti-pola

3.1. Argumentasi

Paul Irish - insinyur front-end dan advokat pengembang untuk Google Chrome - menulis pada 2014, Desember :

Sekarang SSL didorong untuk semua orang dan tidak memiliki masalah kinerja , teknik ini sekarang merupakan anti-pola . Jika aset yang Anda butuhkan tersedia di SSL, maka selalu gunakan https://aset tersebut.

Mengizinkan cuplikan meminta melalui HTTP membuka pintu untuk serangan seperti serangan GitHub Man-on-the-side baru-baru ini . Selalu aman untuk meminta aset HTTPS bahkan jika situs Anda menggunakan HTTP, namun kebalikannya tidak benar .

3.2. Tautan lain

3.3. Contohnya


4. Mengembangkan proses

Sebagai contoh, saya mencoba menggunakan konsol bersih .

  • File contoh KiraCleanConsole__cdn_links_demo.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>clean-console without protocol demonstration</title>
    <!-- Really dead link -->
    <script src="https://unpkg.com/bowser@latest/bowser.min.js"></script>
    <!-- Package exists; link without “https:” -->
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
    <!-- Package exists: link with “https:” -->
    <script src="https://cdn.jsdelivr.net/npm/gemini-scrollbar/index.js"></script>
</head>
<body>
    Kira Goddess!
</body>
</html>
  • keluaran:
D:\SashaDebugging>clean-console -i KiraCleanConsole__cdn_links_demo.html
checking KiraCleanConsole__cdn_links_demo.html
phantomjs: opening page KiraCleanConsole__cdn_links_demo.html

phantomjs: Unable to load resource (#3URL:file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error opening //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js: The network path was not found.

  phantomjs://code/runner.js:31 in onResourceError

phantomjs: Unable to load resource (#5URL:https://unpkg.com/[email protected]/bowser.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error downloading https://unpkg.com/[email protected]/bowser.min.js - server replied: Not Found

  phantomjs://code/runner.js:31 in onResourceError

phantomjs: Checking errors after sleeping for 1000ms
2 error(s) on KiraCleanConsole__cdn_links_demo.html

phantomjs process exited with code 2

Tautan //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jsvalid, tetapi saya mendapatkan kesalahan.

Perhatikan file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jsdan baca jawaban Thilo dan bg17aw tentang file://.

Saya tidak tahu tentang perilaku ini dan tidak bisa mengerti mengapa saya memiliki masalah seperti ini untuk pager .


5. Alat pihak ketiga

Saya menggunakan paket Teks Sublime URL yang Dapat Diklik. Gunakan itu, saya bisa membuka tautan dari editor teks saya di browser.

Contoh tautan CSS

Kedua tautan dalam contoh ini valid. Tapi tautan pertama yang berhasil saya buka di browser menggunakan URL yang dapat diklik, tautan kedua - tidak. Ini mungkin tidak nyaman.


6. Kesimpulan

Iya:

  1. Jika Anda memiliki masalah seperti pada Developing processitem, Anda dapat mengatur alur kerja pengembangan Anda.
  2. Jika Anda memiliki masalah seperti pada Third-party toolsitem, Anda dapat berkontribusi alat.

Tetapi Anda tidak perlu masalah tambahan ini. Baca informasi berdasarkan tautan dalam Anti-patternitem: URL relatif protokol sudah usang.

Саша Черных
sumber
2

Pola yang saya lihat di html5-boilerplate adalah:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>

Ini berjalan lancar pada skema yang berbeda seperti http, https, file.

neurit
sumber
Ini tidak lagi benar, lihat stackoverflow.com/a/37609402/2237601 atau di sini , mereka sekarang gunakan https://untuk semuanya
bg17aw
@ bg17aw Masalah dengan penggunaan di https://mana - mana adalah Anda harus terus memeriksa semua tautan eksternal Anda untuk melihat apakah mereka benar-benar mendukungnya, dan mengubahnya menjadi http://jika tidak (karena kalau tidak mereka tidak akan berfungsi). Ini mungkin merepotkan dengan sejumlah besar tautan.
tomasz86
@ tomasz86 Anda melewatkan intinya, saya hanya merujuk pada kasus tertentu yang menghubungkan ke konten dari CDNs. https: // wajib untuk itu saat ini. Jawabannya juga berbicara tentang kasus tertentu (html5-boilerplate). Tidak ada "memeriksa http" seperti yang Anda katakan, karena CDN selalu menggunakan https sekarang.
bg17aw
@ bg17aw Itu benar tetapi pertanyaan umum di sini bukan hanya tentang CDN. Dengan membaca hanya jawaban / komentar ini, mudah untuk berpikir bahwa https://seharusnya (atau dapat) digunakan di semua tautan yang tidak benar.
tomasz86
@ tomasz86 Keindahan memiliki beberapa jawaban adalah bahwa sementara tidak ada satu pun yang sempurna (jika jawaban akan sempurna, yang lain perlu dihapus), membaca beberapa dari mereka memberi kita pandangan yang lebih luas. Dalam hal ini, jawabannya mengatakan "pola pada html5boilerplate adalah ..." dan komentar saya memperbarui jawaban ini dengan menyebutkan "yang tidak lagi pola pada html5-boilerplate". Itu dia. Tambahan yang diperlukan untuk jawaban khusus ini. Harap perhatikan juga pertanyaan aslinya tentang CDN!
bg17aw
1

Karena contoh Anda menghubungkan ke domain eksternal, jika Anda menggunakan HTTPS maka Anda harus memverifikasi bahwa domain eksternal juga diatur untuk SSL. Jika tidak, pengguna Anda mungkin melihat kesalahan SSL dan / atau kesalahan 404 (mis. Versi lama Plesk menyimpan HTTP dan HTTPS dalam folder terpisah). Untuk CDN, seharusnya tidak menjadi masalah tetapi untuk situs web lain apa pun bisa.

Di samping catatan, diuji saat memperbarui situs web lama dan juga berfungsi di url = bagian dari META REFRESH.

pengguna2246924
sumber