首页 > 其他分享 >URL详解与URL编码

URL详解与URL编码

时间:2024-04-09 11:46:38浏览次数:26  
标签:编码 www http URL 详解 com encodeURI

URL详解与URL编码

 

作为前端,每日与 URL 打交道是必不可少的。但是也许每天只是单纯的用,对其只是一知半解,随着工作的展开,我发现在日常抓包调试,接口调用,浏览器兼容等许多方面,不深入去理解URL与URL编码则会踩到很多坑。故写下此篇文章,详解一下 URL 。

URL 与 URI

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

URL:(Uniform/Universal Resource Locator 的缩写,统一资源定位符)。

URI:(Uniform Resource Identifier 的缩写,统一资源标识符)。

关系:

URI 属于 URL 更低层次的抽象,一种字符串文本标准。

就是说,URI 属于父类,而 URL 属于 URI 的子类。URL 是 URI 的一个子集。

二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。

 

端口 与 URL标准格式

何为端口?端口(Port),相当于一种数据的传输通道。用于接受某些数据,然后传输给相应的服务,而电脑将这些数据处理后,再将相应的回复通过开启的端口传给对方。

端口的作用:因为 IP 地址与网络服务的关系是一对多的关系。所以实际上因特网上是通过 IP 地址加上端口号来区分不同的服务的。

端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535。

 

URL 标准格式。

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

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

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

 

利用 <a> 标签自动解析 url

开发当中一个很常见的场景是,需要从 URL 中提取一些需要的元素,譬如 host 、 请求参数等等。

通常的做法是写正则去匹配相应的字段,当然,这里要安利下述这种方法,来自 James 的 blog,原理是动态创建一个 a 标签,利用浏览器的一些原生方法及一些正则(为了健壮性正则还是要的),完美解析 URL ,获取我们想要的任意一个部分。

代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // This function creates a new anchor element and uses location // properties (inherent) to get the desired URL data. Some String // operations are used (to normalize results across browsers).   function parseURL(url) {     var a =  document.createElement('a');     a.href = url;     return {         source: url,         protocol: a.protocol.replace(':',''),         host: a.hostname,         port: a.port,         query: a.search,         params: (function(){             var ret = {},                 seg = a.search.replace(/^\?/,'').split('&'),                 len = seg.length, i = 0, s;             for (;i<len;i++) {                 if (!seg[i]) { continue; }                 s = seg[i].split('=');                 ret[s[0]] = s[1];             }             return ret;         })(),         file: (a.pathname.match(/([^/?#]+)$/i) || [,''])[1],         hash: a.hash.replace('#',''),         path: a.pathname.replace(/^([^/])/,'/$1'),         relative: (a.href.match(/tps?:\/[^/]+(.+)/) || [,''])[1],         segments: a.pathname.replace(/^\//,'').split('/')     }; }

Usage 使用方法:

1 2 3 4 5 6 7 8 9 10 11 12 var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top');    myURL.file;     // = 'index.html' myURL.hash;     // = 'top' myURL.host;     // = 'abc.com' myURL.query;    // = '?id=255&m=hello' myURL.params;   // = Object = { id: 255, m: hello } myURL.path;     // = '/dir/index.html' myURL.segments; // = Array = ['dir', 'index.html'] myURL.port;     // = '8080' myURL.protocol; // = 'http' myURL.source;   // = 'http://abc.com:8080/dir/index.html?id=255&m=hello#top'

利用上述方法,即可解析得到 URL 的任意部分。

 

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 字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

 

那么如何编码?如下:

escape 、 encodeURI 、encodeURIComponent

  escape()

首先想声明的是,W3C把这个函数废弃了,身为一名前端如果还用这个函数是要打脸的

escape只是对字符串进行编码(而其余两种是对URL进行编码),与URL编码无关。编码之后的效果是以 %XX 或者 %uXXXX 这种形式呈现的。它不会对 ASCII字符、数字 以及 @ * / + 进行编码。

根据 MDN 的说明,escape 应当换用为 encodeURI 或 encodeURIComponent;unescape 应当换用为 decodeURI 或 decodeURIComponent。escape 应该避免使用。举例如下:

1 2 3 4 5 6 7 8 encodeURI('https://www.baidu.com/ a b c') // "https://www.baidu.com/%20a%20b%20c" encodeURIComponent('https://www.baidu.com/ a b c') // "https%3A%2F%2Fwww.baidu.com%2F%20a%20b%20c"   //而 escape 会编码成下面这样,eocode 了冒号却没 encode 斜杠,十分怪异,故废弃之 escape('https://www.baidu.com/ a b c') // "https%3A//www.baidu.com/%20a%20b%20c" 

 

  encodeURI()

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

1 2 encodeURI("http://www.cnblogs.com/season-huang/some other thing"); //"http://www.cnblogs.com/season-huang/some%20other%20thing";

编码后变为上述结果,可以看到空格被编码成了%20,而斜杠 / ,冒号 : 并没有被编码。

是的,它用于对整个 URL 直接编码,不会对 ASCII字母 、数字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ' 进行编码。

1 2 encodeURI("~!@#$&*()=:/,;?+'") // ~!@#$&*()=:/,;?+'

 

  encodeURIComponent()

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

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

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

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

这个时候,就该用到 encodeURIComponent() 。它的作用是对 URL 中的参数进行编码,记住是对参数,而不是对整个 URL 进行编码。

因为它仅仅不对 ASCII字母、数字 ~ ! * ( ) '  进行编码。

错误的用法:

1 2 3 4 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() 着眼于对单个的参数进行编码:

1 2 3 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"

 

利用上述的使用<a>标签解析 URL 以及根据业务场景配合 encodeURI() 与 encodeURIComponent() 便能够很好的处理 URL 的编码问题。

应用场景最常见的一个是手工拼接 URL 的时候,对每对 key-value 用 encodeURIComponent 进行转义,再进行传输。   原文地址:http://www.cnblogs.com/coco1s/p/5038412.html  

标签:编码,www,http,URL,详解,com,encodeURI
From: https://www.cnblogs.com/lvjinlin/p/18123607

相关文章

  • Javascript Promise用法详解
    1、约定本文的demo代码有些是伪代码,不可以直接执行。没有特殊说明,本文所有demo都是基于ES6规范。Object.method代表是静态方法,Object#method代表的是实例方法。如Promise#then代表的是Promise的实例方法,Promise.resolve代表的是Promise的静态方法.2、什么......
  • C#高级–反射详解
    一、反射是什么1、C#编译运行过程高级语言->编译->dll/exe文件->CLR/JIT->机器码2、原理解析metadata:元数据数据清单,记录了dll中包含了哪些东西,是一个描述。IL:中间语言,编译把高级语言编译后得到的C#中最真实的语言状态,面向对象语言。反射:来自于System.Reflection,是一个帮......
  • Promises/A+ 详解及实现
    规范:Promises/A+https://promisesaplus.com/此篇文章将在Node环境通过 Class 语法来实现一个符合Promises/A+规范的 MyPromise ,通过官方872个测试用例文章中x.x.x标记如2.1.1表示规范中对应的规范序号;myPromise 表示 MyPromise 的一个实例对象【2.......
  • 批量转换pcd数据的编码形式:Binary转ASCII
    本文为CSDN晚意丶3D原创,转载请表明原文出处———————————————————————————————————————批量转换pcd数据的编码形式:Binary转ASCII代码结果相关内容pcd点云格式的编码有两种,分别是Binary和ASCIIBinary是二进制格式,用文......
  • 预处理详解
    要想了解预处理,首先要了解预定义符号,它是由__和大写字母组成的:了解完预定义符号,就要知道用什么来表示预定义符号,用#define来定义常量和宏,#define定义常量:它的表达式为:#definenamestuff。它的基本代码为:#include<stdio.h>//#define定义常量#defineMAX1000intmain(......
  • 一文详解ThreadLocal与线程间的数据传递
    一.ThreadLocalThreadLocal在并发编程中比较常用,在诸多中间件的源码中都能看到它的身影。对于ThreadLocal的说明先来一段官方解释:ThreadLocal提供的是一种线程局部变量。这些变量不同于其它变量的点在于每个线程在获取变量的时候,都拥有它自己相对独立的变量副本。ThreadLo......
  • GC机制+字符编码+文件操作
    深浅拷贝深浅拷贝问题1.1定义理解给一个列表,想基于这个列表进行更改生成一个新的列表。方式一:将原来列表复制一份一摸一样的只对新列表生效,对原来的不生效num_list=[1,2,3]num_list_new=[1,2,3]num_list_new.append(4)print(num_list)#[1,2,3]print(num_list_n......
  • 【WPF应用41】WPF中的Expander控件详解
    WindowsPresentationFoundation(WPF)中的Expander控件是一个用于显示详细信息的交互式UI元素。它允许用户通过点击标题来展开或折叠内容区域。Expander控件通常用于在界面上组织内容,提供一种可见/隐藏的功能,以帮助用户专注于当前感兴趣的信息。一、Expander控件简介Expand......
  • C语言:指针详解(1)
    目录一、内存和地址二、指针变量和地址三、指针变量类型的意义四、const修饰指针五、指针运算六、野指针七、assert断言八、指针的使用和传值调用在正式学习指针之前,我们先要理解在C/C++中两个非常重要的概念——内存和地址。正是有这两种因素的存在,才使得C/C++拥有......
  • 051 Form fields(form-urlencoded and form-data)
    浏览器传值给服务器的Fromfilelds类型的两种方式form-urlencodedaction中去掉所有特性修饰publicIActionResultIndex2(int?bookid,bool?isloggedin,   Bookbook)Postman设置如下点击Send,通过此测试可以看出formfields的优先级更高,book中的值是下面body部......