Допустимо ли заменить http:// на // в <script src = "http://...">?

У меня есть следующий элемент:

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

Кажется, это работает везде, где я тестировал, но есть ли случаи, когда это не работает?

14 ответов

Решение

Относительный URL-адрес без схемы (http: или https:) действителен для RFC 3986: "Универсальный идентификатор ресурса (URI): общий синтаксис", раздел 4.2. Если клиент его подавляет, то это вина клиента, поскольку он не соответствует синтаксису URI, указанному в RFC.

Ваш пример действителен и должен работать. Я сам использовал этот метод относительных URL на сайтах с интенсивным трафиком и у меня не было жалоб. Также мы тестируем наши сайты в Firefox, Safari, IE6, IE7 и Opera. Все эти браузеры понимают этот формат URL.

Он гарантированно работает в любом основном браузере (я не беру браузеры с долей рынка менее 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 без схемы.

Есть ли случаи, когда это не работает?

Если родительская страница была загружена с file://, то это, вероятно, не работает (он будет пытаться получить file://cdn.example.com/js_file.jsчто, конечно, вы могли бы предоставить и на местном уровне).

Многие люди называют этот протокол относительным URL.

Это вызывает двойную загрузку файлов CSS в IE 7 и 8.

Здесь я продублирую ответ в " Скрытых возможностях HTML":

Используя независимый от протокола абсолютный путь:

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

Если браузер просматривает страницу по протоколу SSL через HTTPS, он запрашивает этот ресурс по протоколу https, в противном случае он запрашивает его по HTTP.

Это предотвращает появление этого ужасного сообщения об ошибке "Эта страница содержит как защищенные, так и незащищенные элементы" в IE, сохраняя все ваши запросы активов в одном протоколе.

Предостережение: при использовании на <link> или @import для таблицы стилей, IE7 и IE8 загружают файл дважды. Тем не менее, все остальные варианты применения вполне приемлемы.

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

Есть ли случаи, когда это не работает?

Просто добавьте это в смесь, если вы разрабатываете на локальном сервере, это может не сработать. Вам нужно указать схему, иначе браузер может предположить, что 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].

1. Резюме

Ответ за 2019 год: вы все еще можете использовать URL-адреса, относящиеся к протоколу, но этот метод - анти-паттерн

Также:

  1. У вас могут быть проблемы в развитии.
  2. Некоторые сторонние инструменты могут не поддерживать их.

Миграция с относящихся к протоколу URL-адресов на https:// это было бы хорошо.


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

Этот ответ актуален для января 2019 года. В дальнейшем данные этого ответа могут устареть.


3. Анти-шаблон

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

Пол Ириш (Paul Irish) - инженер-фронтовик и адвокат разработчика для Google Chrome - напишите в декабре 2014 года:

Теперь, когда SSL поощряется для всех и не имеет проблем с производительностью, этот метод теперь является анти-паттерном. Если нужный вам актив доступен по SSL, то всегда используйте https:// актив.

Разрешение фрагменту запрашивать по HTTP открывает двери для атак, таких как недавняя атака GitHub "Человек на стороне". Всегда безопасно запрашивать HTTPS-ресурсы, даже если ваш сайт работает по протоколу HTTP, однако обратное неверно.

3.2. Другие ссылки

3.3. Примеры


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

Например, я пытаюсь использовать clean-console.

  • Пример файла 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 и прочитайте ответы Тило и bg17aw о file://,

Я не знал об этом поведении и не мог понять, почему у меня такие проблемы с Pageres.


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

Я использую кликабельные URL-адреса Sublime Text. Используйте его, я могу просто открыть ссылки из моего текстового редактора в браузере.

Примеры CSS-ссылок

Обе ссылки в примере действительны. Но первая ссылка, которую я могу успешно открыть в браузере, использует кликабельные URL, вторая ссылка - нет. Это может быть не очень удобно.


6. Заключение

Да:

  1. Если у вас есть проблемы, как в Developing process пункт, вы можете установить ваш рабочий процесс разработки.
  2. Остальное у вас проблемы как в Third-party tools предмет, вы можете внести инструменты.

Но вам не нужны эти дополнительные проблемы. Читайте информацию по ссылкам в Anti-pattern item: относящиеся к протоколу URL устарели.

Следуя указаниям gnud, в разделе 5.2 RFC 3986 говорится:

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

Так // верно:-)

Да, это задокументировано в RFC 3986, раздел 5.2:

(редактировать: Ой, моя ссылка на RFC устарела).

Это действительно правильно, как утверждают другие ответы. Однако вы должны заметить, что некоторые веб-сканеры установят для них значение 404, запрашивая их на своем сервере, как если бы они были локальными. (Они игнорируют двойной слеш и рассматривают его как один слэш).

Вы можете настроить правило на своем веб-сервере, чтобы перехватывать их и перенаправлять.

Например, с Nginx вы бы добавили что-то вроде:

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

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

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

Мы видим 404 ошибки в наших журналах при использовании //somedomain.com в качестве ссылок на файлы JS.

Ссылки, которые вызывают 404-е годы, выглядят так: ref:

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

404 запроса:

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

Когда они регулярно появляются в журналах нашего веб-сервера, можно с уверенностью сказать, что: Все браузеры и боты НЕ соблюдают раздел 4.2 RFC 3986. Самым безопасным вариантом является включение протокола, когда это возможно.

Шаблон, который я вижу на 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,

Так как ваш пример связан с внешним доменом, если вы используете HTTPS, вы должны убедиться, что внешний домен также настроен для SSL. В противном случае ваши пользователи могут увидеть ошибки SSL и / или ошибки 404 (например, старые версии Plesk хранят HTTP и HTTPS в отдельных папках). Для CDN это не должно быть проблемой, но для любого другого сайта это может быть.

С другой стороны, проверено при обновлении старого сайта, а также работает в части url= META REFRESH.

Другие вопросы по тегам