Bootstrap

深入学习HTTP-----HTTP报文格式/消息结构

注:文章部分图片来自于《图解HTTP》


一.HTTP概念介绍

参见:HTTP概念介绍

一个例子—访问百度首页
curl -v https://www.baidu.com/ 

在命令行使用Curl工具,输入上面的指令。p.s. curl的用法详解:curl工具用法详解


Trying 36.152.44.95...
TCP_NODELAY set
Connected to www.baidu.com (36.152.44.95) port 443 (#0)

//
///注意:其中省略HTTPS相关流程
//

> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: keep-alive
< Content-Length: 2443
< Content-Type: text/html
< Date: Tue, 29 Sep 2020 06:07:19 GMT
< Etag: "5886041d-98b"
< Last-Modified: Mon, 23 Jan 2017 13:24:45 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
< 
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
Connection #0 to host www.baidu.com left intact
Closing connection 0
  1. 首先,可以看出我们访问的HTTP请求是经过HTTPS服务的,所以其中有握手,校验证书等步骤,这个可以不管
  2. 这个大家都比较熟悉了,就是HTML文件的文件头部的一个标签
  3. 剩下的部分,其实就是我们请求的HTTP报文和返回的HTTP响应消息,下面详细来看一下。

二.HTTP请求消息结构


1.定义&例子

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。


在这里插入图片描述

一个 http 请求报文由四个部分组成:

  1. 请求行(Request-Line)
  2. 请求头部(Request Header Fields)
  3. 回车换行(CRLF)
  4. 消息体(Message Body)

对应到刚才我们请求百度的例子:

> GET / HTTP/1.1 //请求行
> Host: www.baidu.com//请求头
> User-Agent: curl/7.64.1//请求头
> Accept: */*  //请求头
> 

由于我们发的是GET请求,并没有携带请求数据,所以只有这么短短的几行。下面看一下用POST请求的效果

> POST /2019/06/24/domainexpire/ HTTP/1.1
> Host: www.zhangblog.com
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 21
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 21 out of 21 bytes --->并没有显示请求体

没有显示请求体可能是Curl工具问题,这里留个坑,网上也没查到


2.常见请求头/响应头参数

不难发现,请求消息中,请求头的数据很多,都是Key-value这种形式的,它用来告知服务端这个请求的一些信息。


三.HTTP响应消息结构

一个HTTP 响应报文有以下几部分组成:

  1. 状态行
  2. 响应头部
  3. 空行
  4. 请求数据

在这里插入图片描述
对应到刚才我们请求百度的例子:

< HTTP/1.1 200 OK -----> 状态行
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: keep-alive
< Content-Length: 2443
< Content-Type: text/html
< Date: Tue, 29 Sep 2020 06:07:19 GMT
< Etag: "5886041d-98b"
< Last-Modified: Mon, 23 Jan 2017 13:24:45 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
< 					----->空行
<!DOCTYPE html>     ----->响应数据
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
  1. 响应数据很明显就是百度的首页HTML页面
  2. 状态行中包括响应的状态码,这一个在请求时候是没有的

四.除了GET/POST的其他请求类型

HTTP 协议中共定义了八种方法或者叫“动作”来表明对 Request-URI 指定的资源的不同操作方式,具体介绍如下:

  • OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送’*'的请求来测试服务器的功能性。
  • HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
  • GET:向特定的资源发出请求。
  • POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
  • PUT:向指定资源位置上传其最新内容。
  • DELETE:请求服务器删除 Request-URI 所标识的资源。
  • TRACE:回显服务器收到的请求,主要用于测试或诊断。
  • CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
    虽然 HTTP 的请求方式有 8 种,但是我们在实际应用中常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。

五.常见响应头状态码

状态码:是由三位数字组成,第一位:响应的类型,常使用的有5大类型:

1xx: 服务器接收客户端请求,客户端可以继续发送请求
  1. 100 继续 初始的请求已经接受,请客户端继续发送剩余部分
  2. 101 切换协议 客户要求服务器根据请求转换HTTP协议版本,服务器已确定切换

2xx: 服务器接收请求,并进行处理

200:ok 客户端的请求成功收到、解析、接收
201:created 请求已经完成,并且一个新的返回资源被创建,被创建的资源可能是一个URI资源,通常URI资源在Location头指定。
202:Accepted 请求被接收用来处理,但是处理并没有完成,请求可能或者根本没有遵照执行
204:No Content 服务器已经接受请求并且没必要返回实体数据,可能需要返回更新信息


3xx:Redirection 重定向:要求用户进一步细化请求

300 Multiple Choices 请求资源符合任何一个呈现方式。
301 Moved Permanently 请求的资源已经被赋予一个新的URI。
302 Found 通过不同的URI请求资源的临时文件。
303 See Other
307 Temporary Redirect

注意⚠️:

  1. 303 状态码表示服务器要将浏览器重定向到另一个资源,这个资源的 URI 会被写在响应 Header 的 Location 字段。从语义上讲,重定向到的资源并不是你所请求的资源,而是对你所请求资源的一些描述。303 常用于将 POST 请求重定向到 GET 请求,比如你上传了一份个人信息,服务器发回一个 303 响应,将你导向一个“上传成功”页面。
  2. 302 状态码表示目标资源临时移动到了另一个 URI 上。由于重定向是临时发生的,所以客户端在之后的请求中还应该使用原本的 URI。服务器会在响应 Header 的 Location 字段中放上这个不同的 URI。浏览器可以使用 Location 中的 URI 进行自动重定向。
  3. 在这里总结一下,从实际效果看:302 允许各种各样的重定向,一般情况下都会实现为到 GET 的重定向,但是不能确保 POST 会重定向为 POST;而 303 只允许任意请求到 GET 的重定向;307 和 302 一样,除了不允许 POST 到 GET 的重定向。
  4. 302包括303,303只允许get重定向,307不允许get重定向

4xx Client Error请求客户端错误

400 Bad Request:表示客户端请求有语法错误,不能被服务器所理解;
401 Unauthonzed:表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一 起使用;
403 Forbidden:表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因;
404 Not Found:请求的资源不存在,例如,输入了错误的URL;


5xx 服务器错误

500 Internal Server Error:表示服务器发生不可预期的错误,导致无法完成客户端的请求;
503 Service Unavailable:表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常;
502 Bad Gateway
501 Not Implemented 服务器没有相应的执行动作来完成当前请求。
503 Service Unavailable 因为临时文件超载导致服务器不能处理当前请求。

;