Допустимо ли заменить 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
Что со всеми этими парнями? Не то чтобы вопрос плохой или что-то еще, мне просто любопытно. Но держу пари, что первоначальная репутация Криса повлияла на меня.
Фредерик Ворденшельд

13
@Frederik: Потому что это увлекательный и полезный трюк, о котором большинство людей, видимо, не подозревают.
SLaks

8
@ Фредерик: Что?
Утро

Ответы:


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 Analytics через https на IE6 приведет к ошибке сертификата.
Эйлистри

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
@ Роджер Пэйт: я еще не видел браузер, который не следует RFC для URI. Этот конкретный стандарт существует уже так давно ... Я только что проверил его в IE3.0, и он прекрасно его понимает. Если вы попадете в браузер, который не понимает эти ссылки, скорее всего, это такой маргинальный браузер, что это не будет иметь значения.
Эндрю Мур

1
@Andrew: Может быть, вы отличаетесь от меня, но когда я говорю «гарантия» в контексте программирования, я действительно имею в виду «нет никакого способа, которым это может когда-либо провалиться», а не просто «это работает только в популярных реализациях, которые я» мы проверили. " Я не хотел делать из этого много, но это казалось достаточно важным, чтобы упомянуть.

4
@ Роджер: Да, но в контексте веб-разработки маргинальные браузеры (<0,01% рынка) не принимаются во внимание. Это все равно что сказать, что API присутствует во всех версиях Windows, а потом кто-то приходит, чтобы сказать, что он может не поддерживаться в Wine ...
Эндрю Мур

79

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

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


19
Должен знать для парней, тестирующих HTML на локальной машине!
Philip007

аааа ... не удивительно, что мой script src="//..."не работал! Я открывал HTML-файл локально!
wisbucky

Кто-нибудь знает способ обойти это?
km6zla

@ ogc-ник: Вы можете запустить локальный веб-сервер. Много вариантов в наши дни, с нулевой конфигурацией. В любом случае, вы этого хотите, так как многие другие вещи (например, XHR или веб-работники также не работают с файлом: домен)
Thilo

@ Thilo Это временно работает для меня, но я делаю приложение с Github's Electron, и это становится немного сложнее.
км6зла

41

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

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


@AndrewMoore Поскольку исключаемая «вещь» обозначает веб-протокол, называть его «относительным протоколом» имеет больше смысла. Я никогда не слышал о том, чтобы ftp или http назывались "схемами" ...
Cerin

25

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

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

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

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

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

Предостережение: при использовании в <link>или @import для таблицы стилей 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 на локальный хост (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, запрашивая их на своем сервере, как если бы они были локальными. (Они игнорируют двойную косую черту и рассматривают ее как одну косую черту).

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

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

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

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

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


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
Пожалуйста, включите протокол. Перерывы без протокола в моем приложении Cordova.
pgorsira

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элементе: относящиеся к протоколу 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-шаблон). Как вы говорите, «проверка на http» отсутствует, поскольку CDN теперь всегда используют https.
Bg17aw

@ bg17aw Это правда, но общий вопрос здесь касается не только CDN. Читая только этот ответ / комментарий, легко подумать, что https://следует (или можно) использовать во всех ссылках, что неправильно.
tomasz86

@ tomasz86 Прелесть наличия нескольких ответов заключается в том, что хотя ни один из них не является идеальным (если ответ будет идеальным, остальные нужно будет удалить), чтение нескольких из них дает нам более широкое представление. В этом случае ответ говорит: «шаблон на html5boilerplate - это ...», и мой комментарий обновляет этот ответ, упоминая «что это больше не шаблон на html5 -айлплате». Вот и все. Необходимое дополнение к этому конкретному ответу. Также обратите внимание, что оригинальный вопрос действительно о CDN!
bg17aw

1

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.