看懂《书源规则:从入门到入土》(1)HTTP基础



前言:

我不喜欢伸手党。觉得不懂可以问很正常没问题,但应该是自身尽力后依然无法解决后再问。而且应该给予解答者尊重,而不是一味的骚扰甚至恶语相向。



相信不少曾经有想写书源的想法酷友应该有和我一样的经历,阅读的书源规则文档每个字都能看懂 ,但组合在一起就不知道是什么东西了 受虐滑稽 ,于是放弃了 受虐滑稽

下面一系列图文我会尽力让大家能看懂书源文档,编写一些简单的书源。希望能减轻大佬们应付小白的压力。

该系列图文我会尽量面向小白写得浅显易懂,让没什么基础的酷友能轻松上手。

(尽管我真的很想直接甩MDN(Mozilla Developer Network)文档上来你们自己去悟 t耐克嘴

书源规则文档链接: 查看链接



免责声明:

该系列(看懂《书源规则:从入门到入土》)图文仅供学习使用,自行编写的规则所造成的后果请自行承担,本人概不负责。



消歧义:

本章所说的http协议包括常规的http协议及https协议中的http部分



本章可能需要涉及的工具:

1:浏览器(推荐最新的chrome或firefox。当然你非要用internet explorer 6是你的自由)

2:抓包工具(比如fiddler。如果涉及https包需要进行mitm(Man-In-The-Middle attack,中间人攻击),请自行部署mitm证书)

3:对于部分人可能还要翻译工具 t耐克嘴

-------------

首先,什么是http?

http(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

说简单点,就是客户端(通常是浏览器)与网站服务器进行交互的协议,详细介绍去看Wikipedia,我这不讲历史。

---------------

http请求(request):

http请求是我们向服务器发送到指令,希望服务器提供怎样的服务。一个http请求报文通常分为方法(method)、请求头(headers)、请求体(body)三个部分。

http请求报文示例,图源MDN

方法:

在HTTP/1.1协议中一共定义了8种方法来以不同方式操作指定的资源,分别是:GET , HEAD , POST , PUT , DELETE , TRACE , OPTIONS , CONNECT。

在本文中,只需要知道GET和POST就可以了 ,其他有兴趣的可以去看Wikipedia或MDN。

GET:请求一个指定资源的表示形式。

POST:用于将实体提交到指定的资源。

在上述示例中,我们看到了第一行"GET / HTTP/1.1",这就是这一个http请求所用的“方法”。

🦊:您好我是浏览器,服务器大哥,我想通过 http 1.1(HTTP/1.1) 协议 获取(GET) 站点 根目录(/) 的资源。

请求头:

好了,现在服务器知道了客户端希望获得怎样的服务了。但method里是不是写得太简陋了,你不打算提点要求吗? 坏笑

这就是请求头的作用,向服务器发送一些附加信息,希望服务器提供怎样的“个性化”服务。

示例中,我们用了两个字段:

Host:developer.mozilla.org

Accept-Language:fr

这是什么意思呢?别急,咋们慢慢来。

🦊:我希望看到的是 developer.mozilla.org 这台 主机(host) 上的网站,我能 接受的语言(accept language) 是 法语(fr是french的缩写)。

请求体:

示例里没有,后面有我会再讲。这部分是客户端提交给服务器处理的数据。

综上,示例中的请求报文的意思就是:

🦊:您好我是浏览器,服务器大哥,我想通过http 1.1协议获取站点根目录的资源。我希望看到的是developer.mozilla.org这台主机上的网站,我能接受的语言是法语。我暂时没有其他数据要您处理了(请求体:无),麻烦大哥 哈哈哈

------------

http响应(response):

(非重点,一笔带过)

http响应是服务器处理客户端的请求后,向客户端发送的处理结果。一个http响应报文通常包含状态(status)、响应头(headers)、响应体(body)三个部分。

http响应报文示例,图源MDN

状态:

表示服务器对这个请求处理的结果。示例中的意思是:http 1.1请求已处理,状态码200(处理成功)。

响应头:

服务器发送的附加信息,表示服务器的一些工作状态和下面会提到的响应体的一些情况。

示例中的响应头

Date:Sat , 09 Oct 2010 14:28:02 GMT

Server:Apache

Last-Modified:Tue, 01 Dec 2009 20:18:22 GMT

ETag:"51142bc1-7449-479b075b2891b"

Accept-Ranges:bytes

Content-Length:29769

Content-Type:text/html

的意思是:

当前 时间(date) 格林尼治标准时间2010年10月9日14时28分2秒星期六 服务端程序(server) Apache 你请求的资源 最后变动时间(Last-Modified) 格林尼治标准时间2009年12月1日20时18分22秒星期二 标记(etag) 51142bc1-7449-479b075b2891b 可接受的 范围请求单位(accept-ranges) 是 字节(bytes) 内容(响应体)长度(Content-Length) 29769字节 内容类型(Content-Type) html文本(text/html)

响应体:

服务器根据请求返回的数据。

综上:示例中的响应报文的意思是:

🥔:浏览器弟弟,你的http1.1请求已经处理成功。现在服务器时间是格林尼治标准时间2010年10月9日14时28分2秒星期六,服务端程序是Apache,你请求的资源最后变动时间是格林尼治标准时间2009年12月1日20时18分22秒星期二,资源标记51142bc1-7449-479b075b2891b,服务器可接受的范围请求单位是字节,一会发生给你的内容长度29769字节,类型是html文本,内容(响应体)是<!DOCTYPE html...

------------

看到这里,也许有同志会来问了。上面水了那么多字,怎么还没入题 受虐滑稽

怎么会没入题呢?写源的时候不用写搜索吗?搜索不就是我们告诉服务器,我们希望得到怎样的书吗。

那怎么告诉服务器?用http请求啊 吐舌 。现在我们以一个网站为例,看看这个请求是什么玩意。

按照流程,我们是不是应该先输入名字,然后点击搜索 受虐滑稽 。那么在个过程里面,究竟发生了什么?

现在,我们打开浏览器控制台看看

现在看到了,搜索功能是写在一个form(表单)元素里的,当点击提交时这个表单收集到的数据会通过http post方法提交到/search.html

现在我们抓取一下点击搜索时浏览器和服务器之间的http报文。(因为在我是在手机码字,用fiddler不那么方便,此处用小黄鸟做演示 。原理都是一样的)

请求

一大堆字段看不懂对不?没关系,大部分都不用理解,咱们只挑需要的讲。

方法:POST /search.html h2

通过http2(h2)协议向网站的/search.html这个资源发送一个post请求。

请求头:

accept-language:zh,zh-SG;q=0.9,en-US;q=0.8,en;q=0.7

可接受的语言:中文,中文-新加坡,英语-美国,英语

accept-encoding:gzip,deflate

可接受的压缩算法:gzip , deflate

请求体:s=%E5%AE......(下面那堆字,懒得打 受虐滑稽 )

向服务器发送“s=完美世界&submit=”这个字符串。

至于为什么是一堆%XX这样的代码是因为这部分内容不是ASCII编码,所以浏览器需要进行转换,于是就变成了这样的uri编码了。

一个字都看不懂的自觉向上滚 t耐克嘴 ,去复习一下。

响应

同上,咱们只挑重要的讲

状态:h2 200

这个http2请求已处理,状态码200(处理成功)

响应头:

content-type:text/html;charset=UTF-8

内容类型:html文本,字符集UTF-8

content-encoding:gzip

内容压缩算法 :gzip

响应体:

下面那堆乱码 受虐滑稽

因为已经被压缩了,所以这里看起来是乱码。浏览器收到响应后会把响应体用gzip算法解压就能得到一个正常的html文档了 受虐滑稽

-------------

编写搜索:

好了,我们已经知道了搜索时请求的资源是/search.html,

请求方式是post,

请求体的写法是s=书名&submit=

请求头一般是可选的,但有时候需要指定某些字段(比如指定某个user-agent(用户代理,俗称ua),使服务器发送电脑端网页)

那么我们应该怎么写一个请求给网站,来获取搜索结果呢?

这个网站可能稍复杂点,不能一条url搞定,所以我们用json(JavaScript Object Notation)方式编写。

json通过 键:值 对的方式指定属性和属性值,键值对之间用英文逗号分隔(换行并非必须,只是为了“美观”),括号里最后一个键值对末尾不要加逗号,就像这样:

{

a:1,

b:'text',

c:{

d:true

},

e:[1,2,3]

}

根据文档,搜索>搜索地址 部分我们应该这样写

/search.html,{

'headers':{},

'body':'s={{key}}&submit=',

'method':'POST'

}

注:

1 :{{key}}是一个阅读的内部变量,表示搜索的书名,发送请求时程序会自动替换。

2:如果不指定请求头的话最好把headers部分删掉。

-------------

结语&预告:

本章扯了那么多,终于解决了发送搜索的问题。那么拿到服务器响应后我们该如何过滤和呈现呢?

敬请期待下一章:html基础

-------------

引用:

超文本传输协议 - 维基百科:

查看链接

HTTP - MDN:

查看链接