HTTP请求
认识URL
URL基本格式
平时我们俗称的"网址"其实就是说的URL(Uniform Resource Locator统一资源定位符). (还有一个唯一资源标识符,称为uri,严格来说,uri范围比url广).
互联网上的每一个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.
URL的详细规则由因特网标准RFC1738进行了约定.
http :协议方案名.常见的有http和https, 也有其他的类型.(例如访问mysql时用的jdbc:mysql)
user:pass :登录信息,由于安全问题,现在的网站进行身份认证一般不再通过URL进行了,一般都会省略.
www.example.jp :服务器地址.此处是一个"域名"(这里的域名也可以是IP地址,可以通过DNS系统解析成一个具体的IP地址).
80 : 端口号.这里是设定的为80.如果url中不带端口号,浏览器就会自动给默认端口,用什么端口,取决于协议.(http -> 80, https -> 443).
/dir/index.htm :带层次的文件路径.(可能是个真实的硬盘文件,也可以对应一个虚拟的文件)
网络上资源位置:(1)通过ip地址知道服务器在哪.(2)通过端口号知道程序是哪一个.
(3)通过路径访问资源.
uid=1 :查询字符串.本质是一个键值对结构.键值之间用&分隔.键和值之间用=分隔.(这是针对请求内容做的补充说明,是客户端给服务器传递的重要途径,内容由程序猿自定义).
ch1 :片段标识.片段标识主要用于页面内跳转.(例如Vue官方文档: Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org), 旁边有一个类似于目录的东西,通过点击跳转,上面url的片段标识也会变化,这就是利用了片段标识).
结合上述的内容,就可以描述出一个网络资源了.
举个例子:描述一个蟹黄堡资源
http://蟹堡王:比奇堡32号/蟹堡王/巨无霸双层蟹堡?洋葱=不要&&美乃滋=大量&&酸黄瓜=2片
使用ping命令查看域名对应的IP地址.
在cmd中输入 ping mp.csdn.net,即可看到域名解析结果.
关于query string.
query string 中的内容是键值对结构.其中key和value的取值和个数,完全都是由程序员自己约定的.我们可以通过这样的方式来定制传输我们需要的信息给服务器.
URL中可以省略的部分
协议名:可以省略,省略后默认为http://
ip地址/域名:在HTML中可以省略.省略后表示的服务器ip/域名与当前HTML所属的ip/域名一致
端口号:可以省略.省略后如果是http协议,端口号自动设为80,如果是https协议,自动设为443.
带层次的文件路径:可以省略.省略后相当于/.有些服务器会在发现/路径时自动访问/index.html
查询字符串:可以省略
片段标识:可以省略.
关于URL encode
像/?:这样的字符,已经被url当作特殊意义来理解了.因此这些字符不能随意出现.
比如,某个参数中需要带这些特殊字符,就必须先对特殊字符进行转义.
一个中文字符由UTF-8或者GBK这样的编码方式构成,虽然URL中没有特殊含义,但是仍然需要进行转义.否则浏览器可能把UTF-8/GBK编码中的某个字节当作URL中的特殊符号.
转义的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每两位做一位,前面加上%,编码成%xy形式.
"+"被转义成了"%2B".
urldecode就是urlencode 的逆过程.
认识"方法"(method)
但是事实上,这些方法的语义,都是"标准文档作者"的一厢情愿
开发者在实际开发程序的时候,才不管这一套!(它们干啥我说了算)
完全可以用POST来从服务器拿数据,也完全可以用GET往服务器放数据.
GET方法(读操作)
GET是最常用的HTTP方法,常用于获取服务器上的某个资源.
在浏览器中直接输入URL,此时浏览器就会发送一个GET请求.
另外,HTML中的link,img,script等标签,也会触发GET请求.
使用Fiddler进行抓包观察请求结果
随便抓一个:
GET请求的特点
首行的第一部分为GET.
URL的query string可以为空,也可以不为空.
header部分有若干个键值对结构.
body部分为空.
关于GET请求的URL长度问题
网上有些资料描述:get请求长度最多1024kb,这样的说法是错误的.
他说的是以前.实际上HTTP标准文档上明确说了,对于GET URL的长度不做限制.之前老版本的IE浏览器在实现的时候,URL的长度有限制(历史了). 目前较长的URL也是很常见的.
POST方法(写操作)
POST也是一种常见的方法.多用于提交用户输入的数据给服务器(例如登录页面).
POST请求的特点
首行的第一部分为POST;
URL的 query string 一般为空(也可以不为空);
header部分有若干个键值对结构.
body部分一般不为空.body内的数据格式通过header中的Content-Type指定.body的长度由header中的Content-Length指定.
经典面试题:谈谈GET和POST的区别.
先盖棺定论:GET和POST本质上没有区别.
使用GET的场景,也可以替换成POST.使用POST的场景,也能替换成GET.
这个取决于代码是咋写的.尤其是服务器和客户端都是你自己实现的情况下.
部分服务器/部分浏览器某些状况下GET和POST不能完美替换
但是大部分情况下相互替换问题不大.
但是GET和POST在使用习惯上还是有区别的.
1.GET习惯于将数据放到url的query string中.POST习惯于把数据放到body中.
其实GET也可以把数据放到body(有的服务器/浏览器可能不支持)
POST也可以把数据放到query string中(对于绝大部分的服务器和浏览器都支持).
2.语义上的区别:标准文档中,GET的语义是用来获取数据,POST的语义是给服务器传输数据.
实际使用并不一定非得拘泥于上述要求.
3.关于幂等性.标准文档中,建议GET请求实现成幂等的.POST则无要求.
幂等源于数学属于,计算机种也很常用.
每次输入的结果一定,输出的结果也一定,称为幂等.
每次输入的内容一定,输出的结果不一定,不是幂等.
计算机中的幂等也是挺关键的一件事情,如果某个操作本身是幂等的,此时就可以进行缓存了.
因而GET可以缓存,POST不可以.
4.GET请i去可以被浏览器收藏夹收藏,POST请求不可以.
补充说明:
关于安全性:有些资料说:"POST和GET更安全",这样的说法是不科学的,是否安全主要取决于前端是否在传输密码等敏感信息时是否进行加密,和GET/POST无关.
关于传输数据类型:有的资料说"GET只能传输文本数据,POST可以传输二进制数据".这个是不科学的.GET的query string虽然无法直接传输二进制数据,但是可以针对二进制数据进行url encode.