Est-il valide de remplacer http: // par // dans un <script src = “http: //…”>?

458

J'ai l'élément suivant:

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

Dans ce cas, le site est HTTPS, mais le site peut également être uniquement HTTP. (Le fichier JS est sur un autre domaine.) Je me demande s'il est valide de faire ce qui suit pour des raisons de commodité:

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

Je me demande s'il est valable de supprimer le http:ou https:?

Il semble fonctionner partout où j'ai testé, mais y a-t-il des cas où cela ne fonctionne pas?

Darryl Hein
la source
2
Le "ça semble fonctionner partout" peut-il être généralisé aux images, iframes, link-rels etc etc? Ce sont des choses intéressantes, si c'est le cas.
12345
Oui, cela devrait fonctionner dans n'importe quel endroit qui nécessite un URI: images, liens, etc. Il peut être rare de voir cela en cours d'utilisation, mais c'est parfaitement valide.
Jeff
1
Qu'est-ce qui se passe avec tous ces gars de vote instantané? Non pas que la question soit mauvaise ou quoi que ce soit, je suis juste curieux. Mais je parie que la réputation initiale de Chris a une influence.
Frederik Wordenskjold
13
@Frederik: Parce que c'est une astuce fascinante et utile que la plupart des gens ignorent apparemment.
SLaks
8
@Frederik: Quoi?
SLaks

Réponses:

387

Une URL relative sans schéma (http: ou https :) est valide, conformément à la RFC 3986: «Identificateur de ressource uniforme (URI): syntaxe générique», section 4.2 . Si un client s'étouffe dessus, c'est la faute du client car il ne respecte pas la syntaxe URI spécifiée dans le RFC.

Votre exemple est valide et devrait fonctionner. J'ai moi-même utilisé cette méthode d'URL relative sur des sites très fréquentés et je n'ai reçu aucune plainte. Nous testons également nos sites dans Firefox, Safari, IE6, IE7 et Opera. Ces navigateurs comprennent tous ce format d'URL.

Jeff
la source
30
"Si un client s'étouffe dessus, c'est la faute du client car il ne respecte pas la syntaxe URI spécifiée dans le RFC." - Je pense que c'est une question intéressante - mais si un client suit "la spécification" n'est guère une bonne norme pour savoir s'il est sage de le faire dans une application Web.
Matt Howell
6
Bien que cette technique semble peu connue, elle est prise en charge par tous les navigateurs Web. Cela fonctionne très bien.
Ned Batchelder
8
Je me demande pourquoi google ne l'utilise pas pour l'analyse. Ils utilisent la méthode document.location.protocol.
Darryl Hein
5
@Darryl Hein Je pense que Google utilise la méthode document.location.protocol car elle modifie également l'url, pas seulement le schéma. Ils accèdent à SSL.google-analytics.com si le document utilise le schéma https.
Nick Meldrum
18
google ne l'utilise pas car la pile réseau de Windows XP ne prend pas en charge SNI. Voir ici: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Par conséquent, autoriser le chargement du script Google Analytics via https sur IE6 entraînerait une erreur de certificat.
Eilistraee
152

Il est garanti de fonctionner dans n'importe quel navigateur grand public (je ne prends pas en considération les navigateurs avec moins de 0,05% de part de marché). Heck, cela fonctionne dans Internet Explorer 3.0.

La RFC 3986 définit un URI comme composé des parties suivantes:

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

Lors de la définition d'URI relatifs ( Section 5.2 ), vous pouvez omettre l'une de ces sections, toujours en partant de la gauche. En pseudo-code, cela ressemble à ceci:

 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;

L'URI que vous décrivez est un URI relatif sans schéma.

Andrew Moore
la source
1
Ouais je suppose que je pensais que le schéma et l'autorité étaient toujours mutuellement dépendants. Il est logique que ce ne soit pas le cas, mais ce n'est pas quelque chose que j'ai rencontré jusqu'à très récemment.
Chris
1
Il n'est pas garanti de fonctionner dans n'importe quel navigateur. Il est garanti de fonctionner uniquement dans les navigateurs qui suivent la RFC.
2
@Roger Pate: Je n'ai pas encore vu un navigateur ne pas suivre le RFC pour l'URI. Ce standard particulier existe depuis si longtemps ... Je viens de le tester dans IE3.0 et il le comprend parfaitement. Si vous tombez sur un navigateur qui ne comprend pas ces liens, il y a de fortes chances que ce soit un navigateur si marginal qu'il n'aura pas d'importance.
Andrew Moore
1
@Andrew: Peut-être que vous êtes différent de moi, mais quand je dis "garantir" dans le contexte de la programmation, je veux vraiment dire "il n'y a aucun moyen que cela puisse éventuellement échouer", pas seulement "cela ne fonctionne que dans les implémentations populaires que je ' ve testé. " Je ne voulais pas en faire grand cas, mais cela semblait assez important pour le mentionner.
4
@Roger: Oui, mais dans le cadre du développement web, les navigateurs marginaux (<0,01% de part de marché) ne sont pas pris en compte. C'est comme dire qu'une API est présente dans toutes les versions de Windows et que quelqu'un vient dire qu'elle pourrait ne pas être prise en charge dans Wine ...
Andrew Moore
79

y a-t-il des cas où cela ne fonctionne pas?

Si la page parente a été chargée à partir de file://, cela ne fonctionnera probablement pas (elle essaiera de l'obtenir file://cdn.example.com/js_file.js, ce que vous pourriez bien sûr fournir localement également).

Thilo
la source
19
Un must pour les gars qui testent le HTML sur une machine locale!
Philip007
argh ... pas étonnant que mon script src="//..."ne fonctionnait pas! J'ouvrais le fichier html localement!
wisbucky
Quelqu'un sait comment contourner cela?
km6zla
@ ogc-nick: vous pouvez exécuter un serveur Web local. Beaucoup d'options de nos jours, avec une configuration nulle. Vous le voulez quand même, comme beaucoup d'autres choses (comme les XHR ou les web travailleurs ne fonctionnent pas non plus pour le fichier: domaine)
Thilo
@Thilo Cela a fonctionné temporairement pour moi mais je fais une application avec Electron de Github et cela devient un peu plus compliqué.
km6zla
41

Beaucoup de gens appellent cela une URL relative au protocole.

Il provoque un double téléchargement des fichiers CSS dans IE 7 et 8 .

SLaks
la source
@AndrewMoore Comme la «chose» exclue indique le protocole Web, l'appeler «relatif au protocole» a plus de sens. Je n'ai jamais entendu parler de ftp ou http appelé "schémas" ...
Cerin
25

Ici, je reproduis la réponse dans les fonctionnalités cachées de HTML :

Utilisation d'un chemin absolu indépendant du protocole:

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

Si le navigateur affiche une page en SSL via HTTPS, il demandera cet actif avec le protocole https, sinon il le demandera avec HTTP.

Cela empêche cet horrible message d'erreur «Cette page contient des éléments sécurisés et non sécurisés» dans IE, en conservant toutes vos demandes de ressources dans le même protocole.

Avertissement: lorsqu'ils sont utilisés sur un <link>ou @import pour une feuille de style, IE7 et IE8 téléchargent le fichier deux fois . Cependant, toutes les autres utilisations sont très bien.

kennytm
la source
17

Il est parfaitement valable de laisser de côté le protocole. La spécification d'URL est très claire à ce sujet depuis des années, et je n'ai pas encore trouvé de navigateur qui ne la comprenne pas. Je ne sais pas pourquoi cette technique n'est pas mieux connue; c'est la solution parfaite au problème épineux du franchissement des frontières HTTP / HTTPS. Plus ici: transitions Http-https et URL relatives

Ned Batchelder
la source
7

y a-t-il des cas où cela ne fonctionne pas?

Juste pour jeter cela dans le mélange, si vous développez sur un serveur local, cela pourrait ne pas fonctionner. Vous devez spécifier un schéma, sinon le navigateur peut supposer que src="//cdn.example.com/js_file.js"c'est le cas src="file://cdn.example.com/js_file.js", ce qui cassera puisque vous n'hébergez pas cette ressource localement.

Microsoft Internet Explorer semble être particulièrement sensible à cela, voir cette question: impossible de charger jQuery dans Internet Explorer sur localhost (WAMP)

Vous essayerez probablement toujours de trouver une solution qui fonctionne sur tous vos environnements avec le moins de modifications nécessaires.

La solution utilisée par HTML5Boilerplate est d'avoir un repli lorsque la ressource n'est pas chargée correctement, mais cela ne fonctionne que si vous incorporez une vérification:

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

MISE À JOUR: HTML5Boilerplate utilise maintenant <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jsaprès avoir décidé de déprécier les URL relatives du protocole, voir [ici] [3].

bg17aw
la source
4

Suite à la référence de GNUD, la section 5.2 de la RFC 3986 dit:

Si le composant de schéma est défini, indiquant que la référence commence par un nom de schéma, alors la référence est interprétée comme un URI absolu et nous avons terminé. Sinon, le schéma de l'URI de référence est hérité du composant de schéma de l'URI de base .

Il en //est ainsi :-)

Pablo Torrecilla
la source
3

Oui, cela est documenté dans RFC 3986 , section 5.2:

(modifier: Oups, ma référence RFC était obsolète).

gnud
la source
3

C'est en effet correct, comme l'ont indiqué d'autres réponses. Vous devez cependant noter que certains robots d'exploration Web déclencheront 404 pour ceux-ci en les demandant sur votre serveur comme s'il s'agissait d'une URL locale. (Ils ignorent la double barre oblique et la traitent comme une simple barre oblique).

Vous souhaiterez peut-être configurer une règle sur votre serveur Web pour les détecter et les rediriger.

Par exemple, avec Nginx, vous ajouteriez quelque chose comme:

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

Notez cependant que si vous utilisez des points dans vos URI, vous devrez augmenter la spécificité ou cela finira par rediriger ces pages vers des domaines inexistants.

De plus, il s'agit d'une expression assez massive à exécuter pour chaque requête - à mon avis, cela vaut la peine de punir les navigateurs non conformes avec 404 sur un (léger) impact sur les performances de la majorité des navigateurs conformes.

jlovison
la source
3

Nous voyons des erreurs 404 dans nos journaux lorsque nous utilisons //somedomain.com comme références à des fichiers JS.

Les références qui provoquent les 404 sortent comme ceci: ref:

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

404 demande:

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

Avec ceux-ci apparaissant régulièrement dans nos journaux de serveur Web, il est sûr de dire que: Tous les navigateurs et les robots n'honorent PAS la section 4.2 de la RFC 3986. Le pari le plus sûr est d'inclure le protocole autant que possible.

Lemiarty
la source
Oui, je m'en suis un peu éloigné, mais pas à cause des 404 (je n'ai jamais vu de 404 ... si un bot ne l'honore pas, je m'en fiche) - parce que je ne charge plus les ressources de d'autres CDN donc je n'ai pas besoin de le faire (au lieu de cela je minimise autant que possible en 1 ou 2 fichiers).
Darryl Hein
1
Veuillez inclure le protocole. Les références sans protocole se brisent dans mon application Cordova.
pgorsira
3

1. Résumé

Réponse pour 2019: vous pouvez toujours utiliser des URL relatives au protocole, mais cette technique est un anti-modèle .

Aussi:

  1. Vous pourriez avoir des problèmes de développement.
  2. Certains outils tiers peuvent ne pas les prendre en charge.

Migration depuis des URL relatives au protocole vers https://ce serait bien.


2. Pertinence

Cette réponse est pertinente pour janvier 2019. À l'avenir, les données de cette réponse pourraient être obsolètes.


3. Anti-modèle

3.1. Argumentation

Paul Irish - ingénieur front-end et défenseur des développeurs de Google Chrome - écrit en décembre 2014 :

Maintenant que SSL est encouragé pour tout le monde et n'a pas de problèmes de performances , cette technique est maintenant un anti-modèle . Si l'actif dont vous avez besoin est disponible sur SSL, utilisez toujours l' https://actif.

Autoriser l'extrait à demander via HTTP ouvre la porte à des attaques comme la récente attaque GitHub Man-on-the-side . Il est toujours sûr de demander des actifs HTTPS même si votre site est sur HTTP, mais l'inverse n'est pas vrai .

3.2. Un autre liens

3.3. Exemples


4. Processus d'élaboration

Par exemple, j'essaie d'utiliser une console propre .

  • Exemple de fichier 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>
  • production:
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

Lien //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js est valide, mais j'obtiens une erreur.

Faites attention file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.jset lisez les réponses de Thilo et bg17awfile:// .

Je ne connaissais pas ce comportement et je ne pouvais pas comprendre pourquoi j'avais des problèmes comme celui-ci pour les pageres .


5. Outils tiers

J'utilise le package Sublime Text URLs cliquables . Utilisez-le, je peux simplement ouvrir les liens de mon éditeur de texte dans le navigateur.

Exemples de liens CSS

Les deux liens dans l'exemple sont valides. Mais le premier lien que je peux ouvrir avec succès dans le navigateur utilise des URL cliquables, le deuxième lien - non. Cela peut ne pas être très pratique.


6. Conclusion

Oui:

  1. Si vous avez des problèmes comme Developing process élément, vous pouvez définir votre flux de travail de développement.
  2. Sinon, vous avez des problèmes comme dans l' Third-party toolsarticle, vous pouvez contribuer à des outils.

Mais vous n'avez pas besoin de ces problèmes supplémentaires. Lisez les informations par des liens dans l' Anti-patternélément: les URL relatives au protocole sont obsolètes.

Саша Черных
la source
2

Le motif que je vois sur html5-passe-partout est:

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

Il fonctionne en douceur sur les différents régimes comme http, https, file.

névrite
la source
Ce n'est plus vrai, voir stackoverflow.com/a/37609402/2237601 ou ici , ils utilisent maintenant https://pour tout
bg17aw
@ bg17aw Le problème avec l'utilisation https://partout est que vous devez ensuite continuer à vérifier tous vos liens externes pour voir s'ils le prennent réellement en charge et les changer http://s'ils ne le font pas (sinon ils ne fonctionneront pas). Cela peut être gênant avec un grand nombre de liens.
tomasz86
@ tomasz86 vous manquez le point, je ne faisais que rappeler le cas particulier de la liaison au contenu des CDN. https: // est obligatoire pour cela de nos jours. La réponse parle également d'un cas particulier (html5-passe-partout). Il n'y a pas de "vérification de http" comme vous le dites, car les CDN utilisent toujours https maintenant.
bg17aw
@ bg17aw C'est vrai, mais la question générale ici ne concerne pas seulement les CDN. En lisant juste cette réponse / commentaire, il est facile de penser que cela https://devrait (ou peut) être utilisé dans tous les liens, ce qui n'est pas correct.
tomasz86
@ tomasz86 La beauté d'avoir plusieurs réponses est que même si aucune n'est parfaite (si une réponse est parfaite, les autres doivent être supprimées), en lire quelques-unes nous donne une vue plus large. Dans ce cas, la réponse dit "le modèle sur html5boilerplate est ..." et mon commentaire met à jour cette réponse en mentionnant "ce n'est plus le modèle sur html5 -ilerplate". C'est ça. Un ajout nécessaire à cette réponse particulière. Veuillez également noter que la question d'origine concerne en effet les CDN!
bg17aw
1

Comme votre exemple est lié à un domaine externe, si vous utilisez HTTPS, vous devez également vérifier que le domaine externe est également configuré pour SSL. Sinon, vos utilisateurs peuvent voir des erreurs SSL et / ou des erreurs 404 (par exemple, les anciennes versions de Plesk stockent HTTP et HTTPS dans des dossiers séparés). Pour les CDN, cela ne devrait pas être un problème, mais pour tout autre site Web, cela pourrait l'être.

Sur une note latérale, testé lors de la mise à jour d'un ancien site Web et fonctionne également dans la partie url = d'un META REFRESH.

user2246924
la source