HTTP协议 Request 详解

183 阅读5分钟

请求头

如图是一个简单的HTTP Request报文。在这个报文中,第一行固定是请求的方法、资源和http的版本号。

第二行就是请求的头信息了。就是上图中蓝色背景的这一块内容。从http1.1开始,头信息中的Host就是必须的了。 用来区分请求的到底是那个虚拟主机,对应的是那个网站。

此时我们有个一个疑问,在建立TCP链接的时候是提供了域名的,为什么不能用这里提供的域名呢?

因为,在建立TCP链接的时候,可以写域名、也可以写IP。能够通信就可以了。

如果写的是域名,那么客户机首先会把域名解析成IP,最后还是通过IP链接到服务器的。所以服务器是不知道客户机使用那个域名链接服务器的。因此在http请求头里面指定域名是必须的,只有这样才能够区分出来到底要访问哪个虚拟路径。

事实上,标准的头信息还有很多,后面的文章中会慢慢分享。

这里除了适用标准的之外,也可以增加一些自定义的头信息。头信息都是每一个占一行,以 key: value的形式表示。注意每一行的分割,是通过回车换行\r\n 2个字符, 而不是仅仅回车或者仅仅换行,这个和windows系统下的换行是一致的。

在头信息结束之后,会有一个空行,这个空行一定是只包含一个回车换行,不包含任何空格。该空行来标识,头信息结束了,下面就是body的部分。

但是并不是所有的请求都有body部分,比如GET方法就没有Body部分。而POST方法是一定有Body部分的。Body部分的内容格式和长度都会在头信息中指定出来。

比如:

上述是浏览器中提交表单时的一种常用格式。如果表单中没有文件上传,我们一般就会是使用这种Content-Type格式。还有一些比如JSON格式,html格式也是比较常用的。

HTTP的请求方法

在1.1版本中,一共支持8个方法。

幂等性 idempotence

通俗的讲就是说,多次访问同一个资源,可能是post,也可能能get,结果是相同的,这样就具有幂等性了

http的方法都应该具有幂等性。这在编写api的时候是特别重要的。api都应该具有幂等性。

HTTP有哪些标准头

Accept,其实只是表示客户端能接受什么类型的数据,但并不是说服务器会返回什么类型的数据。

Accept-Language: 一般做国际化的时候,我们会根据这个判断来返回适当的语言。

Authorization: 有时候访问网站浏览器会弹框要求用户输入用户名密码,那么输入的用户名和密码实际上就是通过这个传输过去的。注意不是表单哦。

Connection: upgrade要求服务升级。这里其实要配合Upgrade一起使用。

Content-Type: 这个只会在请求类型是post/put等这种有Request Body的时候才会有这个。它就是指定Request Body使用那种类型的编码进行编码的。

Content-Length是指body部分的长度,通常情况下是要跟Content-Type配合使用的。

Range:我们目前用的比较少,但是在下载一些东西的时候,特别是下载一些大的文件的时候,会采用分段下载、还有一些断点续传,这些其实就是需要用到Range,同时携带字节偏移量。当然这是需要服务端支持的。

Referer:是指访问这个网站之前访问的url,可以根据它来判断访问来源。同时,它也可以判断一些站内的访问路径,一些做网站的访问跟踪的和统计的都是靠referer来确定每一个用户的访问路径。

User-Agent 就是浏览器的信息,一般是个很长的字符串。如果判断用户使用了哪种操作系统、哪个浏览器之类的都是可以通过这个字段判断的。

Upgrade:要结合前面提到的使用,我们在Connection写上协议升级,再在这里写上需要升级的协议。

最后2个灰色背景的最开始的时候其实不是协议里面规定的,但后来已经成为事实标准了。

X-Forwarded-For: 在通过代理的时候会加这样的一个头,这个头会携带以前的IP,所以这里面可能是一个,也可能是多个IP/域名,并用逗号隔开。

其中第一个是最原始的客户机的IP,每过一个代理就会加上自身的IP,如果你需要判断取得最原始用户的IP,可以通过这里来判断。

但是需要注意的是,并不是每个代理都会传递http的头,可能有些匿名ID,根本不会传递这个信息。更糟糕的是这个是可以伪造的。事实上,任何http的头都是可以伪造的。如果别人伪造了http头信息,那么使用这个也是判断不出来的。

X-Requested-With: 这个实际上是用来标记AJAX的。如果你在浏览器中,一般请求都是通过Ajax发出的,都会带这个头。

这是Java的一个类,有一些常用的方法:

HttpServletRequest

session里面的东西都是存在服务端的。而不是传递的。

http协议是一个无状态的协议,也就是说,第一次和第二次请求是不通的链接,所以我们是没有办法简单的将这两次请求认作是同一个人的,认作同一个人实际上是靠在服务端发现一个sessionId,这个值是通过cookie传递,来判断是同一个人。

sessionId,在不同的web服务器中是不一样的。然后服务端根据sessionId,到对应的存储里面去取值。