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
|
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
|
// "https%3A%2F%2Fwww.baidu.com%2F%20a%20b%20c"//而 escape 会编码成下面这样,eocode 了冒号却没 encode 斜杠,十分怪异,故废弃之// "https%3A//www.baidu.com/%20a%20b%20c" |
encodeURI()
encodeURI() 是 Javascript 中真正用来对 URL 编码的函数。它着眼于对整个URL进行编码。
|
1
2
|
|
编码后变为上述结果,可以看到空格被编码成了%20,而斜杠 / ,冒号 : 并没有被编码。
是的,它用于对整个 URL 直接编码,不会对 ASCII字母 、数字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ' 进行编码。
|
1
2
|
encodeURI("~!@#$&*()=:/,;?+'")// ~!@#$&*()=:/,;?+' |
encodeURIComponent()
嘿,有的时候,我们的 URL 长这样子,请求参数中带了另一个 URL :
|
1
|
|
直接对它进行 encodeURI 显然是不行的。因为 encodeURI 不会对冒号 : 及斜杠 / 进行转义,那么就会出现上述所说的服务器接受到之后解析会有歧义。
|
1
2
|
encodeURI(URL) |
这个时候,就该用到 encodeURIComponent() 。它的作用是对 URL 中的参数进行编码,记住是对参数,而不是对整个 URL 进行编码。
因为它仅仅不对 ASCII字母、数字 ~ ! * ( ) ' 进行编码。
错误的用法:
|
1
2
3
4
|
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
|
|
利用上述的使用<a>标签解析 URL 以及根据业务场景配合 encodeURI() 与 encodeURIComponent() 便能够很好的处理 URL 的编码问题。
URL详解与URL编码的更多相关文章
- 【基础进阶】URL详解与URL编码
作为前端,每日与 URL 打交道是必不可少的.但是也许每天只是单纯的用,对其只是一知半解,随着工作的展开,我发现在日常抓包调试,接口调用,浏览器兼容等许多方面,不深入去理解URL与URL编码则会踩到很 ...
- Fiddler抓包6-get请求(url详解)
前言 上一篇介绍了Composer的功能,可以模拟get和post请求,get请求有些是不带参数的,这种比较容易,直接放到url地址栏就行.有些get请求会带有参数,本篇详细介绍url地址格式. 一. ...
- Fiddler抓包6-get请求(url详解)【转载】
本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/fiddler/ 前言 上一篇介绍了Composer的功能,可以模拟get和post请求 ...
- 3、get请求(url详解)
前言 上一篇介绍了Composer的功能,可以模拟get和post请求,get请求有些是不带参数的,这种比较容易,直接放到url地址栏就行.有些get请求会带有参数,本篇详细介绍url地址格式. 一. ...
- 基础篇-http协议《http 简介、url详解、request》
目录 一.http 简介 二.url 详解 三.request 1.get 和 post 2.请求方法 3.request 组成 4.请求头 5.get 请求参数 6.post 请求参数 7.post ...
- HTTP协议详解以及URL具体访问过程
1.简介 1.1.HTTP协议是什么? 即超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准.从 ...
- URI与URN与URL详解
当没有URI时 什么是URI和URN和URL URI详解 Uniform Resource Identifier 统一资源标识符 URI的组成 案例: https://tools.ietf.org/h ...
- php使用http_build_query,parse_url,parse_str创建与解析url详解
1.http_build_query string http_build_query ( mixed $query_data [, string $numeric_prefix [, string $ ...
- Django框架详解之url
Django基本命令 下载Django pip3 install django 创建一个django project django-admin.py startproject cms 当前目录下会生成 ...
随机推荐
- 关闭 Sublime Text 3 自动更新
打开Submine Text,找到Preferences -> Settings-User写入 "update_check":false,PS:一定要加逗号.不会可以看图片 ...
- [No000049]狗日的中年——姜文
文件名 大小 [No000049]狗日的中年——姜文.7z 228KB
- vijos 1512
SuperBrother打鼹鼠 背景 SuperBrother在机房里闲着没事干(再对比一下他的NOIP,真是讽刺啊......),于是便无聊地开始玩“打鼹鼠”...... 描述 在这个“打鼹鼠”的游 ...
- PHP核心技术与最佳实践--笔记
<?php error_reporting(E_ALL); /* php 5.3引入 延迟静态绑定 */ /* php5.4引入trait,用来实现多层继承 trait Hello{} trai ...
- android values目录的读取优先级
android项目新建时会有一个values目录(高版本会增加values-v11,values-v14目录),该目录用于存放显示相的配置数据的定义文件,如strings.xml, style.xml ...
- document.elementFromPoint在IE8下无法稳定获取当前坐标元素的解决方法
document.elementFromPoint(e.clientX, e.clientY) document.elementFromPoint(e.clientX, e.clientY) 执行2次 ...
- NOI2018准备Day2
昨天雄心壮志了一番,今天就有点儿松懈了,是生于忧患,死于安乐吗 刷了15道大水题,5道字符串,5道多维数组,5道顺序查找,9个小时,平均40分钟一道水题,目标10分钟一道......昨天才刷了20道. ...
- java:如何用代码控制H2 Database启动
1.纯手动start/stop package com.cnblogs.yjmyzz.h2; import java.sql.Connection; import java.sql.DriverMan ...
- VMware-Transport(VMDB) error -44:Message.The VMware Authorization Service is not running解决方案
出现的错误如下: 原因:本机中有一个VMware服务未开启导致的. 解决方案: 1.打开“运行”->输入services.msc !!!文章转自浩瀚先森博客,转载请注明,谢谢.http://ww ...
- Vuforia AR SDK入门
Vuforia是一个能让应用拥有视觉的软件平台.开发者借助它可以很轻松地为任何应用添加先进计算机视觉功能,允许你识别图片和物体,或者在真实世界中重建环境内容. 如果你现在正在制作一些可交互的市场活动项 ...