È valido per sostituire http: // con // in uno <script src = “http: //…”>?


458

Ho il seguente elemento:

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

In questo caso il sito è HTTPS, ma il sito potrebbe anche essere solo HTTP. (Il file JS si trova su un altro dominio.) Mi chiedo se sia valido per fare ciò per comodità:

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

Mi chiedo se è valido per rimuovere il http:o https:?

Sembra funzionare ovunque ho provato, ma ci sono casi in cui non funziona?


2
Il "sembra funzionare ovunque" può essere generalizzato a immagini, iframe, link-link ecc ecc? Questa è roba interessante, se è così.
12345,

Sì, dovrebbe funzionare in qualsiasi posto che richieda un URI: immagini, collegamenti, ecc. Potrebbe essere raro vederlo in uso, ma è perfettamente valido.
Jeff,

1
Cosa succede con tutti quei ragazzi che hanno votato all'istante? Non che la domanda sia sbagliata o altro, sono solo curiosa. Ma scommetto che la reputazione iniziale di Chris ha un'influenza.
Frederik Wordenskjold,

13
@Frederik: Perché è un trucco affascinante e utile di cui la maggior parte delle persone non è a conoscenza.
SLaks

8
@Frederik: What?
SLaks

Risposte:


387

È valido un URL relativo senza schema (http: o https :), per RFC 3986: "Uniform Resource Identifier (URI): Sintassi generica", Sezione 4.2 . Se un client lo soffoca, è colpa del cliente perché non è conforme alla sintassi URI specificata nell'RFC.

Il tuo esempio è valido e dovrebbe funzionare. Ho usato quel metodo URL relativo anche su siti fortemente trafficati e non ho avuto lamentele. Inoltre, testiamo i nostri siti su Firefox, Safari, IE6, IE7 e Opera. Tutti questi browser comprendono questo formato URL.


30
"Se un client lo soffoca, allora è colpa del cliente perché non è conforme alla sintassi URI specificata nell'RFC." - Penso che questa sia una domanda interessante - ma se un client segue "le specifiche" non è certo un buon standard se è saggio farlo in un'app Web.
Matt Howell,

6
Sebbene questa tecnica sembri poco nota, è supportata in tutti i browser web. Funziona alla grande.
Ned Batchelder,

8
Mi chiedo perché Google non lo usi per l'analisi. Usano il metodo document.location.protocol.
Darryl Hein,

5
@Darryl Hein Credo che Google utilizzi il metodo document.location.protocol perché modifica anche l'URL, non solo lo schema. Accedono a SSL.google-analytics.com se il documento utilizza lo schema https.
Nick Meldrum

18
google non lo utilizza perché lo stack di rete di Windows XP non supporta SNI. Vedi qui: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Pertanto, il caricamento dello script di analisi di Google tramite https su IE6 comporterebbe un errore del certificato.
Eilistraee,

152

È garantito il funzionamento con qualsiasi browser tradizionale (non sto prendendo in considerazione browser con una quota di mercato inferiore allo 0,05%). Diamine, funziona in Internet Explorer 3.0.

RFC 3986 definisce un URI come composto dalle seguenti parti:

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

Quando si definiscono gli URI relativi ( Sezione 5.2 ), è possibile omettere una qualsiasi di quelle sezioni, iniziando sempre da sinistra. In pseudo-codice, assomiglia a questo:

 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 che stai descrivendo è un URI relativo senza schema.


1
Sì, credo di aver pensato che schema e autorità fossero sempre reciprocamente dipendenti. Ha senso che non lo sia, ma non è qualcosa che ho incontrato fino a poco tempo fa.
Chris,

1
Non è garantito il funzionamento in nessun browser. È garantito per funzionare solo nei browser che seguono la RFC.

2
@Roger Pate: devo ancora vedere un browser che non segue l'RFC per l'URI. Quel particolare standard è in circolazione da così tanto tempo ... L'ho appena testato in IE3.0 e lo capisce perfettamente. Se cadi su un browser che non capisce quei collegamenti, è probabile che sia un browser così marginale che non importa.
Andrew Moore,

1
@Andrew: Forse sei diverso da me, ma quando dico "garanzia" nel contesto della programmazione, intendo davvero "non c'è modo che questo possa, mai fallire," non solo "funziona solo con implementazioni popolari che io ' ho testato ". Non intendevo farne un grosso problema, ma sembrava abbastanza importante da menzionare.

4
@Roger: Sì, ma nel contesto dello sviluppo web, i browser marginali (<0,01% quota di mercato) non vengono presi in considerazione. È come dire che un'API è presente in tutte le versioni di Windows e poi qualcuno viene a dire che potrebbe non essere supportato in Wine ...
Andrew Moore,

79

ci sono casi in cui non funziona?

Se la pagina principale è stata caricata file://, probabilmente non funziona (tenterà di ottenere file://cdn.example.com/js_file.js, cosa che ovviamente potresti fornire anche localmente).


19
Un must per ragazzi che provano html su macchine locali!
Philip007,

argh ... non c'è da stupirsi che script src="//..."non funzionasse! Stavo aprendo il file html localmente!
Wisbucky

Qualcuno sa come aggirare questo?
km6zla,

@ ogc-nick: è possibile eseguire un server Web locale. Molte opzioni in questi giorni, con configurazione zero. Lo vuoi comunque, come molte altre cose (come XHR o anche i web worker non funzionano per il file: domain)
Thilo

@Thilo Ha funzionato temporaneamente per me, ma sto realizzando un'app con Electron di Github e questo diventa un po 'più complicato.
km6zla,


25

Qui duplico la risposta in Funzionalità nascoste di HTML :

Utilizzando un percorso assoluto indipendente dal protocollo:

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

Se il browser visualizza una pagina in SSL tramite HTTPS, richiederà tale risorsa con il protocollo https, altrimenti lo richiederà con HTTP.

Questo evita quel terribile messaggio di errore "Questa pagina contiene elementi sia protetti che non protetti" in IE, mantenendo tutte le richieste di risorse all'interno dello stesso protocollo.

Avvertenza: se utilizzato su <link>o @import per un foglio di stile, IE7 e IE8 scaricano il file due volte . Tutti gli altri usi, tuttavia, vanno bene.


17

È perfettamente valido lasciare il protocollo. Le specifiche dell'URL sono state molto chiare su questo per anni e devo ancora trovare un browser che non lo capisca. Non so perché questa tecnica non sia meglio conosciuta; è la soluzione perfetta al spinoso problema di attraversare i confini HTTP / HTTPS. Altro qui: transizioni Http-https e relativi URL


7

ci sono casi in cui non funziona?

Solo per lanciarlo nel mix, se si sta sviluppando su un server locale, potrebbe non funzionare. Devi specificare uno schema, altrimenti il ​​browser potrebbe supporre che lo src="//cdn.example.com/js_file.js"siasrc="file://cdn.example.com/js_file.js" , il che si interromperà poiché non stai ospitando questa risorsa localmente.

Microsoft Internet Explorer sembra essere particolarmente sensibile a questo, vedi questa domanda: Impossibile caricare jQuery in Internet Explorer su localhost (WAMP)

Probabilmente proveresti sempre a trovare una soluzione che funzioni su tutti i tuoi ambienti con il minor numero di modifiche necessarie.

La soluzione utilizzata da HTML5Boilerplate è avere un fallback quando la risorsa non è caricata correttamente, ma funziona solo se si incorpora un controllo:

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

AGGIORNAMENTO: HTML5Boilerplate ora utilizza <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.jsdopo aver deciso di deprecare gli URL relativi al protocollo, vedere [qui] [3].


4

Seguendo il riferimento dello gnud, la sezione 5.2 del RFC 3986 dice:

Se viene definito il componente dello schema, indicando che il riferimento inizia con un nome di schema, il riferimento viene interpretato come un URI assoluto e abbiamo terminato. Altrimenti, lo schema dell'URI di riferimento viene ereditato dal componente dello schema dell'URI di base .

Quindi //è corretto :-)


3

Sì, questo è documentato in RFC 3986 , sezione 5.2:

(modifica: Spiacenti, il mio riferimento RFC era obsoleto).


3

È davvero corretto, come hanno affermato altre risposte. Dovresti notare, tuttavia, che alcuni web crawler attivano 404 per questi richiedendoli sul tuo server come se un URL locale. (Ignorano la doppia barra e la trattano come una singola barra).

Potresti voler impostare una regola sul tuo server web per catturarli e reindirizzarli.

Ad esempio, con Nginx, aggiungi qualcosa come:

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

Tieni presente, tuttavia, che se utilizzi punti nei tuoi URI, dovrai aumentare la specificità o finirà per reindirizzare tali pagine a domini inesistenti.

Inoltre, questa è una regex piuttosto massiccia da eseguire per ogni query - a mio avviso, vale la pena punire i browser non conformi con 404s su un (lieve) risultato di prestazioni sulla maggior parte dei browser compatibili.


3

Stiamo riscontrando 404 errori nei nostri registri quando si utilizza //somedomain.com come riferimento ai file JS.

I riferimenti che causano i 404 escono così: ref:

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

404 richiesta:

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

Con questi che compaiono regolarmente nei registri del nostro server Web, è sicuro dire che: Tutti i browser e i robot NON rispettano la sezione 4.2 di RFC 3986. La scommessa più sicura è quella di includere il protocollo ogni volta che è possibile.


Sì, mi sono un po 'spostato da esso, ma non a causa dei 404 (non ho mai visto 404 ... se un bot non lo onora, non me ne potrebbe fregare di meno) - perché non carica più risorse da altri CDN, quindi non ho bisogno di farlo (invece minimizzo il più possibile in 1 o 2 file).
Darryl Hein,

1
Si prega di includere il protocollo. I riferimenti senza protocollo si rompono nella mia app Cordova.
pgorsira,

3

1. Riepilogo

Risposta per il 2019: è ancora possibile utilizzare URL relativi al protocollo, ma questa tecnica è un anti-pattern .

Anche:

  1. Potresti avere problemi nello sviluppo.
  2. Alcuni strumenti di terze parti potrebbero non supportarli.

https://Sarebbe bello eseguire la migrazione da URL relativi al protocollo .


2. Rilevanza

Questa risposta è pertinente per gennaio 2019. In futuro, i dati di questa risposta potrebbero essere obsoleti.


3. Anti-pattern

3.1. Argomentazione

Paul Irish - ingegnere front-end e fautore dello sviluppatore per Google Chrome - scrive nel 2014, a dicembre :

Ora che SSL è incoraggiato per tutti e non ha problemi di prestazioni , questa tecnica è ora un anti-modello . Se la risorsa di cui hai bisogno è disponibile su SSL, usa sempre la https://risorsa.

Consentire allo snippet di richiedere su HTTP apre la porta ad attacchi come il recente attacco Man-on-the-side di GitHub . È sempre sicuro richiedere risorse HTTPS anche se il tuo sito è su HTTP, tuttavia non è vero il contrario .

3.2. Un altro link

3.3. Esempi


4. Processo di sviluppo

Ad esempio, provo a utilizzare clean-console .

  • File di esempio 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>
  • produzione:
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

Il link //cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.jsè valido, ma viene visualizzato un errore.

Presta attenzione file://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.jse leggi le risposte a Thilo e bg17awfile:// .

Non sapevo di questo comportamento e non riuscivo a capire perché ho problemi come questo per i pager .


5. Strumenti di terze parti

Uso il pacchetto Sublime Text degli URL cliccabili . Usalo, posso semplicemente aprire i collegamenti dal mio editor di testo nel browser.

Esempi di collegamenti CSS

Entrambi i collegamenti nell'esempio sono validi. Ma il primo link che posso aprire con successo nel browser usa URL cliccabili, secondo link - no. Questo potrebbe non essere molto conveniente.


6. Conclusione

Sì:

  1. In caso di problemi come Developing processnell'articolo, è possibile impostare il flusso di lavoro di sviluppo.
  2. Altrimenti hai problemi come Third-party toolsnell'articolo, puoi contribuire con strumenti.

Ma non hai bisogno di questi problemi aggiuntivi. Leggi le informazioni tramite link Anti-patternnell'elemento: gli URL relativi al protocollo sono obsoleti.


2

Lo schema che vedo su html5-boilerplate è:

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

Funziona senza problemi su sistemi diversi, come http, https, file.


Questo non è più vero, vedi stackoverflow.com/a/37609402/2237601 o qui , ora usano https://per tutto
bg17aw

@ bg17aw Il problema con l'utilizzo https://dappertutto è che devi continuare a controllare tutti i tuoi collegamenti esterni per vedere se lo supportano effettivamente e cambiarli in http://se non funzionano (altrimenti non funzioneranno). Questo può essere problematico con un gran numero di collegamenti.
tomasz86,

@ tomasz86 ti manca il punto, mi riferivo solo al caso particolare del collegamento ai contenuti delle CDN. https: // è obbligatorio per questo al giorno d'oggi. La risposta parla anche di un caso particolare (html5-boilerplate). Non c'è "controllo per http" come dici tu, dato che i CDN usano sempre https ora.
bg17aw,

@ bg17aw Questo è vero, ma la domanda generale qui non riguarda solo i CDN. Leggendo solo questa risposta / commento è facile pensare che https://dovrebbe (o può) essere usato in tutti i collegamenti che non sono corretti.
tomasz86,

@ tomasz86 La bellezza di avere risposte multiple è che mentre nessuna di esse è perfetta (se una risposta sarebbe perfetta, le altre dovrebbero essere eliminate), leggerne alcune ci dà una visione più ampia. In questo caso, la risposta dice "lo schema su html5boilerplate è ..." e il mio commento aggiorna questa risposta menzionando "che non è più lo schema su html5-boilerplate". Questo è tutto. Un'aggiunta necessaria a questa risposta particolare. Inoltre, tieni presente che la domanda originale riguarda le CDN!
bg17aw,

1

Poiché il tuo esempio si collega a un dominio esterno, se stai utilizzando HTTPS, dovresti verificare che anche il dominio esterno sia configurato per SSL. Altrimenti, gli utenti potrebbero visualizzare errori SSL e / o errori 404 (ad es. Versioni precedenti di Plesk archiviano HTTP e HTTPS in cartelle separate). Per i CDN, non dovrebbe essere un problema, ma per qualsiasi altro sito Web potrebbe esserlo.

In una nota a margine, testato mentre si aggiorna un vecchio sito Web e funziona anche in url = parte di un aggiornamento META.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.