Ist es gültig, http: // in einem <script src = “http: //…”> durch // zu ersetzen?

458

Ich habe folgendes Element:

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

In diesem Fall ist die Site HTTPS, aber die Site kann auch nur HTTP sein. (Die JS-Datei befindet sich in einer anderen Domäne.) Ich frage mich, ob es aus praktischen Gründen gültig ist, Folgendes zu tun:

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

Ich frage mich, ob es gültig ist, das http:oder zu entfernen https:?

Es scheint überall zu funktionieren, wo ich es getestet habe, aber gibt es Fälle, in denen es nicht funktioniert?

Darryl Hein
quelle
2
Kann das "es scheint überall zu funktionieren" auf Bilder, Iframes, Link-Rels usw. usw. verallgemeinert werden? Das ist interessant, wenn ja.
12345
Ja, es sollte an jedem Ort funktionieren, an dem eine URI erforderlich ist: Bilder, Links usw. Es kann selten vorkommen, dass dies verwendet wird, aber es ist vollkommen gültig.
Jeff
1
Was ist mit all den sofortigen Upvoting-Jungs? Nicht dass die Frage schlecht ist oder so, ich bin nur neugierig. Aber ich wette, Chris 'anfänglicher Ruf hat Einfluss.
Frederik Wordenskjold
13
@Frederik: Weil es ein faszinierender und nützlicher Trick ist, den die meisten Leute anscheinend nicht kennen.
SLaks
8
@ Frederick: Was?
SLaks

Antworten:

387

Eine relative URL ohne Schema (http: oder https :) ist gemäß RFC 3986 gültig : "URI (Uniform Resource Identifier): Generic Syntax", Abschnitt 4.2 . Wenn ein Client daran erstickt, ist dies die Schuld des Clients, da er die im RFC angegebene URI-Syntax nicht einhält.

Ihr Beispiel ist gültig und sollte funktionieren. Ich habe diese relative URL-Methode selbst auf stark frequentierten Websites verwendet und hatte keine Beschwerden. Außerdem testen wir unsere Websites in Firefox, Safari, IE6, IE7 und Opera. Diese Browser verstehen alle dieses URL-Format.

Jeff
quelle
30
"Wenn ein Client daran erstickt, ist der Client schuld, weil er die im RFC angegebene URI-Syntax nicht einhält." - Ich denke, das ist eine interessante Frage - aber ob ein Kunde "der Spezifikation" folgt, ist kaum ein guter Standard dafür, ob es sinnvoll ist, dies in einer Web-App zu tun.
Matt Howell
6
Obwohl diese Technik wenig bekannt zu sein scheint, wird sie in allen Webbrowsern unterstützt. Es funktioniert einfach super.
Ned Batchelder
8
Ich frage mich, warum Google dies nicht für Analysen verwendet. Sie verwenden die Methode document.location.protocol.
Darryl Hein
5
@Darryl Hein Ich glaube, Google verwendet die Methode document.location.protocol, da es auch die URL ändert, nicht nur das Schema. Sie gehen zu SSL.google-analytics.com, wenn das Dokument das https-Schema verwendet.
Nick Meldrum
18
Google verwendet dies nicht, da der Windows XP-Netzwerkstapel SNI nicht unterstützt. Siehe hier: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Daher würde das Laden des Google Analytics-Skripts über https in IE6 zu einem Zertifikatfehler führen.
Eilistraee
152

Es funktioniert garantiert in jedem Mainstream-Browser (ich berücksichtige keine Browser mit einem Marktanteil von weniger als 0,05%). Heck, es funktioniert in Internet Explorer 3.0.

RFC 3986 definiert einen URI aus folgenden Teilen:

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

Wenn Sie relative URIs definieren ( Abschnitt 5.2 ), können Sie jeden dieser Abschnitte weglassen, immer von links beginnend. Im Pseudocode sieht es so aus:

 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;

Der von Ihnen beschriebene URI ist ein schemaloser relativer URI.

Andrew Moore
quelle
1
Ja, ich glaube, ich dachte, Schema und Autorität waren immer voneinander abhängig. Es macht Sinn, dass es nicht so ist, aber es ist nichts, was mir bis vor kurzem begegnet ist.
Chris
1
Es ist nicht garantiert, dass es in einem Browser funktioniert. Es funktioniert garantiert nur in Browsern, die dem RFC folgen.
2
@ Roger Pate: Ich habe noch keinen Browser gesehen, der dem RFC für URI nicht folgt. Dieser spezielle Standard gibt es schon so lange ... Ich habe ihn gerade in IE3.0 getestet und er versteht ihn vollkommen. Wenn Sie auf einen Browser stoßen, der diese Links nicht versteht, handelt es sich wahrscheinlich um einen so marginalen Browser, dass dies keine Rolle spielt.
Andrew Moore
1
@ Andrew: Vielleicht unterscheiden Sie sich von mir, aber wenn ich im Kontext der Programmierung "Garantie" sage, meine ich wirklich "es gibt keine Möglichkeit, dass dies jemals scheitern kann", nicht nur "es funktioniert nur in populären Implementierungen, die ich ' habe getestet. " Ich wollte keine große Sache daraus machen, aber es schien wichtig genug zu sein, um es zu erwähnen.
4
@ Roger: Ja, aber im Rahmen der Webentwicklung werden marginale Browser (<0,01% Marktanteil) nicht berücksichtigt. Es ist, als würde man sagen, dass eine API in allen Windows-Versionen vorhanden ist, und dann sagt jemand, dass sie in Wine möglicherweise nicht unterstützt wird ...
Andrew Moore
79

Gibt es Fälle, in denen es nicht funktioniert?

Wenn die übergeordnete Seite von geladen wurde file://, funktioniert sie wahrscheinlich nicht (es wird versucht, sie abzurufen file://cdn.example.com/js_file.js, was Sie natürlich auch lokal bereitstellen können).

Thilo
quelle
19
Ein Muss für Leute, die HTML auf einem lokalen Computer testen!
Philip007
Argh ... kein Wunder, dass ich script src="//..."nicht funktionierte! Ich habe die HTML-Datei lokal geöffnet!
wisbucky
Kennt jemand einen Weg, um das zu umgehen?
km6zla
@ ogc-nick: Sie können einen lokalen Webserver ausführen. Heutzutage gibt es viele Optionen ohne Konfiguration. Sie wollen das sowieso, da viele andere Dinge (wie XHR oder Web-Worker auch nicht für die Datei: Domain funktionieren)
Thilo
@Thilo Das hat vorübergehend für mich funktioniert, aber ich mache eine App mit Githubs Electron und das wird etwas komplizierter.
km6zla
41

Viele Leute nennen dies eine protokollrelative URL.

Dies führt zu einem doppelten Download von CSS-Dateien in IE 7 und 8 .

SLaks
quelle
@AndrewMoore Da das ausgeschlossene "Ding" das Webprotokoll anzeigt, ist es sinnvoller, es als "protokollbezogen" zu bezeichnen. Ich habe noch nie davon gehört, dass FTP oder http "Schemata" genannt werden ...
Cerin
25

Hier dupliziere ich die Antwort in Versteckte Funktionen von HTML :

Verwenden eines protokollunabhängigen absoluten Pfads:

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

Wenn der Browser eine Seite in SSL über HTTPS anzeigt, fordert er dieses Asset mit dem https-Protokoll an, andernfalls fordert er es mit HTTP an.

Dies verhindert, dass die schreckliche Fehlermeldung "Diese Seite enthält sowohl sichere als auch nicht sichere Elemente" im IE alle Ihre Asset-Anforderungen innerhalb desselben Protokolls hält.

Vorsichtsmaßnahme: Bei Verwendung auf einem <link>oder @import für ein Stylesheet, IE7 und IE8 die Datei zweimal herunter . Alle anderen Verwendungen sind jedoch in Ordnung.

kennytm
quelle
17

Es ist absolut gültig, das Protokoll wegzulassen. Die URL-Spezifikation ist seit Jahren sehr klar, und ich habe noch keinen Browser gefunden, der sie nicht versteht. Ich weiß nicht, warum diese Technik nicht besser bekannt ist. Es ist die perfekte Lösung für das heikle Problem, HTTP / HTTPS-Grenzen zu überschreiten. Mehr hier: HTTP-https-Übergänge und relative URLs

Ned Batchelder
quelle
7

Gibt es Fälle, in denen es nicht funktioniert?

Nur um dies in den Mix zu werfen, wenn Sie auf einem lokalen Server entwickeln, funktioniert es möglicherweise nicht. Sie benötigen ein Programm angeben, sonst wird der Browser davon ausgehen kann , dass src="//cdn.example.com/js_file.js"ist src="file://cdn.example.com/js_file.js", was zu brechen , da Sie nicht auf diese Ressource lokal Hosting.

Microsoft Internet Explorer scheint hierfür besonders sensibel zu sein. Siehe folgende Frage: jQuery kann nicht in Internet Explorer auf localhost (WAMP) geladen werden.

Sie würden wahrscheinlich immer versuchen, eine Lösung zu finden, die in all Ihren Umgebungen mit den geringsten erforderlichen Änderungen funktioniert.

Die von HTML5Boilerplate verwendete Lösung besteht darin, einen Fallback zu haben, wenn die Ressource nicht korrekt geladen ist. Dies funktioniert jedoch nur, wenn Sie eine Prüfung einbinden :

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

UPDATE: HTML5Boilerplate wird jetzt verwendet, <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jsnachdem entschieden wurde, protokollbezogene URLs zu verwerfen (siehe [hier] [3]).

bg17aw
quelle
4

In Anlehnung an den Gnud-Verweis heißt es in Abschnitt 5.2 des RFC 3986 :

Wenn die Schemakomponente definiert ist und angibt, dass die Referenz mit einem Schemanamen beginnt, wird die Referenz als absoluter URI interpretiert und wir sind fertig. Andernfalls wird das Schema des Referenz-URI von der Schemakomponente des Basis-URI geerbt .

Also //ist richtig :-)

Pablo Torrecilla
quelle
3

Ja, dies ist in RFC 3986 , Abschnitt 5.2 dokumentiert :

(Bearbeiten: Ups, meine RFC-Referenz war veraltet).

Gnud
quelle
3

Es ist in der Tat richtig, wie andere Antworten angegeben haben. Sie sollten jedoch beachten, dass einige Webcrawler 404s für diese auslösen, indem sie sie auf Ihrem Server wie eine lokale URL anfordern. (Sie ignorieren den doppelten Schrägstrich und behandeln ihn als einfachen Schrägstrich).

Möglicherweise möchten Sie auf Ihrem Webserver eine Regel einrichten, um diese abzufangen und umzuleiten.

Mit Nginx würden Sie beispielsweise Folgendes hinzufügen:

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

Beachten Sie jedoch, dass Sie, wenn Sie Punkte in Ihren URIs verwenden, die Spezifität erhöhen müssen, da diese Seiten sonst in nicht vorhandene Domänen umgeleitet werden.

Dies ist auch ein ziemlich massiver Regex, der für jede Abfrage ausgeführt werden muss. Meiner Meinung nach lohnt es sich, nicht konforme Browser mit 404s zu bestrafen, wenn die meisten kompatiblen Browser einen (leichten) Leistungseinbruch erleiden.

jlovison
quelle
3

Wir sehen 404 Fehler in unseren Protokollen, wenn wir //somedomain.com als Verweise auf JS-Dateien verwenden.

Die Referenzen, die die 404s verursachen, sehen folgendermaßen aus: ref:

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

404 Anfrage:

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

Da diese regelmäßig in unseren Webserver-Protokollen angezeigt werden, kann man mit Sicherheit sagen: Alle Browser und Bots berücksichtigen RFC 3986, Abschnitt 4.2, NICHT . Am sichersten ist es, wenn möglich, das Protokoll einzuschließen.

Lemiarty
quelle
Ja, ich habe mich irgendwie davon abgewandt, aber nicht wegen 404s (ich habe noch nie 404s gesehen ... wenn ein Bot es nicht einhält, könnte es mich weniger interessieren) - weil ich keine Ressourcen mehr von lade andere CDNs, damit ich dies nicht tun muss (stattdessen minimiere ich so viel wie möglich in 1 oder 2 Dateien).
Darryl Hein
1
Bitte geben Sie das Protokoll an. Protokolllose Refs brechen in meiner Cordova-App.
pgorsira
3

1. Zusammenfassung

Antwort für 2019: Sie können weiterhin protokollbezogene URLs verwenden, diese Technik ist jedoch ein Anti-Pattern .

Ebenfalls:

  1. Möglicherweise haben Sie Probleme bei der Entwicklung.
  2. Einige Tools von Drittanbietern unterstützen sie möglicherweise nicht.

Eine Migration von protokollbezogenen URLs zu https://diesen wäre schön.


2. Relevanz

Diese Antwort ist für Januar 2019 relevant. In Zukunft sind die Daten dieser Antwort möglicherweise veraltet.


3. Anti-Muster

3.1. Argumentation

Paul Irish - Front-End-Ingenieur und Entwickleranwalt für Google Chrome - schreibt im Dezember 2014 :

Jetzt, da SSL für alle empfohlen wird und keine Leistungsbedenken hat , ist diese Technik jetzt ein Anti-Pattern . Wenn das benötigte Asset über SSL verfügbar ist, verwenden Sie das https://Asset immer.

Das Zulassen, dass das Snippet über HTTP angefordert wird, öffnet die Tür für Angriffe wie den jüngsten GitHub Man-on-the-Side-Angriff . Es ist immer sicher, HTTPS-Assets anzufordern, auch wenn sich Ihre Site unter HTTP befindet. Das Gegenteil ist jedoch nicht der Fall .

3.2. Ein weiterer Link

3.3. Beispiele


4. Entwicklungsprozess

Zum Beispiel versuche ich, Clean-Console zu verwenden .

  • Beispieldatei 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>
  • Ausgabe:
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

Verknüpfung //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js ist gültig, aber ich erhalte eine Fehlermeldung.

Achten Sie auf file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jsund lesen Thilo und bg17aw Antworten zufile:// .

Ich wusste nichts über dieses Verhalten und konnte nicht verstehen, warum ich solche Probleme für Pager habe .


5. Tools von Drittanbietern

Ich verwende Clickable URLs Sublime Text-Paket. Verwenden Sie es, ich kann einfach Links aus meinem Texteditor im Browser öffnen.

Beispiele für CSS-Links

Beide Links im Beispiel sind gültig. Aber der erste Link, den ich erfolgreich im Browser öffnen kann, verwendet klickbare URLs, der zweite Link - nein. Dies ist möglicherweise nicht sehr praktisch.


6. Fazit

Ja:

  1. Wenn Sie Probleme wie im Developing processArtikel haben, können Sie Ihren Entwicklungsworkflow festlegen.
  2. Andernfalls haben Sie Probleme wie im Third-party toolsArtikel, können Sie Werkzeuge beitragen.

Diese zusätzlichen Probleme benötigen Sie jedoch nicht. Lesen Sie Informationen über Links im Anti-patternElement: Protokollbezogene URLs sind veraltet.

Саша Черных
quelle
2

Das Muster, das ich auf HTML5-Boilerplate sehe, ist:

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

Es läuft auf verschiedenen Systemen wie http, https, file.

Neurit
quelle
Dies ist nicht mehr wahr, siehe stackoverflow.com/a/37609402/2237601 oder hier , sie verwenden jetzt https://für alles
bg17aw
@ bg17aw Das Problem bei der Verwendung https://überall ist, dass Sie dann alle Ihre externen Links überprüfen müssen, um festzustellen , ob sie dies tatsächlich unterstützen, und sie ändern müssen, http://wenn dies nicht der Fall ist (da sie sonst nicht funktionieren). Dies kann bei einer großen Anzahl von Links problematisch sein.
Tomasz86
@ tomasz86 Sie verpassen den Punkt, ich habe nur auf den speziellen Fall der Verknüpfung mit Inhalten von CDNs hingewiesen. https: // ist heutzutage dafür obligatorisch. Die Antwort spricht auch über einen bestimmten Fall (HTML5-Boilerplate). Es gibt keine "Suche nach http", wie Sie sagen, da CDNs jetzt immer https verwenden.
bg17aw
@ bg17aw Das stimmt, aber die allgemeine Frage hier betrifft nicht nur CDNs. Wenn Sie nur diese Antwort / diesen Kommentar lesen, ist es leicht zu denken, dass https://sie in allen Links verwendet werden sollten (oder können), was nicht korrekt ist.
Thomasz86
@ tomasz86 Das Schöne an mehreren Antworten ist, dass, obwohl keine von ihnen perfekt ist (wenn eine Antwort perfekt wäre, müssten die anderen gelöscht werden), das Lesen einiger von ihnen uns eine breitere Sichtweise gibt. In diesem Fall lautet die Antwort "das Muster auf html5boilerplate ist ..." und mein Kommentar aktualisiert diese Antwort mit der Erwähnung "das ist nicht mehr das Muster auf html5-boilerplate". Das ist es. Eine notwendige Ergänzung zu dieser speziellen Antwort. Bitte beachten Sie auch, dass es sich bei der ursprünglichen Frage tatsächlich um CDNs handelt!
bg17aw
1

Da Ihr Beispiel die Verknüpfung mit einer externen Domäne ist, sollten Sie bei Verwendung von HTTPS überprüfen, ob die externe Domäne auch für SSL eingerichtet ist. Andernfalls werden Ihren Benutzern möglicherweise SSL- und / oder 404-Fehler angezeigt (z. B. speichern ältere Versionen von Plesk HTTP und HTTPS in separaten Ordnern). Für CDNs sollte es kein Problem sein, aber für jede andere Website könnte es sein.

Nebenbei bemerkt, getestet während der Aktualisierung einer alten Website und funktioniert auch im url = Teil eines META REFRESH.

user2246924
quelle