http标头的一些字段的介绍以及使用
公司大下周,趁着摸鱼的时间总结一下大部分标头的大概意思和用法。不是很全,但是大部分应该都在平时需要知道的一些标头的用意
1.Access-Control-Allow-Origin 通过设置这个属性表示可以被哪些网站进行跨域资源共享
// 设置某个网站 或者多个网站允许跨站资源共享
Access-Control-Allow-Origin: http://example.com:8080 http://foo.example.com
// 允许所有的域名访问 一般会有安全隐患
Access-Control-Allow-Origin:*
2.Accept-Ranges 服务器是否支持资源范围请求
资源范围请求:指按byte为单位,请求资源的某一段数据
Accept-Ranges:bytes 表示该资源支持byte形式资源范围请求
Accept-Ranges:none则表示不支持
3.Access-Control-Allow-Methods 允许哪些请求方法
Access-Control-Allow-Methods是一个HTTP响应头部,用于指定在预检请求中允许的HTTP方法。它是CORS(跨域资源共享)标准的一部分。CORS是一种机制,用于让Web应用程序可以访问其他域名下的资源。因为同源策略的限制,JavaScript代码只能从同一个域名下加载资源。
const http = require('http');
const server = http.createServer((req, res) => {
// 设置CORS头部
res.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有请求方式
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT'); // 允许部分请求方式
....
});
server.listen(3000);
**4.Access-Control-Allow-Credentials **
响应头用于在请求要求包含 credentials时,告知浏览器是否可以将对请求的响应暴露给前端 JavaScript 代码。
Access-Control-Allow-Credentials 的值为 true 的情况下将响应暴露给前端的 JavaScript 代码。
Credentials 可以是 cookies、authorization headers 或 TLS client certificates。
Access-Control-Allow-Credentials值为true时,Access-Control-Allow-Origin必须有明确的值,不能是通配符(*)
一般遇到的问题就是设置config.js里面devServer的proxy 的 changeOrigin:true,允许跨域 可以代理反向的地址(本地开发的时候会用到)
5.Access-Control-Allow-Headers
Access-Control-Allow-Headers(ACAH)是CORS标准中的一个关键头信息,它允许服务器指定哪些自定义头可以被客户端访问
Access-Control-Allow-Headers头的作用是允许服务器指定哪些自定义请求头可以被浏览器访问。通常情况下,浏览器只允许访问一些常见的请求头,如Content-Type和Authorization。但是,如果 Web 应用程序需要在请求头中使用自定义字段,则需要在服务器端配置Access-Control-Allow-Headers来允许浏览器访问它们。
对于 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 三种 MIME 类型(不包括参数)),它们始终是被支持的,不需要在这个首部特意列出
6.Access-Control-Max-Age
浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求(比如异步请求GET, POST, PUT, DELETE, OPTIONS等等),所以浏览器会向所请求的服务器发起两次请求,第一次是浏览器使用OPTIONS方法发起一个预检请求,第二次才是真正的异步请求,第一次的预检请求获知服务器是否允许该跨域请求:如果允许,才发起第二次真实的请求;如果不允许,则拦截第二次请求。
Access-Control-Max-Age用来指定本次预检请求的有效期,单位为秒,,在此期间不用发出另一条预检请求。
比如:
resp.addHeader("Access-Control-Max-Age", "0") //表示每次异步请求都发起预检请求,也就是说,发送两次请求。
resp.addHeader("Access-Control-Max-Age", "1800") //表示隔30分钟才发起预检请求。也就是说,发送两次请求
7.Allow 首部字段用于枚举资源所支持的 HTTP 方法的集合
8.Age 消息头里包含对象在缓存代理中存贮的时长,以秒为单位
Age 的值通常接近于 0。表示此对象刚刚从原始服务器获取不久;其他的值则是表示代理服务器当前的系统时间与此应答中的通用头 Date 的值之差。
9.HTTP Authorization 请求标头用于提供服务器验证用户代理身份的凭据,允许访问受保护的资源。
可以理解为携带token
config.headers!.Authorization = 'Bearer ’ + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
10.Cache-Control 缓存 Expires
Cache-Control 通用消息头字段,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。他简称为HTTP缓存,分为强缓存和弱缓存,
后面专门总结一下强缓存和弱缓存 Cache-Control
这里浅谈一下
HTTP缓存一直是一个老生常谈的问题,前端在日常发布、部署工作中,常常要面对。其中面对的问题有可能会是:部署的代码无法生效,这次本人所在团队也遇到了相关问题,
比如:
1.项目会在静态资源(如:css,js)使用chunkHash来处理,因此能保证修改后与旧代码文件名字不会重复。以避免无法更新改动
2.在该项目中部署后,进行代码进行一次location.reload,改动即可以生效。
最后,发现是因为该项目部署的服务器上所有静态资源的response headers的设置如下:
response headers:cache-control: public, max-age=31536000
项目的入口: index.html也是如此。因此实际是因为所有的.html文件命中(cache hit)了强缓存,导致了用户无法直接呈现更新后代码的改动。
那么如何解决呢
1.跳转时增加时间戳例如:
location.href = ‘https://www.localhost:5000.com/index.html?t=201811141248001’;
2.修改response headers中的cache-control
cache-control: public, max-age=0
3.使用HTML Meta 标签,可以在html代码中增加meta标签:
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。
最好还是不要指定HTML标签,通过可能会出现混乱(到底以那端为主,实际response header的优先级更高)。此外,在HTML5中,这些<meta HTTP等>标签是无效的。只有HTML5规范中列出的HTTP等效值才被允许。
http缓存:
1.判断是否存在缓存
2.判断缓存是否有效
3.请求服务端时,判断服务端资源是否更新 即协商缓存是否命中
4.返回资源
查看是否存在换在缓存在Response Header中 Cache-Control 对应的设置可以一直到是否设置了缓存这里介绍一下Cache-Control有哪些值:
public:表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容。(例如:1.该响应没有max-age指令或Expires消息头;2. 该响应对应的请求方法是 POST 。)
private:表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。
no-cache:在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证 (协商缓存验证)。
no-store:缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
max-age= :设置缓存存储的最大周期,超过这个时间缓存被认为过期 (单位秒)。与Expires相反,时间是相对于请求的时间。
s-maxage= :覆盖max-age或者Expires头,但是仅适用于共享缓存 (比如各个代理),私有缓存会忽略它。
max-stale[=] :表明客户端愿意接收一个已经过期的资源。可以设置一个可选的秒数,表示响应不能已经过时超过该给定的时间。
min-fresh=:表示客户端希望获取一个能在指定的秒数内保持其最新状态的响应。
stale-while-revalidate= 实验性
表明客户端愿意接受陈旧的响应,同时在后台异步检查新的响应。秒值指示客户愿意接受陈旧响应的时间长度。
stale-if-error= 实验性
表示如果新的检查失败,则客户愿意接受陈旧的响应。秒数值表示客户在初始到期后愿意接受陈旧响应的时间。
must-revalidate
一旦资源过期(比如已经超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。
proxy-revalidate
与 must-revalidate 作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略。
no-transform
不得对资源进行转换或转变。Content-Encoding、Content-Range、Content-Type等 HTTP 头不能由代理修改。例如,非透明代理或者如Google’s Light Mode可能对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。no-transform指令不允许这样做。
only-if-cached
表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。
强缓存:
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。
实际就是我们整体流程内的,查看是否存在缓存以及,查看缓存是否有效。
实现强缓存,主要是根据客户端保留的一个服务器端的response header中的两个字段:expires、cache-control。
cache-control优先级比expires高。
比如:
expires:Sat, 19 Aug 2023 02:25:59 GMT
cache- control:private max-age=3153600
从上面可以看出 HTTP响应报文中expires的时间值,是一个绝对值。HTTP响应报文中Cache-Control为max-age=31536000,是相对值。在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。
Expires:Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
缓存失效时间计算公式如下:
expirationTime = responseTime + freshnessLifetime - currentAge
responseTime 表示浏览器接收到此响应的那个时间点。
状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置
这里说明一下 disk cache 表示从磁盘中获取缓存资源,momory cache 从内存中获取资源
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:
Last-Modified / If-Modified-Since 和 Etag / If-None-Match。
Etag / If-None-Match 优先级比 Last-Modified / If-Modified-Since 高。
Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT
If-Modified-Since: If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
浏览器发送HTTP请求时,把If-Modified-Since一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。
如果时间一致,那么返回HTTP状态码304(Not Modified),客户端接到之后,直接把本地缓存文件显示到浏览器中。
如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。
Etag: 是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)
ETag: “33a64df551425fcc55e4d42a148795d9f25f89d4”
ETag: W/“0815”
If-None-Match: 是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200
如何判断协商缓存是否命中
如果协商缓存命中,请求响应返回的http状态为304并且会显示一个Not Modified的字符串。
如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;
强缓存不发请求到服务器,协商缓存会发请求到服务器。
但是如果强制刷新,或者清空缓存在刷新,或者打开无痕窗口进度都会请求服务器资源
11. Keep-Alive
是一个通用消息头,允许消息发送者暗示连接的状态,还可以用来设置超时时长和最大请求数。
keep-Alive:timeout=60 // 接口请求60秒之后没有返回就提示请求超时
12. Connection
Connection 通用标头控制网络连接在当前会话完成后是否仍然保持打开状态。如果发送的值是 keep-alive,则连接是持久的,不会关闭,允许对同一服务器进行后续请求。
13. Content-Type
Content-Type 实体头部用于指示资源的 MIME 类型 media type 。
在响应中,Content-Type 标头告诉客户端实际返回的内容的内容类型。浏览器会在某些情况下进行 MIME 查找,并不一定遵循此标题的值; 为了防止这种行为,可以将标题 X-Content-Type-Options 设置为 nosniff。
Content-Type四种常见取值
1. application/x-www-form-urlencoded POST 提交数据的方式。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
Content-Type: application/x-www-form-urlencoded;charset=utf-8
2. multipart/form-data 这是另一种非常常见的 POST 数据提交的方式。我们在使用表单上传文件时,必须让 form 的 enctyped 等于这个值
POST http://192.168.2.12/index HTTP/1.1
Content-Type:multipart/form-data;
boundary=--WebKitFormBoundaryrGKCBY7qhFd3TrwA
---WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
---WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition:form-data;name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
---WebKitFormBoundaryrGKCBY7qhFd3TrwA
3. application/json
用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,这是我们用的最常见的格式
4.text/xml
XML-RPC(XML Remote Procedure Call)。它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC 请求是这样的:
POST http://http://ws.webxml.com.cn/ HTTP/1.1
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getSupportCityDatasetResponse xmlns="http://WebXml.com.cn/">
<getSupportCityDatasetResult>
<xsd:schema>schema</xsd:schema>xml</getSupportCityDatasetResult>
</getSupportCityDatasetResponse>
</soap:Body>
</soap:Envelope>
14. Content-Encoding和Accept-Encoding
Accept-Encoding 和Content-Encoding是HTTP中用来对采用哪种编码格式传输正文进行协定的一对头部字段。
首先浏览器(也就是客户端)发送请求时,通过Accept-Encoding带上自己支持的内容编码格式列表;
服务端在接收到请求后,从中挑选出一种用来对响应信息进行编码,并通过Content-Encoding来说明服务端选定的编码信息,浏览器在拿到响应正文后,依据Content-Encoding进行解压。
Content-Encoding: gzip // gzip是一种比较流行的压缩算法,当它被使用时,HTTP消息实体会首先进行deflate压缩,然后会采用crc32校验,最后加上一个8字节长度的报头。
Content-Encoding: deflate // deflate算法与gzip算法类似,不同在于它没有8字节长度的报头。deflate算法常用于Java应用中的压缩。
Content-Encoding: br // br是一种采用Brotli算法的压缩算法,Brotli算法是Google公司2015年发明的一种数据压缩算法,可以获得更高的压缩比。但由于目前的浏览器和服务器普遍不支持,因此使用场景比较少。
15. Content-Length 和 Transfer-Encoding
Content-Length, HTTP消息长度, 用十进制数字表示的八位字节的数目. 一般情况下, 很多工作都被框架完成, 我们很少去关注这部分内容, 但少数情况下发生了Content-Length与实际消息长度不一致, 程序可能会发生比较奇怪的异常
比如:
无响应直到超时.
请求被截断, 而且下一个请求解析出现错乱
他是如何工作的:
Content-Length使用十进制的数字表示了消息的长度, 服务端/客户端通过它来得知后续要读取消息的长度.
当你设置了content-length的长度比如 Content-Length:100;然后你返回的字符长度可能不止一百,或者说你根本就不知道返回的长度是多少,因为服务器返回的数据长度是不固定的,可能出现content-length > 实际长度也可能 < 实际长度,那么这些都会导致请求数据报错。一般情况下,我们只会在Response-headers里面设置
Transfer-Encoding:chunked
他的大概意思是数据以一系列分块的形式进行发送. Content-Length 首部在这种情况下不被发送. 在每一个分块的开头需要添加当前分块的长度, 以十六进制的形式表示,后面紧跟着 \r\n , 之后是分块本身, 后面也是\r\n. 终止块是一个常规的分块, 不同之处在于其长度为0.
16. Content-Location 和 Location
Content-Location报头指示为返回的数据的备用位置。主要用途是指示作为内容协商结果传输的资源的 URL 。
Location指示重定向的 URL ,同时Content-Location指示用于访问资源的直接 URL ,而未来未进一步内容协商。
Location是与响应关联的头部,Content-Location与返回的数据相关联。没有示例,这种区分看起来很抽象。
17加粗样式. Vary
HTTP 响应头决定如何满足未来的请求头,以决定一个缓存的响应是否可以使用,而不是从源服务器请求一个新的。服务器使用它来指示在内容协商算法中选择资源表示时使用哪个标头。Vary 头是一个非常重要的头部信息,使用不当将会导致缓存的错误使用和性能问题。
18. Referer
Referer是HTTP请求header中的一部分,其表示请求当前资源的客户端来源,当浏览器(或模拟浏览器行为)向web服务器发送请求的时候,头部信息里会携带Referer。
他的作用就是防盗链, 比如只允许某一台服务器访问我自己的服务资源,则可以交验http请求头中的包含的referee,来判断是不是特定的域名,如果不是则拒绝响应,大部分情况下,referee都是指向自身网站的服务器地址的。