HTTP协议

目录

一、HTTP协议格式

1、抓包工具的原理

2、抓包工具的使用

3、HTTP请求的格式

4、HTTP响应的格式

二、HTTP请求详解

1、URL

1.1 URL基本格式

1.2 URL encode

2、方法

2.1 GET方法

2.2 POST方法

2.3 比较GET和POST方法

3、请求头header

3.1 Host

3.2 Content-length和Content-Type

3.3 User-Agent

3.4 Referer

3.5 Cookie

4、正文body

三、HTTP响应详解

1、状态码

1.1 200 OK

1.2 404 Not Found

1.3 403 Forbidden 

1.4 405 Method Not Allowed

1.5 500 Internal Server Error

1.6 504 Getaway Timeout

1.7 302 Move temporarily

1.8 301 Moved Permanently

1.9 状态码小结

2、响应报头header

3、响应正文body

四、如何构造HTTP请求

1、form表单

2、ajax

3、socket


一、HTTP协议格式

        HTTP协议是一种应用非常广泛的应用层协议,当我们在浏览器中输入一个URL(“网址”)时,浏览器就会给客户端发送一个HTTP请求,服务器收到请求之后,就会返回一个HTTP响应。

        为了能够看到HTTP请求和响应的详细内容,我们需要使用抓包工具,本文以Fiddler为例。

1、抓包工具的原理

        Fiddler抓包工具相当于一个“代理程序”:客户端向服务器发送的HTTP请求时,客户端会先把请求交给Fiddler,Fiddler再把请求转交给服务器;当服务器返回HTTP响应时,会先把响应交给Fiddler,Fiddler再把响应交给客户端。

        因此,Fiddler就会很清楚客户端和服务器之间交互的数据细节。

简单理解就是,Fiddler相当于一个给客户端跑腿儿的小弟~

代理分为两种:

正向代理:给客户端提供服务的代理程序,此时正向代理就相当于把真实的客户端隐藏起来了,服务器不知道真实的客户端是谁。

反向代理:给服务器提供服务的代理程序,此时反向代理就相当于把真实的服务器隐藏起来了,客户端不知道真实的服务器是谁。

2、抓包工具的使用

启动Fiddler应用程序后,它就会自动抓取当前主机上每个进程产生的HTTP请求/响应:

>> 左侧窗口显示了所有的HTTP请求/响应,可以选中其中某个请求进行查看;

>> 右侧上方显示了HTTP请求的报文内容,切换到Raw标签页可以看到详细的数据格式; 

>> 右侧下方显示了HTTP响应的报文内容,切换到Raw标签页可以看到详细的数据格式; 

>> 请求和响应的详细数据,可以点击右下角的 View in notepad 按钮,通过记事本打开。

注意:可以使用ctrl+a全选左侧的抓包结果,再按delete键可以清楚所有被选中的结果。 

3、HTTP请求的格式

下图是一个HTTP请求的抓包结果:

一个HTPP请求由四个部分构成:

(1) 首行:即HTTP请求的第一行内容,它包括了:

① HTTP的方法:描述了这次请求要干什么;

② URL:描述了网络上的一个唯一资源;

③ 版本号:描述了当前这个HTTP请求是哪个版本的。

(2) 请求头header:是一个按行组织的键值对,即每一行是一个键值对,键和值之间用: 分割;

(3) 空行:空行表示header的结束标记;

(4) 正文body:正文用来承载一些具体的数据,正文允许为空字符串。

4、HTTP响应的格式

下图是一个HTTP响应的抓包结果:

 一个HTPP响应由四个部分构成:

(1) 首行:HTTP响应的第一行内容,它包括:

① 版本号:描述了当前这个HTTP请求是哪个版本的;

② 状态码:描述当前这次请求是否成功;

③ 状态码描述:对状态码的解释说明。

(2) 响应头header:同样也是按行组织的键值对结构,每一行是一个键值对,键和值之间用: 分割;

(3) 空行:空行表示header的结束标记;

(4) 正文body:正文用来承载一些具体的数据,可能是css,html,图片等多种格式;正文允许为空字符串。

二、HTTP请求详解

1、URL

        我们平时所说的“网址”其实就是URL(Uniform Resource Locator),唯一资源定位符,用来定位互联网中的一个唯一的资源。

1.1 URL基本格式

一个具体的URL:

信息解释能否省略
http://

        协议方案名,常见的有:http、https,也有其他类型的,比如访问mysql时用的jdbc:mysql。

        可以省略。省略后默认为http://
user:pass

        登录信息,用于登录网站进行身份认证;现在的网站一般不再通过URL进行身份认证。

        一般都会省略。
www.example.jp

        表示服务器的IP地址,此处用域名表示,域名会通过DNS系统解析成一个具体的IP地址。

        在HTML中可以省略,省略后表示服务器的IP/域名和当前HTML所属的IP/域名一致。
80        表示服务器的端口号        可以省略,如果是http协议,省略后自动设为80;如果是https协议,省略后自动设为443。
dir/index.html

        通过上面的服务器地址和端口号,就能够确定要访问的服务器是互联网上的哪个主机的哪个进程,而进程中可能有很多资源,通过带层次的文件路径就可以访问到进程中的一个具体的资源。

        服务器提供的资源可能是硬盘上的一个真实存在的文件(访问静态资源),也可能是服务器根据http请求在内存中构造出的一个html片段(访问动态资源)。

        可以省略,省略后相当于/,有些服务器会在发现/路径的时候自动访问/index.html。
uid=1        查询字符串(query string),本质是一个键值对结构,键值对之间使用&分隔,键和值之间使用=分隔,相当于客户端给服务器传递的一些必要的参数,键值对的内容和数量由程序猿自己约定。        可以省略。
ch1        片段标识符一般用于小说、文档等类型的网站进行页面内跳转,通过不同的片段标识符跳转到不同的章节。        可以省略。

1.2 URL encode

        像 / ? @ = 等这样的字符,在URL中具有特定的含义,因此这些字符不能随意出现在URL中,如果要出现,就必须对这些字符进行urlencode。

        一个中文字符由UTF-8或者GBK的编码方式构成,虽然在URL中没有特殊含义,但是也需要进行转义,否则浏览器可能会把UTF-8/GBK编码中的某个字节当作URL中的特殊符号。

当我们在浏览器中搜索C++时:

可以发现,+被转义成了%2B~

转义规则:

        将待转义的字符转为16进制表示,然后在每个字节前面再加上%,转义后的格式为%XY。

urldecode就是urlencode的逆过程,把转义后的编码再还原为原来的字符。

urlencode工具:https://tool.chinaz.com/Tools/urlencode.aspx

2、方法

方法说明支持的HTTP协议版本
GET获取资源1.0、1.1
POST传输实体主体1.0、1.1
PUT传输文件1.0、1.1
HEAD类似于GET方法,但只返回响应头header1.0、1.1
DELETE删除服务器指定资源1.0、1.1
OPTIONS询问服务器支持的请求方法1.1
TRACE回显服务器端收到的请求,测试的时候用到1.1
CONNECT要求用隧道协议连接代理1.1
LINK建立和资源之间的联系1.0
UNLINE断开连接关系1.0

        HTTP请求中虽然有很多方法,但是最常用的还是GET方法,然后是POST方法,其他的方法都不太常用。

2.1 GET方法

GET方法是最常用的HTTP方法,常用于用户获取服务器上的某个资源

构造GET请求的方式:

(1) 在浏览器中直接输入一个URL,浏览器就会触发GET请求,因为浏览器要加载出一个页面,往往要经过多重HTTP请求的交互。

例如,当我们访问搜狗主页时,会产生许多和sogou域名相关的请求:

(2) html里的link、a、img、script等标签也会触发GET请求,因为它们都会引用一个外部资源。

(3) html里的form表单也可以构造出GET请求;

(4) 使用JavaScript里的ajax也能构造GET请求。

GET请求的特点:

(1) 首行第一部分为GET;

(2) URL的query string可以为空,也可以不为空,如果需要给服务器传递一些参数,就是通过query string传递的;

(3) header部分有若干个键值对结构;

(4) body部分通常为空。

 关于GET请求的URL长度问题

网上有些资料描述,GET请求的长度最多为1kb、2kb……这样的说法是错误的。

HTTP协议由RFC 2616标准定义的,标准中并没有对URL的长度做出任何限制。

标准虽然没有做出限制,但是浏览器和服务器在实现的时候,可能会对URL的长度做出限制,具体的长度取决于浏览器的实现和HTTP服务器的实现。

2.2 POST方法

POST方法是一种较常见的HTTP方法,常用于用户给服务器提供数据(例如登录页面)。

 构造POST请求的方式:

(1) html里的form表单构造POST请求;

(2) JavaScript里的ajax构造POST请求。

POST请求的特点:

(1) 首行的第一部分为POST;

(2) URL中通常是没有query string的(也可以有);

(3) header部分有若干个键值对结构;

(4) body部分一般不为空,body的数据格式有很多种,json、html、css……

POST在给服务器传递信息的时候,通常就会把信息放到body中。

2.3 比较GET和POST方法

        GET和POST没有本质区别,使用GET实现的场景,基本都可以使用POST代替;使用POST实现的场景,也可以使用GET代替。

 GET和POST细节上的区别

区别GETPOST
语义从服务器获取数据向服务器提交数据
使用习惯

给服务器传递的数据,GET请求通常是

放在URL的query sring中

POST请求通常是把给服务器传递的

数据放在body中

幂等GET请求建议实现成幂等的POST请求则不要求实现成幂等的
缓存在幂等的基础上,GET的请求结果可以被缓存POST则一般不会缓存

幂等:如果多次请求得到的结果一样,就视为请求是幂等的。

 关于安全性问题

        网上有些资料说,POST比GET更安全,依据是:在GET请求中,用户名和密码会以query string的形式放在URL中,就会直接显示在浏览器的地址栏;而POST则是把参数放在body中,不会直接显示在浏览器地址栏,所以更安全。

        这种说法也是错误的,即使POST把参数放在body中,也是可以通过抓包工具看到的!是否安全取决于前端在传输密码等敏感信息时是否进行加密,和GET、POST无关。

3、请求头header

        请求头header中有很多键值对,这些键值对大部分都是由RFC 2616标准定义的(也可以由程序猿自定制),有特定的含义,本文介绍几个常见的:

3.1 Host

Host表示服务器的IP和端口号。

 

其中,端口号可以省略,省略后为默认值(http的默认值80,https的默认值443) 。

虽然URL中已经有了服务器的IP和端口号,但是如果浏览器经过代理程序访问服务器时,URL中的IP和端口号可能和Host中的不同(但Fiddler中无法体现):URL中可能存放的是代理程序的服务器IP和端口,而Host中存放的是目标服务器IP和端口。

浏览器通过URL中的IP端口找到代理程序服务器,代理程序通过Host中的IP端口找到目标服务器。 

3.2 Content-length和Content-Type

Content-length: 表示body中的数据长度。

Content-Type:表示body中的数据格式。

这两个字段是伴生的,要么两个都有,要么两个都没有:

如果请求中没有body,那么header中就没有这两个字段,比如GET请求;

如果请求中有body,那么header中就有这两个字段,比如POST请求;

Content-length的作用:

HTTP协议在传输层是基于TCP协议(3.0版本之前是,3.0版本是基于UDP协议),而TCP协议是面向字节流的,存在粘包问题,解决粘包问题的两种方式:

(1) 约定一个分割符,在HTTP协议中的体现是空行。

(2) 约定报文的长度,即通过Content-length表示body长度。

Content-Type的常见选项:

(1) application/x-www-form-urlencoded,这是form表单提交的数据格式,此时body的格式形如:

title=test&content=hello

此种格式和URL中的query string的格式相同。

(2)  multipart/form-data,这种格式主要是在上传文件的时候出现。

(3) application/json,数据为json格式,此时body的格式形如:

{"username":"173xxxxxxx","password":"u06Deq8nkTa8FLP6B9809w==","uuid":"153431c6e1464f338f00b7eaa24ea122","status":0}

json格式是最常用的~

关于Content-Type的详细情况:MIME types (IANA media types) - HTTP | MDN (mozilla.org)

3.3 User-Agent

User-Agent用来表示浏览器和操作系统的属性。

User-Agent的作用:

UA的主要作用就是描述了用户的操作系统信息和浏览器信息,即用户在使用什么设备上网

不同的操作系统/浏览器/上网设备,对于某些页面的支持程度不同,有些浏览器只支持文字,有些浏览器能够支持文字、图片……通过UA来收集到浏览器和操作系统的信息,进一步就能够知道这个浏览器/操作系统支持什么样的页面了。

3.4 Referer

Referer表示这个页面是从哪个页面跳转过来的。

在搜狗主页搜索一个内容时,此时的Referer就是搜狗主页:

如果直接在浏览器中输入一个URL,或者通过收藏夹访问一个页面时是没有Referer的。

由于请求中的referer在传输过程中,可能会被修改(运营商劫持),为了解决这个问题,就需要加密,使用HTTPS。

3.5 Cookie

Cookie是浏览器在本地存储数据的一种机制。

浏览器为了安全起见,一般都会禁止网页的JS访问电脑的硬盘(文件系统),为了在本地存储一些数据,所以浏览器给网页提供了一些特殊的API,Cookie就是最经典的一种。

Cookie是按照域名维度来维护的,不同的域名下存放不同的Cookie,一个网站发起的http请求可能是来自多个域名:

其中,每个Cookie是一个键值对:

Cookie中的键值对和URL中的query string一样,都是由程序猿自定制的。

Cookie中的键值对一般都是些简单的字符串,只能存一些简单的信息,比如:上次访问页面的时间、当前访问网页的次数、当前访问页面的身份信息……如果想让Cookie存个图片、视频等内容,Cookie是做不到的。

Cookie从哪里来?

Cookie来源于服务器,在服务器返回的响应报文中,会包含若干个Set-Cookie这样的字段,浏览器收到这样的响应报文后,就会把这样的数据保存在浏览器本地。

打开CSDN主页时返回的HTTP响应报文:

★ Cookie到哪里去?

浏览器在本地保存了一个网站的Cookie后,下次访问再同一个网站时,就会把保存的Cookie通过http请求的header发给服务器。

因为一个服务器要服务的客户端有很多,Cookie就相当于一个身份标识,来区分不同的客户端。

★ Cookie的典型应用场景

Cookie最常用的场景就是在客户端维持登录状态。

例如:我们登录CSDN后,在CSDN中进行写文章、查看文章、查看个人信息等操作时,都会维持登录状态,而不是说点开一个新的页面后,还需要重新登录。

4、正文body

有些请求有body,比如POST,有些请求没有body,比如GET。

body中内容的格式就是header的Content-Type中指定的格式。

三、HTTP响应详解

1、状态码

状态码表示访问一个页面的结果,访问成功还是访问失败,或者遇到其他情况……

以下是一些常见的状态:

1.1 200 OK

表示访问成功,这是一个很常见的状态码~

抓包工具抓到的很多包的状态码都是200~

1.2 404 Not Found

表示没有找到要访问的资源。

比如我们在浏览器中输入一个错误的URL:www.sogou.com/test.html,此时就会出现404状态码:

URL表示唯一资源定位符,当我们通过www.sogou.com定位到搜狗的服务器IP和端口号后,再去通过带层次的文件路径访问test.html时,就会发现并没有这样的文件资源,于是就会返回404 Not Found。

1.3 403 Forbidden 

表示服务器拒绝访问。有的页面通常需要用户具有一定的权限才能访问,在没有权限的情况去访问时,访问就会被拒绝。

比如在未登录的情况下,访问码云的私有仓库,就会出现这样的状态码:

1.4 405 Method Not Allowed

HTTP中所支持的方法有GET、POST等,但是我们要访问的服务器不一定支持所有的方法,发送服务器不支持的请求时就会出现这样的状态码。

1.5 500 Internal Server Error

服务器内部出现错误,一般是服务器的代码在执行过程中遇到了一些特殊情况,比如服务器异常崩溃时,就会产生这个状态码。

1.6 504 Getaway Timeout

当服务器负载比较大的时候,服务器处理单条请求的时候所消耗的时间会很长,就可能会出现超时的情况,从而产生这个状态码。

比如“双十一”秒杀这样的场景下就可能会出现。

1.7 302 Move temporarily

表示临时重定向。访问一个页面时自动跳转到另一个页面就会出现这样的状态码。

一般登录页面会经常见到302,用于实现登录成功后自动跳转到主页。

响应报文的header部分会包含一个Location字段,表示要跳转到哪个页面。

1.8 301 Moved Permanently

永久重定向。当浏览器收到这种响应时,后续的请求都会自动跳转到新的地址。

301也是通过响应报文的header部分中的Location字段来表示要重定向的地址。

1.9 状态码小结

状态码类别描述
1XXInformational(信息性状态码)正在处理接收的请求
2XXSuccess(成功状态码)请求正常处理完毕
3XXRedirection(重定向状态码)需要进行附加操作以完成请求
4XXClient Error(客户端错误状态码)服务器无法处理请求
5XXServer Error(服务器错误状态码)服务器处理请求出错

2、响应报头header

响应报头的格式和请求报头的格式基本一致。

但响应报头中的Content-Type的取值和请求报头中的有些差异。

响应报头中Content-Type常见的取值:

(1) text/html,表示body数据格式是HTML;

(2) text/css,表示body数据格式是CSS;

(3) application/javascript,表示body数据格式JavaScript;

(4) application/json,表示body数据格式是JSON。

关于Content-Type的详细情况:MIME types (IANA media types) - HTTP | MDN (mozilla.org)

3、响应正文body

正文的具体格式取决于响应头中的Content-Type。

四、如何构造HTTP请求

除了通过浏览器构造HTTP请求外,还可以通过以下几种方式构造:

1、form表单

form表单是HTML中的一个常用标签,用于构造GET或者POST请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>form</title>
</head>
<body>
    <form action="https://www.sogou.com" method="get">
        <input type="text" name="test1">
        <input type="text" name="test2">
        <input type="submit" value="提交">
    </form>
</body>
</html>

form标签中的重要属性:

(1) action:表示构造的HTTP 请求的URL是什么;

(2) method:表示构造的HTTP的请求是什么?GET还是POST。

input标签中的重要属性:

(1) name属性表示构造出的HTTP请求的query string中的key值,用户在输入框中输入的内容就是对应的value值;

(2) 如果HTTP请求的方法是GET,上述键值对就会放在query string中;

如果HTTP请求的方法是POST,上述键值对就会放在body中,此时Content-Type就是application/x-www-form-urlencoded格式。

此时的页面效果:

点击提交后就会构造出HTTP请求并发送:

2、ajax

form表单只能构造GET、POST方法的请求,而ajax可以构造所有的HTTP方法,并且ajax默认发起的请求是不会引起跳转(可以手动控制),而form构造的http请求一定会触发页面跳转的。

使用ajax不触发跳转,就可以达到“局部刷新”的效果:如果个页面a和另一个页面b的很多内容都一样,当从a跳转到b时,只需要刷新它们不一样的地方就行了~

ajax全称:Asynchronous JavaScript and XML。

其中Asynchronous表示异步,表示发起请求的主体,不负责接收结果,而是由别人推送过来。

相对应的同步表示:谁发起的请求,谁负责接收结果。网络通信/IO操作中的同步就是这个意思。

而多线程中的synchronized,这里的同步指的是多个线程之间互斥。

由于现在XML用的越来越少,现在使用ajax一般都是用来传输其他数据:比如JSON。

通过ajax构造一个HTTP请求:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        $.ajax({
            //type表示HTTP请求的方法
            type:'get',
            url:'https://www.sogou.com',
            //data:'请求中的body',
            success:function(body){
                //服务器返回正确的响应时(比如200 OK)
                //浏览器就会调用success对应的这个函数来处理响应
                //参数body就是响应的正文
                console.log('ok');
            },
            error:function(){
                //服务器返回错误的响应时(比如404 Not Found)
                //就会由浏览器调用error对应的这个函数
                console.log('error');
            }
        });
    </script>
</body>
</html>

此处我们使用第三方库jquery封装好的ajax API,所以需要先引入一个jquery的网络地址。

$:是jquery中特殊的一个全局对象,通过$就可以调用jquery里的一些方法。

如果此时我们直接运行代码,就会发现代码报错了:

这是一个典型的报错信息——跨域:一个页面在域名a之下,尝试通过ajax访问域名b里的资源。

浏览器默认是禁止跨域操作的,除非b网站返回的响应明确告诉浏览器允许跨域访问,但是大部分的网站、服务器都是不允许跨域的。

要解决这个问题,需要我们自己写个服务器,通过ajax访问自己服务器上的资源。

3、socket

如果一个编程语言,可以进行socket编程,那么就一定可以构造HTTP请求(往一个TCP Socket里写一个符合http协议格式的字符串)。

还可以通过一些第三方工具来构造HTTP请求,比如postman。

发送请求后收到的响应:

postman构造的请求,会自动生成相应的多种语言代码:

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃点橘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值