Допустимо ли заменить 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.
Здесь я продублирую ответ в " Скрытых возможностях 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-адреса, относящиеся к протоколу, но этот метод - анти-паттерн
Также:
- У вас могут быть проблемы в развитии.
- Некоторые сторонние инструменты могут не поддерживать их.
Миграция с относящихся к протоколу URL-адресов на https://
это было бы хорошо.
2. Актуальность
Этот ответ актуален для января 2019 года. В дальнейшем данные этого ответа могут устареть.
3. Анти-шаблон
3.1. аргументация
Пол Ириш (Paul Irish) - инженер-фронтовик и адвокат разработчика для Google Chrome - напишите в декабре 2014 года:
Теперь, когда SSL поощряется для всех и не имеет проблем с производительностью, этот метод теперь является анти-паттерном. Если нужный вам актив доступен по SSL, то всегда используйте
https://
актив.Разрешение фрагменту запрашивать по HTTP открывает двери для атак, таких как недавняя атака GitHub "Человек на стороне". Всегда безопасно запрашивать HTTPS-ресурсы, даже если ваш сайт работает по протоколу HTTP, однако обратное неверно.
3.2. Другие ссылки
- Загружает ресурсы страницы, используя относительные URI протокола
- Прекратить использование URL-адресов, относящихся к протоколу
3.3. Примеры
- В 2017 году переполнение стека перешло с URL-адресов, относящихся к протоколу, на
https
- В 2018 году Chrome пометит все незашифрованные веб-сайты как "небезопасные".
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. Используйте его, я могу просто открыть ссылки из моего текстового редактора в браузере.
Обе ссылки в примере действительны. Но первая ссылка, которую я могу успешно открыть в браузере, использует кликабельные URL, вторая ссылка - нет. Это может быть не очень удобно.
6. Заключение
Да:
- Если у вас есть проблемы, как в
Developing process
пункт, вы можете установить ваш рабочий процесс разработки. - Остальное у вас проблемы как в
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.