Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

URL再理解 #18

Open
2 tasks
LiberoWang opened this issue Nov 20, 2017 · 0 comments
Open
2 tasks

URL再理解 #18

LiberoWang opened this issue Nov 20, 2017 · 0 comments

Comments

@LiberoWang
Copy link

LiberoWang commented Nov 20, 2017

题目:
小明刚开始学习前端编程,发现一个术语经常出现:URL.他大概知道URL是个什么样的概念,但是不知道哪些URL是合法的,哪些是不合法的?究竟一个完整的url由哪些部分构成呢?
请阅读URL规范文档,告诉小明答案。
任务:
调查URL

1.URL的构成

scheme://[user:password@]hostname[:port]/path/[;parameters][?query][#fragment]

scheme: 协议名(不区分大小写),以冒号(:)结束。协议所表示的是获取该资源需要使用的协议。一般协议有http、https、ftp、gopher、telnet、file等。
//:层级URL标识符号。基本上每个URL中都会包含这个符号,是固定的;可以理解为把协议与后面的信息进行分隔开的一个符号。这样的一个好处是Web应用无需关注某个协议的具体实现,而只需要关注于’//’符号后面的指向地址即可。
但是也存在这非层级结构的URL:例如,mailto:协议。当使用mailto:user@example.com?....的时候,该URL将能够传递到默认的邮件客户端程序而无需其他的解析。
user:password@:授权信息/身份验证, @前的是密码:冒号前的是用户名,该部分使用的是@作为该部分的结束符号。很多服务器都要求输入用户名和密码才会允许用户访问数据。其实这一块信息我们看到的比较少,这是一个可选部分,一般的协议(http\https之类)都会使用默认的匿名形式进行数据获取。FTP服务器就是一个常见的实例。

ftp://anonymous@ftp.prep.ai.mit.edu/pub/gnu
ftp://anonymous:my_password@ftp.prep.ai.mit.edu/pub/gnu
http://joe:joespassword@www.joes-hardware.com/sales_info.txt

如果某应用程序使用的URL方案要求输入用户名和密码,比如FTP,但是用户没有提供,通常会插入一个默认的用户名和密码(FTP URL,没有指定用户名和密码,会以anonymous(匿名用户)作为用户名,IE会以IEUser作为密码)。
hostname:服务器地址。这是一个很关键的部分,这关系到你需要从哪个服务器上去获取资源。而我们看到的比较多的是这部分以域名(htc.org)的形式呈现,还有以Ipv4(220.181.111.188)的地址呈现。当然也能够以Ipv6的形式呈现。按照标准的描述是这部分只能用:数字、“.”、“-”组成。但浏览器对这支持的字符会比较多。
port: 服务器端口。这里是属于网络端口,因此可选为[0~2^16),这里的端口并不是物理端口,而是逻辑端口;只要是为了处理多进程时数据进行传输的时候,保证各进程中数据不会发生紊乱,能够传送到相应的进程中所设定的。
path:前面提到的URL指向的是一个唯一确定的资源,而这里指向的是资源的完整路径(即存储的位置,在服务器的哪个地方),一般都是用 / 进行分层描述。
parameters:参数。有些方案,单靠主机名和路径是不足的,需要更多的信息才能工作。负责解析URL的应用程序需要这些协议参数来访问资源。否则服务器不提供服务或者提供错误服务。
ftp://prep.ai.mit.edu/pub/gnu;type=d
有一个参数type=d,参数名type,值为d。
http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
有俩个路径段,hammers和index.html。hammers段有参数sale值为false,index.html有参数graphisc值为true。
?query:查询字符串。用“&”符号隔开,每个参数的名和值用“=”对应。这里的查询字符串是用于参数传递给服务器端。但标准没有对这一部分有着特别严格的规定。这一部分是以 ? 开始作为标识,而现在一般的用法都是类似于以下的形式,?name=hello&id=5&…
#fragment:该部分与上面的?后面的表单信息本质的区别就是这部分内容不会被传递到服务器端。一般用于页面的锚。就是我们常见的网站右下脚一般有一个回到顶部的按钮,一般就是使用其实现的。

2.URL解析

url-analysis

解析url

  • 判断URL是否是合法的URL,如果URL不合法,则调用默认的搜索引擎,直接把输入的内容作为要搜索的内容进行搜索,如果URL合法,则继续下一步。
  • 检查这些请求是HTTPS还是HTTP,如果是HTTPS的话则使用HTTPS协议进行访问,否则使用HTTP协议发送。有些情况下,第一个请求不是HTTPS的,但是当浏览器向网站发出第一个HTTP请求之后,网站会返回浏览器一个响应,请求浏览器使用HTTPS发送请求。
  • 将URL进行字符转换

查找IP地址

  • 先检查浏览器的缓存,看看所要访问的域名是否存在于缓存之中,如果存在,则直接使用缓存中的IP地址进行访问,如果不存在,执行下一步
  • 缓存中没有找到,则调用系统的gethostbyname库函数,进行查询,gethostbyname函数会先检查域名是否在本地的Hosts文件中,如果找到直接返回域名对应的IP,(这也当访问不到某网址时,修改hosts文件的原因)如果没有找到则执行下一步
  • 向DNS服务器发送一个域名查询请求,然后就执行DNS查询过程,这个过程一般情况下会返回所要访问域名对应的IP地址,除非域名真的不存在,或者DNS服务器出现故障。

建立连接

  • 当浏览器得到了目标服务器的IP地址,以及 URL 中给出来端口号(http 协议默认端口号是 80, https 默认端口号是 443),它会调用系统库函数 socket ,请求一个 TCP流套接字。进行网络数据的传输。
  • 连接建立之后,则根据HTTP协议进行数据交换,资源通常是HTML 文件,也可能是 PDF,图片,或者其他类型的内容。

页面渲染

  • 浏览器获得资源文件后,HTML,css,js等文件则根据自身内核的机制,进行页面渲染,然后呈现给用户。

3.URL的合法性

官方API
参考链接:URLSearchParams
url-class
url-searchclass
手动检验:
2017-11-21 10 57 26

Example:
url-examples

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

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

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

编码后变为上述结果,可以看到空格被编码成了%20,而斜杠 / ,冒号 : 并没有被编码。
是的,它用于对整个 URL 直接编码,不会对 ASCII字母 、数字 、 ~ ! @ # $ & * ( ) = : / , ; ? + ‘ 进行编码。

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

encodeURIComponent()
与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。
因此,“; / ? : @ & = + $ , #”,这些在encodeURI()中不被编码的符号,在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"

5.URL相关设置获取

1>. 设置或获取整个 URL 为字符串
var url=window.location.href
返回结果:url https://www.baidu.com/
2>. 设置或获取 URL 的协议部分
var protocol= window.location.protocol;
返回结果: http:
3>. 设置或获取主机
var host =window.location.host
返回结果:www.baidu.com
4>. 设置或获取url端口
var port =window.location.port
返回结果: " " (如果采用默认的80端口(update:即使添加了:80),那么返回值并不是默认的80而是空字符)
5>. 设置或获取与 URL 的路径部分
url="http://echarts.baidu.com/option.html";
var pathname= window.location.pathname;
返回结果:"/option.html"
6>. 设置或获取 href 属性中跟在问号后面的部分
url="http://localhost:63342/project/6-21/aa.html?_ijt=flc0nna93fr89j3dlhh9mn7eco"
var param= window.location.search;
返回结果: "?_ijt=flc0nna93fr89j3dlhh9mn7eco"
7>. 设置或获取 href 属性中在井号“#”后面的分段
url="http://echarts.baidu.com/option.html#title.left"
var param= window.location. hash;
返回结果: "#title.left"

6.URL快捷方式

参考链接:HTTP权威指南--URL快捷方式

相对URL
URL扩展

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant