Чи правильно замінювати http: // з // у <script src = "http: // ...">?


458

У мене є такий елемент:

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

У цьому випадку сайт є HTTPS, але він також може бути лише HTTP. (Файл JS знаходиться в іншому домені.) Мені цікаво, чи справедливо робити наступне для зручності:

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

Мені цікаво, чи справедливо видалити http:або https:?

Здається, він працює скрізь, де я тестував, але чи є випадки, коли це не працює?


2
Чи можна «схоже, що працює скрізь» узагальнювати на образи, рамки, посилання-ретри тощо тощо? Це цікаві речі, якщо так.
12345

Так, він повинен працювати в будь-якому місці, яке вимагає створення URI: зображення, посилання тощо. Це може бути рідко, коли це можна побачити у використанні, але це абсолютно дійсно.
Джефф

1
Що з усім цим миттєвим набором хлопців? Не те, щоб питання було поганим чи нічого, мені просто цікаво. Але я думаю, що на репутацію Кріса впливає.
Фредерік Wordenskjold

13
@Frederik: Оскільки це захоплюючий і корисний трюк, про який, мабуть, більшість людей не знає.
СЛАкс

8
@Frederik: Що?
SLaks

Відповіді:


387

Відносна URL-адреса без схеми (http: або https :) дійсна, згідно RFC 3986: "Уніфікований ідентифікатор ресурсу (URI): Загальний синтаксис", Розділ 4.2 . Якщо клієнт задихається від нього, то це вина клієнта, оскільки він не відповідає синтаксису URI, вказаному в RFC.

Ваш приклад дійсний і повинен працювати. Я сам використовував цей метод відносної URL-адреси на сайтах з великою торгівлею людьми і не мав жодних скарг. Також ми тестуємо наші сайти в Firefox, Safari, IE6, IE7 та Opera. Усі ці браузери розуміють цей формат URL-адрес.


30
"Якщо клієнт задихається від нього, то це вина клієнта, оскільки він не відповідає синтаксису URI, вказаному в RFC." - Я думаю, що це цікаве питання - але чи дотримується клієнт "специфікацію" навряд чи хороший стандарт для того, чи розумно це робити у веб-додатку.
Метт Хоуелл

6
Хоча ця методика, мабуть, мало відома, вона підтримується у всіх веб-браузерах. Це працює просто чудово.
Нед Батчелдер

8
Цікаво, чому Google не використовує це для аналітики. Вони використовують метод document.location.protocol.
Дарріл Хайн

5
@Darryl Hein Я вважаю, що Google використовує метод document.location.protocol, оскільки він також модифікує URL, а не лише схему. Вони переходять на SSL.google-analytics.com, якщо документ використовує схему https.
Нік Мелдрум

18
Google не використовує це, оскільки мережевий стек Windows XP не підтримує SNI. Дивіться тут: blogs.msdn.com/b/ieinternals/archive/2009/12/07 / ... . Тому дозволяючи завантажувати скрипт аналітики google через https на IE6, це призведе до помилки сертифіката.
Eilistraee

152

Це гарантовано працювати в будь-якому основному браузері (я не беру до уваги браузери з меншою часткою ринку менше 0,05%). Чорт, він працює в Internet Explorer 3.0.

RFC 3986 визначає URI як складений з таких частин:

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

Визначаючи відносні URI ( Розділ 5.2 ), ви можете опустити будь-який з цих розділів, завжди починаючи зліва. У псевдокоді це виглядає приблизно так:

 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, який ви описуєте, є відносним URI без схеми.


1
Так, я гадаю, я вважав, що схема і повноваження завжди взаємозалежні. Має сенс, що це не так, але це не те, з чим я стикався зовсім недавно.
Кріс

1
Працювати в будь-якому браузері не гарантовано. Гарантовано працювати лише в браузерах, які слідкують за RFC.

2
@Roger Pate: Я ще не бачив браузера, який не слідкує за RFC для URI. Цей конкретний стандарт існує так довго ... Я щойно перевірив його в IE3.0, і він це прекрасно розуміє. Якщо ви потрапляєте на браузер, який не розуміє цих посилань, швидше за все, це такий маргінальний браузер, що це не має значення.
Ендрю Мур

1
@Andrew: Можливо, ти відрізняєшся від мене, але коли я кажу "гарантія" в контексті програмування, я дійсно маю на увазі "немає способу, що це може, коли-небудь вийти з ладу", не просто "це працює лише в популярних реалізаціях, які я" я перевірений ". Я не хотів зробити з цього великої справи, але це здавалося досить важливим.

4
@Roger: Так, але в контексті розробки веб-сайтів граничні браузери (<0,01% ринку) не враховуються. Це як би сказати, що API присутній у всіх версіях Windows, а потім хтось приходить, щоб сказати, що він може не підтримуватися у Wine ...
Ендрю Мур

79

чи є випадки, коли це не працює?

Якщо батьківська сторінка була завантажена з file://, вона, ймовірно, не працює (вона спробує отримати file://cdn.example.com/js_file.js, що, звичайно, ви могли б також надати локально).


19
Треба знати хлопцям, які тестують html на локальній машині!
Philip007

аргу ... недарма мій script src="//..."не працював! Я відкривав HTML-файл локально!
wisbucky

Хтось знає спосіб цього?
km6zla

@ ogc-nick: Ви можете запустити локальний веб-сервер. На сьогоднішній день безліч варіантів, з нульовою конфігурацією. Так чи інакше, як і багато інших речей (наприклад, XHR або веб-працівники, також не працюють для файлу: домен)
Thilo

@Thilo Це працює для мене тимчасово, але я роблю додаток з Github's Electron, і це стає дещо складніше.
km6zla

41

Багато людей називають це відносною URL-адресою протоколу.

Це спричиняє подвійне завантаження CSS-файлів в IE 7 і 8 .


@AndrewMoore Оскільки "річ", що виключається, позначає веб-протокол, називаючи його "відносно протоколу" має більше сенсу. Я ніколи не чув, щоб ftp або http називались "схемами" ...
Серін

25

Тут я дублюю відповідь у прихованих функціях HTML :

Використання абсолютного незалежного від протоколу шляху:

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

Якщо браузер переглядає сторінку в SSL через HTTPS, він запитає цей ресурс за допомогою протоколу https, інакше він запитає його за допомогою HTTP.

Це запобігає тому жахливому повідомленню про помилку "Ця сторінка містить захищені та незахищені елементи" в IE, зберігаючи всі ваші запити активів в одному протоколі.

Caveat: При використанні в <link>або @ імпорті для таблиці стилів IE7 та IE8 завантажують файл двічі . Однак, всі інші види використання є просто чудовими.


17

Цілком справедливо відмовитися від протоколу. Спеціалізація URL була чітко зрозуміла з цього приводу протягом багатьох років, і я ще не знайшов браузера, який не розуміє цього. Я не знаю, чому ця методика не краще відома; це ідеальне рішення кричущої проблеми перетину меж HTTP / HTTPS. Детальніше тут: переходи Http-https та відносні URL-адреси


7

чи є випадки, коли це не працює?

Просто кинути це в суміш, якщо ви розробляєте на локальному сервері, це може не спрацювати. Потрібно вказати схему, інакше веб-переглядач може припустити, що src="//cdn.example.com/js_file.js"вона src="file://cdn.example.com/js_file.js"буде зламаною, оскільки ви не розміщуєте цей ресурс локально.

Microsoft Internet Explorer, здається, особливо чутливий до цього, див. Це питання: Не вдається завантажити jQuery в Internet Explorer на localhost (WAMP)

Ви, ймовірно, завжди намагатиметесь знайти рішення, яке працює для всіх ваших середовищ із найменшою кількістю необхідних модифікацій.

Рішення, яке використовується HTML5Boilerplate, полягає в тому, щоб мати резервний запас, коли ресурс не завантажений правильно, але це працює лише за умови включення чека:

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

ОНОВЛЕННЯ: HTML5Boilerplate тепер використовується <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jsпісля прийняття рішення про зняття відносних URL-адрес протоколів, див. [Тут] [3].


4

Виходячи з посилання на gnud, у розділі 5.2 RFC 3986 сказано:

Якщо компонент схеми визначений, що вказує на те, що посилання починається з назви схеми, то посилання інтерпретується як абсолютний URI і ми закінчили. В іншому випадку схема опорного URI успадковується від базового компонента схеми URI .

Так //правильно :-)


3

Так, це зафіксовано в RFC 3986 , розділ 5.2:

(редагувати: На жаль, моя посилання RFC застаріла).


3

Це дійсно правильно, як сказано в інших відповідях. Слід зауважити, що деякі веб-сканери запускають 404 для цього, запитуючи їх на вашому сервері, немов локальну URL-адресу. (Вони нехтують подвійною косою рисою і трактують її як єдину косу рису).

Ви можете налаштувати на своєму веб-сервері правило, щоб виловити їх та перенаправити.

Наприклад, за допомогою Nginx можна додати щось на кшталт:

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

Однак зауважте, що якщо ви використовуєте періоди у своїх URI, вам потрібно буде збільшити специфіку, інакше це призведе до перенаправлення цих сторінок на неіснуючі домени.

Крім того, це досить масивний регулярний вираз, який повинен працювати для кожного запиту - на мою думку, варто покарати невідповідні браузери 404s за (незначну) ефективність у більшості сумісних браузерів.


3

Ми спостерігаємо 404 помилки в наших журналах, коли //somedomain.com використовуємо як посилання на файли JS.

Посилання, які викликають 404, виглядають так: ref:

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

Запит 404:

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

Якщо вони регулярно відображаються в журналах нашого веб-сервера, можна з упевненістю сказати, що: Усі браузери та боти НЕ шанують RFC 3986, розділ 4.2. Найбезпечніша ставка - включити протокол, коли це можливо.


Так, я якось відключився від цього, але не через 404 (я ніколи не бачив жодних 404-х ... якщо бот не шанує цього, я міг би потурбуватися менше) - тому що я більше не завантажую ресурси з інші CDN, тому мені не потрібно цього робити (замість цього я максимально об'єдную в 1 або 2 файли).
Дарріл Хайн

1
Будь ласка, включіть протокол. У моїй програмі Кордова перерва на відмову від протоколів.
пгорсіра

3

1. Підсумок

Відповідь на 2019 рік: ви все ще можете використовувати URL-адреси щодо протоколу, але ця методика є антидіаграмою .

Також:

  1. У вас можуть виникнути проблеми в розвитку.
  2. Деякі сторонні інструменти можуть не підтримувати їх.

Перехід від URL-адрес, що відносяться до протоколу, https://було б непогано.


2. Актуальність

Ця відповідь актуальна для січня 2019 року. Надалі дані цієї відповіді можуть бути застарілими.


3. Антидіаграма

3.1. Аргументація

Пол Ірландський - інженер-розробник та прихильник розробника Google Chrome - напишіть у 2014 році, грудень :

Тепер, коли SSL заохочується для всіх і не має проблем із ефективністю , ця методика тепер є антидіаграмою . Якщо потрібний вам ресурс доступний у SSL, то завжди використовуйте його https://.

Дозвіл фрагменту запитувати HTTP відкриває двері для таких атак, як недавня атака GitHub Man-on-the-Side . Завжди безпечно запитувати активи HTTPS, навіть якщо ваш сайт перебуває на HTTP, однак зворотне не відповідає дійсності .

3.2. Ще посилання

3.3. Приклади


4. Процес розробки

Наприклад, я намагаюся використовувати чисту консоль .

  • Приклад файлу 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/jquery@3.3.1/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>
  • вихід:
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/jquery@3.3.1/dist/jquery.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error opening //cdn.jsdelivr.net/npm/jquery@3.3.1/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/bowser@2.1.0/bowser.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error downloading https://unpkg.com/bowser@2.1.0/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

Посилання //cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.jsдійсне, але я отримую помилку.

Зверніть увагу file://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.jsі прочитайте відповіді про Thilo та bg17awfile:// .

Я не знав про таку поведінку і не міг зрозуміти, чому у мене такі проблеми із сторінками .


5. Сторонні інструменти

Я використовую пакунки з URL-адресами Sublime Text. Використовуючи це, я можу просто відкривати посилання зі свого текстового редактора в браузері.

Приклади посилань CSS

Обидва посилання в прикладі дійсні. Але перше посилання, яке я можу успішно відкрити в браузері, використовує URL-адреси, що натискають, друге посилання - ні. Це може бути не дуже зручно.


6. Висновок

Так:

  1. Якщо у вас є проблеми, як в Developing process предметі, ви можете встановити робочий процес розвитку.
  2. Якщо у вас є проблеми, як у Third-party toolsпредметі, ви можете внести інструменти.

Але вам не потрібні додаткові проблеми. Прочитайте інформацію за посиланнями в Anti-patternпункті: URL-адреси щодо протоколів застаріли.


2

Шаблон, який я бачу на коробці html5 :

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

Вона проходить гладко на різних схемах , таких як http, https, file.


Це більше не відповідає дійсності, дивіться stackoverflow.com/a/37609402/2237601 або тут , вони зараз використовують https://для всього
bg17aw

@ bg17aw Проблема використання https://скрізь полягає в тому, що потім вам доведеться постійно перевіряти всі ваші зовнішні посилання, щоб побачити, чи підтримують вони насправді, і змінити їх, http://якщо вони не працюють (інакше вони не працюватимуть). Це може бути проблематично з великою кількістю посилань.
tomasz86

@ tomasz86 вам не вистачає суті, я лише зазначав конкретний випадок посилання на вміст із CDN. https: // є обов'язковим для цього. Відповідь також говорить про конкретний випадок (html5-plateplate). Як ви говорите, немає "перевірки на http", оскільки CDN завжди використовують https.
bg17aw

@ bg17aw Це правда, але загальне питання тут стосується не лише CDN. Читаючи лише цю відповідь / коментар, легко подумати, що https://слід (або можна) використовувати в усіх посиланнях, що не є правильним.
tomasz86

@ tomasz86 Краса отримання декількох відповідей полягає в тому, що хоча жодна з них не є ідеальною (якщо відповідь була б ідеальною, інші потрібно було б видалити), прочитавши декілька з них, ми надаємо більш широке уявлення. У цьому випадку у відповіді йдеться про те, що "шаблон на html5boilerplate є ...", і мій коментар доповнює цю відповідь, згадуючи "що це більше не шаблон на html5-котлі". Це воно. Необхідне доповнення до цієї конкретної відповіді. Також врахуйте, що оригінальне запитання справді стосується CDN!
bg17aw

1

Як ваш приклад посилається на зовнішній домен, якщо ви використовуєте HTTPS, то ви повинні переконатися, що зовнішній домен також встановлений для SSL. В іншому випадку ваші користувачі можуть бачити помилки SSL та / або 404 помилки (наприклад, старіші версії Plesk зберігають HTTP та HTTPS в окремих папках). Для CDN це не повинно бути проблемою, але для будь-якого іншого веб-сайту це може бути.

Зі сторони, протестована під час оновлення старого веб-сайту, а також працює в URL-адресі = частина МЕТАЛЬНОГО СПИСКУ.

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