HTTP头
HTTP头
HTTP报文分为请求报文和响应报文。请求报文和响应报文的的第一行叫做状态行。状态行后面就跟着多个HTTP首部字段。
首先,咱们得清楚HTTP头部有什么作用,HTTP首部用来向请求报文或者响应报文中添加一些附加信息。通过HTTP首部信息,客户端或者服务器端就能了解到这次报文到底具有哪些属性,报文发送端有哪些喜好等等。
HTTP首部的分类:
1.通用首部:请求报文和响应报文都支持,换句话说,就是既可以出现在请求报文中,也可以出现在响应报文中。
2.请求首部:出现在请求报文第一行(请求行)的后面,为请求报文添加一些附加信息
3.响应首部:出现在响应报文第一行的后面,提供了一些关于响应报文的一些信息
4.实体首部:我们都知道,请求报文和响应报文都包含实体报文,实体首部就是用来描述实体报文的一些属性。
5.扩展头部:HTTP规范中没有定义的首部。
1 | Accept 指定客户端能够接收的内容类型 |
Header常见字段的举例
-
Accept:/
最常见,指接受所有类型 还有text/plain,text/html,分别指接受纯文本和html格式
-
Accept-Encoding: gzip
gzip是一种压缩方式,使用最为广泛,使用gzip可以省下很多网页流量,在网速一定的情况下,可以提高访问效率, 而deflate同样也为一种压缩方法(使用LZ77 算法和哈夫曼编码),使数据无损
-
Accept-Language: zh-CN;en-US
语言,zh-CN是简体中文,而zh是中文,en-US是英文
而q是权重系数,范围 0 =< q <= 1,q 值越大,请求越倾向于获得其“;”之前的类型表示的内容,若没有指定 q 值,则默认为1,若被赋值为0,则用于提醒服务器哪些是浏览器不接受的内容类型。 -
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
浏览器支持的字符编码分别是 GB2312、utf-8 和任意字符,优先顺序是 GB2312、utf-8、。
其中表示任意字符编码,虽然 q 都是等于 0.7,但明确指定的 GB2312,utf-8 比 * 具有更高的优先级。 -
Connection: keep-alive
HTTP请求是基于TCP连接的,TCP的请求会包含(三次握手,中间请求,四次挥手)
在HTTP/1.0时代,一个HTTP请求就要三次握手和四次挥手,当一个网页中包含大量的图片或者其它外部资源时,加载一个Document要很多个HTTP请求,也就意味着要多次三次握手和四次挥手,这样就造成了网络资源的浪费
到了HTTP/1.1的时候,通过请求头的connection字段用来申明,作用就是减少TCP握手次数,开始的三次握手后就可以进行多次HTTP正文请求,可以长时间的保持,也就是加载一个Document的时候,即使有大量的图片等,也只用进行一次握手,这样就大大的减少了传输量了。keep-alive就表示之前已经进行过握手,可以直接进行HTTP正文传输,close表示结束,我接下来没有东西了,可以进行四次挥手结束这个TCP连接了 -
Content-Type
Http Header里的Content-Type一般有:
1.application/x-www-form-urlencoded: 数据被编码为名称/值对。这是标准的编码格式。
2.multipart/form-data: 传输文件。
3.text/plain: 数据以纯文本形式进行编码
4.application/json: json格式
对于一个form表单,其enctrype属性即为编码方式
常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。
x-www-form-urlencoded
jquery的ajax方法默认使用application/x-www-form-urlencoded
当请求的Content-Type为application/x-www-form-urlencoded浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…)
同理为application/json时会转换为json数据格式
form-data
http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。
既可以上传键值对,也可以上传文件。
当上传的字段是文件时,会有Content-Type来表名文件类型而content-disposition,用来说明字段的一些信息;
由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
boundary通常由浏览器随机生成
示例
使用HTTP Client 对本地服务器模拟post操作
后端为Django
使用application/x-www-form-urlencoded
1 | POST http://127.0.0.1:8000/test.api/ |
1 | form_name = request.POST.get("name", None) |
list被解析为列表而name被解析为k-v对,我们看到,虽然x-www-form-urlencoded是以k-v对的形式来传递参数的,这并不意味着它不能传递数组(列表),我们只需指定传递的key相同值不同的多组数据即可
使用multipart/form-data
1 | POST http://127.0.0.1:8000/test.api/ |
1 | form_file = request.FILES.get("pic", None) |
我们指定boundary的值为
yurnnlukjwfbrdiqvnqnegfitaaddkom
,这个完全根据自定义,但一般浏览器会以若干—开头以防止和数据名称或内容等冲突导致出错
我们的图片是以2进制的形式上传的,所以写入操作也要对应为2进制文件操作
Response常见字段举例
- Cache-Control(默认为private)
常用属性值。
1.no-cache:这个属性呢,不要被他的样貌给迷惑了,它并不是不缓存响应报文,只不过在服务器返回响应时,缓存都要向服务器评估缓存的新鲜度。也就是说,如果服务器返回的响应相比缓存有所变动,则使用服务器的响应。
2.no-store:该指令规定不缓存任何内容(注意和no-cache的区别)
3.max-age:用法max-age=60(秒),用来表示缓存资源的保鲜时间。当缓存的内容缓存时间大于该值时,请求将重新转发至服务器。
4.s-maxage:用法和max-age相同,并且行为和max-age也相同,不同的是s-maxage适用于公共缓存。
通过指定“Expires”(过期时间)值也会影响到缓存。与max-age不同的是,expires的值是绝对时间,而max-age是相对时间(我的理解)
CORS
CORS(cross-origin sharing standard)
什么情况下需要CORS?
- XMLHttpRequest或Fetch
- Web字体
等等
使用XMLHttpRequest (XHR)对象可以与服务器交互。您可以从URL获取数据,而无需让整个的页面刷新。这使得Web页面可以只更新页面的局部,而不影响用户的操作。XMLHttpRequest在 Ajax 编程中被大量使用。
什么时候触发
CORS可以让你实现跨站点请求并同时阻止恶意js的请求,它会在你发送下面几种HTTP请求时触发:
- 不同的域名 (比如在网站 example.com 请求 api.com)
- 不同的子域名 (比如在网站 example.com 请求 api.example.com)
- 不同的端口 (比如在网站 example.com 请求 example.com:3001)
- 不同协议 (比如在网站 https://example.com 请求 http://example.com)
跨域请求
只有服务器实现了cors接口才可以进行跨域请求
cors对于浏览器发过来的ajax请求有简单请求和非简单请求
- 简单请求:
HEAD, GET, POST请求
浏览器会在header中加上字段 key:origin value:协议+域名+端口(如http://localhost:8080)
服务器根据origin值来决定是否同意这个请求
如果请求通过会在header中多增加几个字段:
Access-Control-Allow-Origin: http://localhost:8080 (仍以上为例)
用来明确指定那些客户端的域名允许访问这个资源。它的值可以是:
允许任意域名(*)或者和一个完整的域名名字(比如:https://example.com)
Access-Control-Allow-Credentail:True(是否包含cookie) - 非简单请求
非简单请求需要发一个option方法的预检请求,成功后浏览器开始发出cors请求,其余与前面相同
其余的我暂时没有过多了解
Referer
Referer是HTTP请求header 的一部分,当浏览器(或者模拟浏览器行为)向web服务器发送请求的时候,头信息里有包含Referer
比如我在www.google.com
里有一个www.baidu.com
链接那么点击这个www.baidu.com
,它的header信息里就有Referer=http://www.google.com
Referer的正确英语拼法是referrer。由于早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。其它网络技术的规范企图修正此问题,使用正确拼法,所以目前拼法不统一。还有它第一个字母是大写。
X-Forward-For
X-Forward-For跟Referer和User-Agent一样,都是 HTTP 中的头域。
当存在X-Forward-For字段时,说明原始请求使用了代理,
X-Forward-For的正向用途是便于服务端识别原始IP。
假设有一个ip为192.0.2.40的客户端,它经过多个代理访问服务器:
代理服务器1:ip=192.0.2.22
代理服务器2:ip=192.0.2.33
服务器:ip=192.0.2.44
那么各个服务器之间的X-Forward-For字段分别为:
- 代理服务器1和客户端:
请求中没有 Forwarded 头域 - 代理服务器2和代理服务器1:
Forwarded:for=192.0.2.40
- 代理服务器2和服务器:
Forwarded:for=192.0.2.40, for:192.0.2.22;by:192.0.2.44;proto=http;host=example.com
由于客户端到代理1的请求没有使用代理,所以值为空或短横线。到代理2时,中间经过了代理1,所以值为原始IP。到服务端时,中间经过了代理1和代理2,所以值为原始IP和代理 1IP
当然,这个字段可以伪造,这样服务器就无法知道你的真实IP
写在后面
对于之前的一次内容的整理和翻新,后续会继续添加,可能会有格式的小问题,后续会进行修改