Codificar URL em JavaScript?

2470

Como você codifica com segurança um URL usando JavaScript para que ele possa ser colocado em uma sequência GET?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

Presumo que você precise codificar a myUrlvariável nessa segunda linha?

nickf
fonte
22
Tente pesquisar em encodeURI () e decodeURI () .
Zack The Human
Consulte a função JavaScript urlencode .
30511 Yanni
1
Você pode usar esta ferramenta aqui: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Andrew

Respostas:

2791

Confira a função interna encodeURIComponent (str) e encodeURI (str) .
No seu caso, isso deve funcionar:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Buu Nguyen
fonte
12
Que tal adicionar a explicação que o @cms deu? escapetambém é uma opção válida.
Hitautodestruct 28/10/12
11
de acordo com @CMS, encodeURInão é realmente seguro para codificação de URL.
Caso contrário, 01/03/13
13
@AnaelFavre porque se destina para codificar toda a URL, que não permite que personagens como :, /, @etc. Estes 2 métodos não são para ser usado intercambiáveis, você deve saber o que está a codificar para usar o método certo.
Buu Nguyen
Como mencionado em outra resposta sobre esta página , este site muito bem detalha a razão para usar este método
Brad Parks
1522

Você tem três opções:

  • escape() não codificará: @*/+

  • encodeURI() não codificará: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() não codificará: ~!*()'

Mas no seu caso, se você deseja passar um URL para um GETparâmetro de outra página, use escapeou encodeURIComponent, mas não encodeURI.

Consulte a pergunta sobre estouro de pilha. Prática recomendada: escape ou encodeURI / encodeURIComponent para discussão adicional.

CMS
fonte
76
A codificação de caracteres usada com escape é variável. Adira ao encodeURI e encodeURIComponent, que usam UTF-8.
Erickson
6
Seja cuidadoso. Esse escape converte caracteres não ASCII em suas seqüências de escape Unicode, como %uxxx.
Opteronn
4
Estou usando encodeURIComponent e percebendo que ele não codificará caracteres de pipe |
Kevzettler
15
@kevzettler - por que deveria fazer isso? Os pipes não são de importância semântica em um URI.
nickf 31/01
4
@GiovanniP: pessoas que permitem caracteres alemães, franceses, japoneses, chineses, árabes como entrada e passam esses parâmetros via GET ou POST.
Tseng
180

Ficar com encodeURIComponent(). A função encodeURI()não se preocupa em codificar muitos caracteres que têm importância semântica nos URLs (por exemplo, "#", "?" E "&"). escape()foi descontinuado e não se preocupa em codificar caracteres "+", que serão interpretados como espaços codificados no servidor (e, conforme apontado por outros aqui, não codificam corretamente caracteres não ASCII).

Há uma boa explicação da diferença entre encodeURI()e emencodeURIComponent() outros lugares. Se você deseja codificar algo para que ele possa ser incluído com segurança como um componente de um URI (por exemplo, como um parâmetro de string de consulta), você deseja usar encodeURIComponent().

Mike Brennan
fonte
83

A melhor resposta é a utilização encodeURIComponentde valores na cadeia de consulta (e em nenhum outro lugar).

No entanto, acho que muitas APIs desejam substituir "" por "+", então tive que usar o seguinte:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escapeé implementado de maneira diferente em navegadores diferentes e encodeURInão codifica muitos caracteres (como # e até /) - é feito para ser usado em um URI / URL completo sem quebrá-lo - o que não é super útil ou seguro.

E como o @Jochem aponta abaixo, convém usar o encodeURIComponent()nome de uma pasta (cada), mas, por qualquer motivo, essas APIs não parecem querer +nomes de pastas, de modo que o velho antigo encodeURIComponentfunciona muito bem.

Exemplo:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Ryan Taylor
fonte
22
Observe que você só deve substituir% 20 por + símbolos após o primeiro ponto de interrogação (que é a parte 'query' do URL). Digamos que eu queira navegar para http://somedomain/this dir has spaces/info.php?a=this has also spaces. Ele deve ser convertido para: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesmas muitas implementações permitem que '% 20' na string de consulta seja substituída por '+'. No entanto, você não pode substituir '% 20' por '+' na seção de caminho da URL; isso resultará em um erro Não encontrado, a menos que você tenha um diretório com +um espaço em vez de um espaço.
Jochem Kuijpers
@Jochem Kuijpers, definitivamente, você não colocaria "+" em um diretório. Eu aplicaria isso apenas aos próprios valores do parâmetro de consulta (ou chaves, se necessário), não a URL inteira ou mesmo a string de consulta inteira.
21713 Ryan Ryan
Eu iria substituir em valor e não no resultado da codificação
njzk2
1
Infelizmente, o @ njzk2 encodeURIComponent('+')daria a você %2B, então você teria que usar duas expressões regulares ... o que eu suponho que seja esse o tipo de coisa que funciona, porque '+' are '' são codificados de forma diferente no final.
Ryan Taylor
Não há motivo para converter% 20 para "+". A sequência de escape válida para o espaço ASCII é% 20, não "+", que não é mencionada na RFC 3986 ( tools.ietf.org/html/rfc3986 ). "+" foi usado nos anos 90; agora está obsoleto e é suportado apenas por motivos herdados. Não use.
xhienne
40

Se você estiver usando jQuery, eu usaria o $.parammétodo Sua URL codifica os campos de mapeamento de objetos para valores, que são mais fáceis de ler do que chamar um método de escape em cada valor.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Maksym Kozlenko
fonte
Eu acho que esse exemplo fornecido é suficiente. Se precisar de mais informações sobre $ .param em api.jquery.com/jquery.param
Maksym Kozlenko
Quase todo mundo usa jQuery e eu me sinto mais confortável na verdade, com isso em vez de encoreURIComponent
Cyril Duchon-Doris
12

encodeURIComponent () é o caminho a percorrer.

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

Mas você deve ter em mente que existem pequenas diferenças em relação à versão php urlencode()e, como o @CMS mencionou, ele não codifica todos os caracteres. Os caras em http://phpjs.org/functions/urlencode/ fizeram js equivalentes a phpencode():

function urlencode(str) {
  str = (str + '').toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}
Adam Fischer
fonte
10

Para codificar uma URL, como já foi dito anteriormente, você tem duas funções:

encodeURI()

e

encodeURIComponent()

A razão pela qual ambos existem é que o primeiro preserva a URL com o risco de deixar muitas coisas sem escape, enquanto o segundo codifica tudo o que é necessário.

Com o primeiro, você poderia copiar o URL recém-escapado na barra de endereços (por exemplo) e ele funcionaria. No entanto, seus '&' sem escape interfeririam com os delimitadores de campo, os '=' interfeririam nos nomes e valores dos campos, e os '+' pareceriam espaços. Mas para dados simples quando você deseja preservar a natureza da URL do que está escapando, isso funciona.

O segundo é tudo o que você precisa fazer para garantir que nada em sua string interfira com um URL. Ele deixa vários caracteres sem importância sem escape, para que o URL permaneça o mais legível possível por humanos, sem interferência. Um URL codificado dessa maneira não funcionará mais como um URL sem desmarcá-lo.

Portanto, se você puder dedicar algum tempo, sempre desejará usar encodeURIComponent () - antes de adicionar pares nome / valor, codifique o nome e o valor usando essa função antes de adicioná-lo à string de consulta.

Estou tendo dificuldades para encontrar razões para usar o encodeURI () - deixarei isso para as pessoas mais inteligentes.

Gerard ONeill
fonte
5

Tipo semelhante de coisa que tentei com javascript normal

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
Narayan Yerrabachu
fonte
5

Maneira elegante

Na minha humilde opinião, a maneira mais elegante de codificar parâmetros de consulta é criar um objeto com parâmetros como

const queryParams = { param1: 'value1', param2: 'value2' }

e codifique-o usando:

const queryString = new URLSearchParams(queryParams).toString()

conforme mencionado nesta resposta: https://stackoverflow.com/a/53171438/7284582

Qback
fonte
4

Para evitar a codificação dupla, é uma boa idéia decodificar o URL antes da codificação (se você estiver lidando com URLs inseridos pelo usuário, por exemplo, que já podem estar codificados).

Vamos dizer que temos abc%20xyz 123como entrada (um espaço já está codificado):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
serg
fonte
4

O que é codificação de URL:

Um URL deve ser codificado quando houver caracteres especiais localizados dentro do URL. Por exemplo:

console.log(encodeURIComponent('?notEncoded=&+'));

Podemos observar neste exemplo que todos os caracteres, exceto a string, notEncodedsão codificados com sinais de%. A codificação de URL também é conhecida como porcentagem porque escapa a todos os caracteres especiais com um%. Depois deste sinal de%, cada caractere especial possui um código único

Por que precisamos de codificação de URL:

Certos caracteres têm um valor especial em uma string de URL. Por exemplo, o? caractere indica o início de uma string de consulta. Para localizar com êxito um recurso na Web, é necessário distinguir entre quando um caractere é feito como parte de uma string ou parte da estrutura do URL.

Como podemos obter a codificação de URL em JS:

O JS oferece várias funções de construção na utilidade que podemos usar para codificar facilmente URLs. Estas são duas opções convenientes:

  1. encodeURIComponent(): Utiliza um componente de um URI como argumento e retorna a sequência de caracteres codificada do URI.
  2. encodeURI(): Usa um URI como argumento e retorna a sequência de caracteres codificada do URI.

Exemplo e advertências:

Esteja ciente de não passar todo o URL (incluindo o esquema, por exemplo, https: //) encodeURIComponent(). Na verdade, isso pode transformá-lo em um URL não funcional. Por exemplo:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

Podemos observar se colocamos toda a URL em encodeURIComponentque as barras (/) também são convertidas em caracteres especiais. Isso fará com que o URL não funcione mais corretamente.

Portanto (como o nome indica) use:

  1. encodeURIComponent em uma determinada parte de um URL que você deseja codificar.
  2. encodeURI em um URL inteiro que você deseja codificar.
Willem van der Veen
fonte
3

Nada funcionou para mim. Tudo o que eu estava vendo era o HTML da página de login, voltando ao lado do cliente com o código 200. (302 no início, mas a mesma solicitação do Ajax carregando a página de login dentro de outra solicitação do Ajax, que deveria ser um redirecionamento, e não um carregamento simples texto da página de login).

No controlador de login, adicionei esta linha:

Response.Headers["land"] = "login";

E no manipulador global do Ajax, fiz o seguinte:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

Agora não tenho nenhum problema e funciona como um encanto.

Asif Ashraf
fonte
2

Codificar URL String

    var url = $ ( local ). attr ( 'href' ); // obtém o URL atual // OR var url = 'folder / index.html? param = # 23dd & noob = yes' ; // ou especifique um 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string
Sangeet Shah
fonte
2

Aqui está uma demonstração ao vivo de encodeURIComponent()e decodeURIComponent()JS construídos em funções:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>
jonathana
fonte
1

Você pode usar a biblioteca esapi e codificar seu URL usando a função abaixo. A função garante que '/' não seja perdido na codificação enquanto o restante do conteúdo do texto é codificado:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme

Mohith Maratt
fonte
1

Use a fixedEncodeURIComponentfunção para cumprir rigorosamente a RFC 3986 :

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Arthur
fonte
1

Você não deve usar encodeURIComponent()diretamente.

Dê uma olhada no RFC3986: URI (Uniform Resource Identifier): Sintaxe genérica

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

O objetivo dos caracteres reservados é fornecer um conjunto de caracteres delimitadores que sejam distinguíveis de outros dados em um URI.

Esses caracteres reservados da definição de URI no RFC3986 NÃO são ignorados encodeURIComponent().

Documentos da Web MDN: encodeURIComponent ()

Para ser mais rigoroso no cumprimento da RFC 3986 (que reserva!, ', (,) E *), mesmo que esses caracteres não tenham usos formalizados para delimitação de URI, o seguinte pode ser usado com segurança:

Use a função MDN Web Docs ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
HoldOffHunger
fonte