如何使用JavaScript安全地编码URL,以便将其放入GET字符串中?

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

我假设您需要在第二行编码myUrl变量?


当前回答

没有什么对我有用。我看到的只是登录页面的HTML,返回到客户端,代码为200。(最初是302,但相同的Ajax请求在另一个Ajax请求中加载登录页面,这应该是一个重定向,而不是加载登录页面的纯文本)。

在登录控制器中,我添加了以下行:

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

在全局Ajax处理程序中,我这样做了:

$(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;
            }
        }
    });
});

现在我没有任何问题,它就像一个魅力。

其他回答

表演

今天(2020.06.12),我在浏览器Chrome 83.0、Safari 13.1和Firefox 77.0的macOS v10.13.6(High Sierra)上对所选解决方案进行了速度测试。这一结果对于大规模URL编码非常有用。

结论

encodeURI(B)似乎最快,但不建议用于URLescape(A)是一种快速的跨浏览器解决方案MDN推荐的解决方案F为中速解决方案D最慢

细节

对于解决方案A.BCDEF我进行了两次测试

对于短URL-50个字符-您可以在这里运行对于长URL-1M个字符-您可以在此处运行

函数A(url){返回转义符(url);}函数B(url){返回encodeURI(url);}函数C(url){返回encodeURIComponent(url);}函数D(url){返回新的URLSearchParams({url}).toString();}函数E(url){return encodeURIComponent(url).replace(/[!'()]/g,escape).replace(/\*/g,“%2A”);}函数F(url){return encodeURIComponent(url).replace(/[!'()*]/g,函数(c){return“%”+c.charCodeAt(0).toString(16);});}// ----------//测试// ----------var myUrl=“http://example.com/index.html?param=1&anotherParam=2";[A、B、C、D、E、F].forEach(f=>console.log(`${f.name}?url=${f(myUrl).replace(/^url=/,'')}`));此代码段仅显示所选解决方案的代码

Chrome的示例结果

您有三个选项:

escape()不会编码:@*/+encodeURI()不会编码:~@#$&*()=:/,;?+'encodeURIComponent()不会编码:~*()'

但在您的情况下,如果要将URL传递到其他页面的GET参数中,则应该使用escape或encodeURIComponent,而不是encodeURI。

有关详细讨论,请参阅堆栈溢出问题最佳实践:转义或encodeURI/encodeURIComponent。

不应直接使用encodeURIComponent()。

看看RFC3986:统一资源标识符(URI):通用语法

sub-delims=“!”/“$”/“&”/“'”/“(”/“)”/ "*" / "+" / "," / ";" / "="保留字符的目的是提供一组可与URI中的其他数据区分的分隔字符。

这些来自RFC3986中URI定义的保留字符不会被encodeURIComponent()转义。

MDN Web文档:encodeURIComponent()

为了更严格地遵守RFC 3986(保留!、'、(、)和*),即使这些字符没有正式的URI分隔用途,也可以安全地使用以下字符:

使用MDN Web Docs功能。。。

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

没有什么对我有用。我看到的只是登录页面的HTML,返回到客户端,代码为200。(最初是302,但相同的Ajax请求在另一个Ajax请求中加载登录页面,这应该是一个重定向,而不是加载登录页面的纯文本)。

在登录控制器中,我添加了以下行:

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

在全局Ajax处理程序中,我这样做了:

$(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;
            }
        }
    });
});

现在我没有任何问题,它就像一个魅力。

现代解决方案(2021)

自从编写了其他答案后,就引入了URLSearchParams API。它可以这样使用:

const queryParams = { param1: 'value1', param2: 'value2' }
const queryString = new URLSearchParams(queryParams).toString()
// 'param1=value1&param2=value2'

它还编码非URL字符。

对于您的具体示例,您可以这样使用:

常量myUrl=“http://example.com/index.html?param=1&anotherParam=2";const myOtherUrl=新URL(“http://example.com/index.html");myOtherUrl.search=新URLSearchParams({url:myUrl});console.log(myOtherUrl.toString());

这个解决方案也在这里和这里提到。