URL编码和解析

1.什么是URL?

URL(Uniform Resource Locator,统一资源定位符)是互联网上标准资源的地址,互联网上每个文件(即资源)都有一个唯一的URL,它包含了文件的位置以及浏览器处理方式等信息。

URL 标准格式
通常而言,我们所熟悉的 URL 的常见定义格式为:

scheme://host[:port#]/path/.../[;url-params][?query-string][#anchor]

scheme:有我们很熟悉的http、https、ftp以及著名的ed2k,迅雷的thunder等。
host:HTTP服务器的IP地址或者域名
port:HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如tomcat的默认端口是8080 http://localhost:8080/
path:访问资源的路径
url-params:所带参数
query-string:发送给http服务器的数据
anchor:锚点定位

2.URI和URL

很多人会混淆这两个名词。

URL:(Uniform/Universal Resource Locator 的缩写,统一资源定位符)。
URI:(Uniform Resource Identifier 的缩写,统一资源标识符)。
关系:
URI 属于 URL 更低层次的抽象,一种字符串文本标准。
就是说,URI 属于父类,而 URL 属于 URI 的子类。URL 是 URI 的一个子集。
二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。

3.URL和编码和解析

为什么要进行URL编码?通常如果一样东西需要编码,说明这样东西并不适合直接进行传输。

1、会引起歧义:例如 URL 参数字符串中使用 key=value 这样的键值对形式来传参,键值对之间以 & 符号分隔,如 ?postid=5038412&t=1450591802326,服务器会根据参数串的 & 和 = 对参数进行解析,如果 value 字符串中包含了 = 或者 & ,如宝洁公司的简称为P&G,假设需要当做参数去传递,那么可能URL所带参数可能会是这样 ?name=P&G&t=1450591802326,因为参数中多了一个&势必会造成接收 URL 的服务器解析错误,因此必须将引起歧义的 & 和 = 符号进行转义, 也就是对其进行编码。

2、非法字符:又如,URL 的编码格式采用的是 ASCII 码,而不是 Unicode,这也就是说你不能在 URL 中包含任何非 ASCII 字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

接下来介绍URL编码和对应的解析方法

encodeURI()和 decodeURI()

encodeURI() 是 Javascript 中真正用来对 URL 编码的函数。它着眼于对整个URL进行编码。

encodeURI("https://blog.csdn.net/CYL_2021/some other thing")
//https://blog.csdn.net/CYL_2021/some%20other%20thing

从上述编码结果可以看出空格会被%20代替,但该方法不会对 ASCII字母 、数字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ’ 进行编码。

decodeURI() 解码

decodeURI("https://blog.csdn.net/CYL_2021/some%20other%20thing")
//https://blog.csdn.net/CYL_2021/some other thing

encodeURIComponent()和decodeURIComponent()

我们的 URL 长这样子,请求参数中带了另一个 URL :

var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456";

直接对它进行 encodeURI 显然是不行的。因为 encodeURI 不会对冒号 : 及斜杠 / 进行转义,那么就会出现上述所说的服务器接受到之后解析会有歧义。

encodeURI(URL)
// "http://www.a.com?foo=http://www.b.com?t=123&b=456"

这个时候,就该用到 encodeURIComponent() 。它的作用是对 URL 中的参数进行编码,记住是对参数,而不是对整个 URL 进行编码。
因为它仅仅不对 ASCII字母、数字 ~ ! * ( ) ’ 进行编码。
错误的用法:

var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456";
encodeURIComponent(URL);
// "http%3A%2F%2Fwww.a.com%3Ffoo%3Dhttp%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456"

错误的用法,看到第一个 http 的冒号及斜杠也被 encode 了
正确的用法:encodeURIComponent() 着眼于对单个的参数进行编码:

var param = "http://www.b.com?t=123&s=456"; // 要被编码的参数
URL = "http://www.a.com?foo="+encodeURIComponent(param);
//"http://www.a.com?foo=http%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456"

decodeURIComponent() 解码

decodeURIComponent(URL)
//http://www.a.com?foo=http://www.b.com?t=123&s=456

4. 应用: 解析 URL Params 为对象

let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
parseParam(url)
/* 结果
{ user: 'anonymous',
id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
city: '北京', // 中文需解码
enabled: true, // 未指定值得 key 约定为 true
}
*/
function parseParam(url){
    
    
    const paramsStr=/.+\?(.+)$/.exec(url)[1];//将?后面的字符串取出来
    const paramsArr=paramsStr.split('&');// 将字符串以 & 分割后存到数组中
    let paramsObj={
    
    };//将params存到对象中
    paramsArr.forEach(param=>{
    
    
        if(/=/.test(param)){
    
     // 处理有 value 的参数
            let [key,val]=param.split('='); // 分割 key 和 value
            val=decodeURIComponent(val);// 解码
            val=/^\d+&/.test(val)?parseFloat(val):val;// 判断是否转为数字
            if(paramsObj.hasOwnProperty(key)){
    
    // 如果对象有 key,则添加一个值
                paramsObj[key]=[].concat(paramsObj[key],val);

            }else{
    
    // 如果对象没有这个 key,创建 key 并设置值
                paramsObj[key] = val;
            }
        }else{
    
     // 处理没有 value 的参数
            paramsObj[param] = true;
        }
    })
    return paramsObj;
}

参考文章:https://www.cnblogs.com/coco1s/p/5038412.html

猜你喜欢

转载自blog.csdn.net/CYL_2021/article/details/130042085