Czy warto zamienić http: // na // w <script src = „http: //…”>?

458

Mam następujący element:

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

W takim przypadku witryna to HTTPS, ale może to być również HTTP. (Plik JS znajduje się w innej domenie.) Zastanawiam się, czy dla wygody można wykonać następujące czynności:

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

Zastanawiam się, czy usunięcie http:lub jest poprawne https:?

Wydaje się, że działa wszędzie, gdzie testowałem, ale czy są jakieś przypadki, w których nie działa?

Darryl Hein
źródło
2
Czy „wydaje się, że wszędzie działa” można uogólnić na obrazy, ramki iframe, odnośniki itp.? To interesujące rzeczy, jeśli tak.
12345
Tak, powinien działać w każdym miejscu, które wymaga podania identyfikatora URI: obrazy, linki itp. Może być rzadkie, aby zobaczyć to w użyciu, ale jest całkowicie poprawne.
Jeff
1
Co słychać u tych natychmiastowych fanów? Nie chodzi o to, że pytanie jest złe lub coś w tym rodzaju, jestem po prostu ciekawy. Ale założę się, że wstępna reputacja Chrisa ma wpływ.
Frederik Wordenskjold
13
@Frederik: Ponieważ jest to fascynująca i przydatna sztuczka, której większość ludzi najwyraźniej nie zdaje sobie sprawy.
SLaks,
8
@Frederik: Co?
SLaks,

Odpowiedzi:

387

Względny adres URL bez schematu (http: lub https :) jest prawidłowy, zgodnie z RFC 3986: „Identyfikator URI: jednolita składnia”, sekcja 4.2 . Jeśli klient dusi się na nim, jest to wina klienta, ponieważ nie przestrzega składni URI określonej w RFC.

Twój przykład jest prawidłowy i powinien działać. Użyłem tej metody względnego adresu URL na stronach o dużym natężeniu ruchu i nie otrzymałem żadnych skarg. Testujemy również nasze witryny w Firefox, Safari, IE6, IE7 i Opera. Wszystkie te przeglądarki rozumieją ten format adresu URL.

Jeff
źródło
30
„Jeśli klient dusi się, to wina jego klienta, ponieważ nie przestrzega składni URI określonej w RFC.” - Myślę, że to interesujące pytanie - ale to, czy klient postępuje zgodnie ze „specyfikacją”, nie jest dobrym standardem dla tego, czy mądrze jest to zrobić w aplikacji internetowej.
Matt Howell,
6
Chociaż technika ta wydaje się mało znana, jest obsługiwana we wszystkich przeglądarkach internetowych. Działa po prostu świetnie.
Ned Batchelder
8
Zastanawiam się, dlaczego Google nie używa tego do analiz. Używają metody document.location.protocol.
Darryl Hein
5
@Darryl Hein Uważam, że Google używa metody document.location.protocol, ponieważ modyfikuje również adres URL, a nie tylko schemat. Przechodzą na stronę SSL.google-analytics.com, jeśli dokument korzysta ze schematu https.
Nick Meldrum,
18
Google nie używa tego, ponieważ stos sieciowy Windows XP nie obsługuje SNI. Zobacz tutaj: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Dlatego zezwolenie na ładowanie skryptu Google Analytics za pośrednictwem protokołu https w IE6 spowoduje błąd certyfikatu.
Eilistraee
152

Gwarantujemy, że będzie działać w dowolnej głównej przeglądarce (nie biorę pod uwagę przeglądarek z mniejszym niż 0,05% udziałem w rynku). Do licha, działa w przeglądarce Internet Explorer 3.0.

RFC 3986 definiuje identyfikator URI składający się z następujących części:

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

Podczas definiowania względnych identyfikatorów URI ( sekcja 5.2 ) można pominąć dowolną z tych sekcji, zawsze zaczynając od lewej. W pseudokodzie wygląda to tak:

 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;

Opisywany identyfikator URI jest względnym identyfikatorem URI bez schematu.

Andrew Moore
źródło
1
Tak, myślę, że myślałem, że schemat i autorytet zawsze były od siebie zależne. To ma sens, że tak nie jest, ale do niedawna tego nie spotkałem.
Chris
1
Nie gwarantuje się działania w dowolnej przeglądarce. Gwarantuje to, że działa tylko w przeglądarkach zgodnych z RFC.
2
@Roger Pate: Nie widziałem jeszcze przeglądarki, która nie przestrzega RFC dla URI. Ten konkretny standard istnieje już od tak dawna ... Właśnie przetestowałem go w IE3.0 i doskonale to rozumie. Jeśli wpadniesz na przeglądarkę, która nie rozumie tych linków, są szanse, że jest to tak marginalna przeglądarka, że ​​nie będzie to miało znaczenia.
Andrew Moore,
1
@Andrew: Być może różnisz się ode mnie, ale kiedy mówię „gwarancja” w kontekście programowania, naprawdę mam na myśli „nie ma możliwości, aby to kiedykolwiek mogło się nie powieść”, nie tylko „działa to tylko w popularnych implementacjach, które ja” przetestowałem ”. Nie chciałem robić z tego wielkiej sprawy, ale wydawało mi się to wystarczająco ważne, aby o tym wspomnieć.
4
@Roger: Tak, ale w kontekście tworzenia stron internetowych marginalne przeglądarki (<0,01% udziału w rynku) nie są brane pod uwagę. To tak, jakby powiedzieć, że interfejs API jest obecny we wszystkich wersjach systemu Windows, a potem ktoś mówi, że może nie być obsługiwany w Wine ...
Andrew Moore
79

czy są jakieś przypadki, w których to nie działa?

Jeśli strona nadrzędna została załadowana file://, to prawdopodobnie nie działa (spróbuje uzyskać file://cdn.example.com/js_file.js, co oczywiście możesz również podać lokalnie).

Thilo
źródło
19
Musi wiedzieć dla facetów testujących HTML na lokalnej maszynie!
Philip007
argh ... nic dziwnego, że mój script src="//..."nie działał! Otwierałem plik HTML lokalnie!
wisbucky
Czy ktoś wie, jak to obejść?
km6zla
@ ogc-nick: Możesz uruchomić lokalny serwer WWW. Wiele opcji w dzisiejszych czasach, przy zerowej konfiguracji. Tak czy inaczej, ponieważ wiele innych rzeczy (takich jak XHR lub pracownicy sieci również nie działają dla pliku: domena)
Thilo
@Thilo To działało tymczasowo dla mnie, ale tworzę aplikację z Github's Electron i to staje się trochę bardziej skomplikowane.
km6zla,
41

Wiele osób nazywa to relatywnym adresem URL protokołu.

Powoduje to podwójne pobranie plików CSS w IE 7 i 8 .

SLaks
źródło
@AndrewMoore Ponieważ wykluczenie „rzecz” oznacza protokół internetowy, nazwanie go „względnym protokołem” ma sens. Nigdy nie słyszałem o ftp lub http nazywanych „schematami” ...
Cerin,
25

Tutaj powielam odpowiedź w Ukrytych funkcjach HTML :

Korzystanie z bezwzględnej ścieżki niezależnej od protokołu:

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

Jeśli przeglądarka przegląda stronę w SSL za pośrednictwem HTTPS, zażąda tego zasobu za pomocą protokołu https, w przeciwnym razie zażąda tego za pomocą HTTP.

Zapobiega to okropnemu komunikatowi o błędzie „Ta strona zawiera zarówno elementy zabezpieczone, jak i niezabezpieczone” w IE, utrzymując wszystkie żądania zasobów w tym samym protokole.

Ostrzeżenie: W przypadku użycia w <link>lub w imporcie arkusza stylów IE7 i IE8 dwukrotnie pobierają plik . Wszystkie pozostałe zastosowania są jednak w porządku.

kennytm
źródło
17

Całkowicie uzasadnione jest pominięcie protokołu. Specyfikacja adresu URL jest od lat bardzo jasna i jeszcze nie znalazłem przeglądarki, która tego nie rozumie. Nie wiem, dlaczego ta technika nie jest lepiej znana; to idealne rozwiązanie drażliwego problemu przekraczania granic HTTP / HTTPS. Więcej tutaj: Przejścia Http-https i względne adresy URL

Ned Batchelder
źródło
7

czy są jakieś przypadki, w których to nie działa?

Wystarczy wrzucić to do miksu, jeśli tworzysz na lokalnym serwerze, może nie działać. Musisz podać schemat, w przeciwnym razie przeglądarka może zakładać, że src="//cdn.example.com/js_file.js"to src="file://cdn.example.com/js_file.js", co złamie ponieważ nie jesteś gospodarzem tego zasobu lokalnie.

Microsoft Internet Explorer wydaje się być szczególnie wrażliwy na to, zobacz to pytanie: Nie można załadować jQuery w Internet Explorerze na localhost (WAMP)

Prawdopodobnie zawsze starałbyś się znaleźć rozwiązanie, które działa we wszystkich twoich środowiskach przy minimalnej ilości potrzebnych modyfikacji.

Rozwiązaniem używanym przez HTML5Boilerplate jest wycofanie się, gdy zasób nie zostanie poprawnie załadowany, ale działa to tylko wtedy, gdy uwzględnisz czek:

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

AKTUALIZACJA: HTML5Boilerplate używa teraz <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jspo podjęciu decyzji o wycofaniu względnych adresów URL protokołu, patrz [tutaj] [3].

bg17aw
źródło
4

Zgodnie z odniesieniem gnuda, RFC 3986 sekcja 5.2 mówi:

Jeśli komponent schematu jest zdefiniowany, co wskazuje, że odwołanie zaczyna się od nazwy schematu, wówczas odwołanie jest interpretowane jako bezwzględny identyfikator URI i gotowe. W przeciwnym razie schemat referencyjnego identyfikatora URI jest dziedziczony z podstawowego komponentu schematu URI .

Tak //jest poprawne :-)

Pablo Torrecilla
źródło
3

Tak, jest to udokumentowane w RFC 3986 , sekcja 5.2:

(edycja: Ups, moje odniesienie do RFC było nieaktualne).

gnud
źródło
3

Jest to rzeczywiście poprawne, jak stwierdzono w innych odpowiedziach. Należy jednak pamiętać, że niektóre roboty indeksujące uruchomią dla nich 404, żądając ich na serwerze, jakby to był lokalny adres URL. (Ignorują podwójny ukośnik i traktują go jako pojedynczy ukośnik).

Możesz ustawić regułę na swoim serwerze internetowym, aby złapać je i przekierować.

Na przykład w Nginx można dodać coś takiego:

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

Pamiętaj jednak, że jeśli używasz kropek w swoich identyfikatorach URI, musisz zwiększyć specyficzność, w przeciwnym razie spowoduje to przekierowanie tych stron do nieistniejących domen.

Ponadto jest to dość masywne wyrażenie regularne, które należy uruchamiać dla każdego zapytania - moim zdaniem warto ukarać przeglądarki niezgodne 404s za (niewielki) spadek wydajności w większości zgodnych przeglądarek.

jlovison
źródło
3

Podczas używania //somedomain.com jako odniesień do plików JS widzimy błędy 404 w naszych logach.

Referencje, które powodują 404, wyglądają tak: ref:

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

Żądanie 404:

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

Ponieważ są one regularnie wyświetlane w dziennikach naszego serwera WWW, można śmiało powiedzieć, że: Wszystkie przeglądarki i boty NIE honorują RFC 3986 sekcja 4.2. Najbezpieczniejszym zakładem jest dołączenie protokołu w miarę możliwości.

Lemiarty
źródło
Tak, w pewnym sensie zrezygnowałem z niego, ale nie z powodu 404s (nigdy nie widziałem żadnych 404s ... jeśli bot tego nie honoruje, nie obchodzi mnie to) - ponieważ nie ładuję już zasobów z inne CDN, więc nie muszę tego robić (zamiast tego dzielę tak dużo, jak to możliwe na 1 lub 2 pliki).
Darryl Hein
1
Proszę dołączyć protokół. W protokole Cordova psują się odwołania bez protokołu.
pgorsira
3

1. Podsumowanie

Odpowiedź na rok 2019: nadal możesz używać adresów URL zależnych od protokołu, ale ta technika jest anty-wzorcem .

Również:

  1. Możesz mieć problemy z rozwojem.
  2. Niektóre narzędzia innych firm mogą ich nie obsługiwać.

Migracja z adresów URL zależnych od protokołu https://byłaby miła.


2. Trafność

Ta odpowiedź dotyczy stycznia 2019 r. W przyszłości dane tej odpowiedzi mogą być nieaktualne.


3. Anty-wzór

3.1 Argumentacja

Paul Irish - inżynier i rzecznik programistów Google Chrome - napisz w 2014 r., Grudzień :

Teraz, gdy protokół SSL jest wspierany przez wszystkich i nie ma problemów z wydajnością , ta technika jest teraz anty-wzorcem . Jeśli potrzebny zasób jest dostępny w protokole SSL, zawsze używaj go https://.

Zezwolenie fragmentowi na żądanie przez HTTP otwiera drzwi do ataków, takich jak niedawny atak GitHub Man-on-the-side . Żądanie zasobów HTTPS jest zawsze bezpieczne, nawet jeśli witryna korzysta z HTTP, jednak odwrotna sytuacja nie jest prawdą .

3.2 Kolejne linki

3.3 Przykłady


4. Proces opracowywania

Na przykład próbuję użyć czystej konsoli .

  • Przykładowy plik 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>
  • wynik:
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

Link //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jsjest prawidłowy, ale pojawia się błąd.

Zwróć uwagę file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jsi przeczytaj Thilo i bg17aw odpowiedzi na tematfile://.

Nie wiedziałem o tym zachowaniu i nie mogłem zrozumieć, dlaczego mam takie problemy z pageres .


5. Narzędzia innych firm

Używam klikalnego pakietu URL Sublime Text. Użyj go, mogę po prostu otworzyć linki z mojego edytora tekstu w przeglądarce.

Przykłady linków CSS

Oba linki w przykładzie są prawidłowe. Ale pierwszy link, który mogę z powodzeniem otworzyć w przeglądarce, wykorzystuje klikalne adresy URL, drugi link - nie. To może nie być zbyt wygodne.


6. Wniosek

Tak:

  1. Jeśli masz problemy jak w Developing process pozycji, możesz ustawić przepływ pracy programistycznej.
  2. W przeciwnym razie masz problemy, ponieważ w Third-party toolselemencie możesz wnieść narzędzia.

Ale nie potrzebujesz tych dodatkowych problemów. Przeczytaj informacje według linków w Anti-patternelemencie: Adresy URL zależne od protokołu są nieaktualne.

Саша Черных
źródło
2

Wzór, który widzę na html5 -ilerplate jest:

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

To działa płynnie na różnych systemów, takich jak http, https, file.

neuryt
źródło
To już nie jest prawda, patrz stackoverflow.com/a/37609402/2237601 lub tutaj , teraz używają https://do wszystkiego
bg17aw
@ bg17aw Problem z używaniem https://wszędzie polega na tym, że musisz ciągle sprawdzać wszystkie linki zewnętrzne, aby zobaczyć, czy faktycznie je obsługują, i zmienić je na, http://jeśli nie działają (w przeciwnym razie nie będą działać). Może to być kłopotliwe w przypadku dużej liczby linków.
tomasz86
@ tomasz86 nie rozumiesz, chodzi mi tylko o konkretny przypadek linkowania do treści z CDN. https: // jest obecnie obowiązkowy. Odpowiedź mówi także o konkretnym przypadku (html5 -ilerplate). Nie ma „sprawdzania http”, jak mówisz, ponieważ sieci CDN zawsze używają teraz protokołu https.
bg17aw
@ bg17aw To prawda, ale ogólne pytanie tutaj nie dotyczy tylko CDN. Czytając tylko tę odpowiedź / komentarz, łatwo jest pomyśleć, że https://powinien (lub może) zostać użyty we wszystkich linkach, co jest nieprawidłowe.
tomasz86
@ tomasz86 Piękno posiadania wielu odpowiedzi polega na tym, że chociaż żadna z nich nie jest idealna (jeśli odpowiedź byłaby idealna, pozostałe trzeba by usunąć), przeczytanie kilku z nich daje nam szerszy widok. W tym przypadku odpowiedź brzmi „wzorzec na html5-kocioł jest…”, a mój komentarz aktualizuje tę odpowiedź, wspominając „że nie jest już wzorem na html5-kocioł”. Otóż ​​to. Potrzebny dodatek do tej konkretnej odpowiedzi. Pamiętaj też, że oryginalne pytanie rzeczywiście dotyczy CDN!
bg17aw
1

Ponieważ Twoim przykładem jest linkowanie do domeny zewnętrznej, jeśli używasz HTTPS, powinieneś sprawdzić, czy domena zewnętrzna jest skonfigurowana również dla SSL. W przeciwnym razie użytkownicy mogą zobaczyć błędy SSL i / lub błędy 404 (np. Starsze wersje Plesk przechowują HTTP i HTTPS w osobnych folderach). W przypadku CDN nie powinno to stanowić problemu, ale w przypadku każdej innej witryny może być.

Na marginesie, przetestowany podczas aktualizacji starej strony, a także działa w url = część META REFRESH.

użytkownik2246924
źródło