web-dev-qa-db-pt.com

É válido para substituir http: // com // em um <script src = "http: // ...">?

Eu tenho o seguinte elemento:

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

Nesse caso, o site é HTTPS, mas o site também pode ser apenas HTTP. (O arquivo JS está em outro domínio.) Eu estou querendo saber se é válido fazer o seguinte por conveniência:

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

Eu estou querendo saber se é válido remover o http: ou https:?

Parece funcionar em todos os lugares que testei, mas há casos em que não funciona?

448
Darryl Hein

Uma URL relativa sem um esquema (http: ou https :) é válida, por RFC 3986: "Uniform Resource Identifier (URI): Sintaxe Genérica", Seção 4.2 . Se um cliente engasgar com ele, então é culpa do cliente, porque eles não estão cumprindo com a sintaxe de URI especificada no RFC.

Seu exemplo é válido e deve funcionar. Eu usei esse método de URL relativo em sites com muito tráfego e não tive nenhuma reclamação. Além disso, testamos nossos sites no Firefox, Safari, IE6, IE7 e Opera. Todos esses navegadores entendem esse formato de URL.

379
Jeff

É garantido que funcione em qualquer navegador convencional (não estou levando em consideração navegadores com menos de 0,05% de participação de mercado). Funciona no Internet Explorer 3.0.

RFC 3986 define um URI como composto das seguintes partes:

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

Ao definir URIs relativas ( Seção 5.2 ), você pode omitir qualquer uma dessas seções, sempre iniciando a partir da esquerda. No pseudo-código, parece com isso:

 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;

O URI que você está descrevendo é um URI relativo sem esquema.

149
Andrew Moore

existem casos em que não funciona?

Se a página pai foi carregada a partir de file://, então provavelmente ela não funcionará (ela tentará obter file://cdn.example.com/js_file.js, o que é claro que você poderia fornecer localmente também).

77
Thilo

Muitas pessoas chamam isso de URL relativo ao protocolo.

Causa um duplo download de arquivos CSS em IE 7 & 8 .

40
SLaks

Aqui eu duplico a resposta em Recursos ocultos do HTML :

Usando um caminho absoluto independente de protocolo :

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

Se o navegador estiver visualizando uma página em SSL por meio de HTTPS, solicitará Esse ativo com o protocolo https, Caso contrário, ele será solicitado com HTTP.

Isso impede que a terrível mensagem de erro "Esta página Contém itens seguros e não seguros " No IE, mantendo Todos os seus pedidos de ativos dentro do Mesmo protocolo .

Advertência: Quando usado em um <link> ou @Import para uma folha de estilo, IE7 e IE8 faça o download do arquivo duas vezes . Todos os outros usos , No entanto, estão bem.

23
kennytm

É perfeitamente válido deixar o protocolo. A especificação da URL tem sido muito clara sobre isso há anos, e eu ainda não encontrei um navegador que não entenda isso. Não sei por que essa técnica não é mais conhecida; é a solução perfeita para o espinhoso problema de cruzar limites HTTP/HTTPS. Mais aqui: Transições Http-https e URLs relativas

16
Ned Batchelder

existem casos em que não funciona?

Apenas para jogar isso na mistura, se você estiver desenvolvendo em um servidor local, pode não funcionar. Você precisa especificar um esquema, caso contrário, o navegador pode assumir que src="//cdn.example.com/js_file.js" é src="file://cdn.example.com/js_file.js", que será interrompido, pois você não está hospedando esse recurso localmente.

Microsoft Internet Explorer parece ser particularmente sensível a isso, veja esta pergunta: Não é possível carregar o jQuery no Internet Explorer no host local (WAMP)

Você provavelmente sempre tentará encontrar uma solução que funcione em todos os seus ambientes com a menor quantidade de modificações necessárias.

A solução usada por HTML5Boilerplate é ter um fallback quando o recurso não é carregado corretamente, mas isso só funciona se você incorporar uma verificação:

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

ATUALIZAÇÃO: HTML5Boilerplate agora usa <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js depois de decidir preterir os URLs relativos ao protocolo, veja [aqui] [3].

5
bg17aw

Seguindo a referência do gnud, a seção RFC 3986 5.2 diz:

Se o componente do esquema for definido, indicando que a referência Começa com um nome de esquema, a referência é interpretada como uma URI absoluta E estamos concluídos. Caso contrário, o esquema de URI de referência É herdado do componente de esquema URI de base .

Então // está correto :-)

3
Pablo Torrecilla

Estamos vendo erros 404 em nossos registros ao usar //somedomain.com como referências a arquivos JS. 

As referências que causam os 404s saem assim: Ref:

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

Pedido 404:

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

Com estes aparecendo regularmente em nossos logs do servidor web, é seguro dizer que: Todos os navegadores e Bots NÃO honram o RFC 3986 seção 4.2. A aposta mais segura é incluir o protocolo sempre que possível.

2
Lemiarty

Sim, isso está documentado em RFC 3986 , seção 5.2:

(edit: Oops, minha referência de RFC estava desatualizada).

2
gnud

É de fato correto, como outras respostas afirmaram. Você deve observar, no entanto, que alguns rastreadores da Web definirão os 404s para eles, solicitando-os em seu servidor como se fossem um URL local. (Eles desconsideram a barra dupla e a tratam como uma única barra).

Você pode querer configurar uma regra no seu servidor para capturá-los e redirecioná-los.

Por exemplo, com o Nginx, você adicionaria algo como:

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

Observe, porém, que se você usar períodos em seus URIs, precisará aumentar a especificidade ou ele acabará redirecionando essas páginas para domínios inexistentes.

Além disso, este é um regex bastante massivo para ser executado em cada consulta - na minha opinião, vale a pena punir os navegadores não compatíveis com os 404s por causa de um (leve) impacto de desempenho na maioria dos navegadores compatíveis.

2
jlovison

O padrão que vejo em 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>

Funciona sem problemas em diferentes esquemas como http, https, file.

1
neurite

Como seu exemplo é vincular a um domínio externo, se você estiver usando HTTPS, verifique se o domínio externo também está configurado para SSL. Caso contrário, seus usuários poderão ver erros de SSL e/ou erros 404 (por exemplo, versões mais antigas do HTTP e HTTPS da loja Plesk em pastas separadas). Para CDNs, não deve ser um problema, mas para qualquer outro site poderia ser.

Em uma nota lateral, testado enquanto atualizava um site antigo e também trabalha na url = parte de um META REFRESH.

0
user2246924

1. Resumo

Resposta para 2019: você ainda pode usar URLs relativas a protocolo, mas this techniquean anti-pattern .

Além disso:

  1. Você pode ter problemas no desenvolvimento.
  2. Algumas ferramentas de terceiros podem não suportá-las.

Migrar de URLs relativas a protocolo para https:// seria Nice.


2. Relevância

Essa resposta é relevante para janeiro de 2019. No futuro, os dados dessa resposta podem estar obsoletos.


3. Anti-padrão

3.1. Argumentação

Paul Irish - engenheiro front-end e defensor do Google Chrome - write em 2014, dezembro :

Agora que o SSL é incentivado para todos e não tem preocupações de desempenho , essa técnica agora é um antipadrão. Se o ativo necessário estiver disponível no SSL, use sempre o ativo https://.

Permitir que o snippet solicite por HTTP abre a porta para ataques como o recente ataque GitHub Man-on-the-side . É sempre seguro solicitar recursos HTTPS, mesmo que seu site esteja em HTTP. No entanto, o contrário não é verdadeiro .

3.2. Outros links

3.3. Exemplos


4. Processo de desenvolvimento

Por exemplo, tento usar clean-console .

  • Exemplo de arquivo 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/[email protected]/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>
  • saída:
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

O link //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js é válido, mas estou recebendo um erro.

Preste atenção em file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js e leia Thilo e bg17aw respostas sobre file://.

Eu não sabia sobre esse comportamento e não conseguia entender por que eu tenho problemas como this para pageres .


5. Ferramentas de Terceiros

Eu uso o pacote Clickable URLs Sublime Text. Use-o, posso simplesmente abrir links do meu editor de texto no navegador.

CSS links examples

Ambos os links no exemplo são válidos. Mas primeiro link eu posso abrir com sucesso no uso do navegador URLs clicáveis, segundo link - não. Isso pode não ser muito conveniente.


6. Conclusão

Sim:

  1. Se você tiver problemas como no item Developing process, poderá definir seu fluxo de trabalho de desenvolvimento.
  2. Se você tiver problemas como no item Third-party tools, pode contribuir com ferramentas.

Mas você não precisa desse problema adicional. Ler informações por links em Anti-pattern item: URLs relativos a protocolos são obsoletos.

0
Саша Черных