📖閱讀本文,你将:
- 學會幾個超級超級實用的響應頭,解決你工作中遇到的問題。
- 不僅解決問題,還能讓你在和後端、運維撕逼時占據上風。
學習 響應頭 很重要嗎?
真的很重要。
不信你看看下面的場景,眼熟不?
一、預覽、下載下傳 讓人操碎了心?
1.1 場景
我不止一次聽到同僚、群友們讨論這個問題:
“後端提供了一個 (或者
txt
/'json' 等)檔案的下載下傳
pdf
,可以當我用
url
标簽打開時,卻變成了預覽……怎麼辦?救!!!”
a
此時,就會有人上去推薦
FileSaver.js
或者 “手寫讀流另存為”。
然後還有人附和...
我:???
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-AnYldnL5cjMzkDOzQGN5YGNwQTZyYzX5ADNwADMwMzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.webp)
這是需要寫代碼才能解決的問題嗎?
如果你有了解過
Content-Disposition
這個
Response Header
,那你一定知道,隻需要響應頭上增加一行,問題就能迎刃而解。
1.2 介紹
Content-Disposition
:這個響應頭可以決定内容是 預覽 還是 下載下傳。
它支援三種格式的值:
-
Content-Disposition: inline
此時,消息體會以頁面的一部分或者整個頁面的形式展示。(預覽)
-
Content-Disposition: attachment
消息體應該被下載下傳,預設檔案名和
格式有關。url
-
Content-Disposition: attachment; filename="filename.jpg"
消息體應該被下載下傳,預設檔案名可指定。
注:如果需要預覽,需要配合适當的 Content-Type
食用;
1.3 示例
為此,我特意寫了一個
express
小示例。
大抵是在
express
應用下寫了三個路由,如下:
const user = {
name: "摸魚的春哥",
blogUrl: "https://juejin.cn/user/1714893870865303"
}
const contentDispositionInline = async (req, res, next) => {
res.setHeader('Content-Disposition', 'inline')
res.send(user)
}
const contentDispositionFilename = async (req, res, next) => {
res.setHeader('Content-Disposition', 'attachment; filename="chunge.json"')
res.send(user)
}
const contentDispositionNoFilename = async (req, res, next) => {
res.setHeader('Content-Disposition', 'attachment')
res.send(user)
}
然後我分别通路三個路由,效果差異:
二、項目更新了,需要客戶 清空緩存 ?
2.1 場景
實施:“客戶回報
Bug
還是沒修複。”
你:“哥,真修複了,要不你讓客戶清一下緩存?”
實施:“啊?客戶說他不會清……”
……
永遠不要期望你的客戶會進行 “那些研發才懂” 的操作。也不要把你的問題,歸因到 浏覽器緩存 上。
浏覽器緩存 是被發明出來優化使用者體驗的,并不是被發明出來阻礙使用者的。
是以,了解如何使用
Cache-Control
這個響應頭,是前端的必知技能。
2.2 介紹
Cache-Control
:用來指定緩存機制。
緩存,作為前端八股文必考知識,相信大家已經耳熟能詳。
常見的
Cache-Control
Response Header屬性 | 值 | 含義 |
cache-control | no-store | 不緩存,這個會讓用戶端、伺服器都不緩存,也就沒有所謂的強緩存、協商緩存了。 |
cache-control | public | 表明響應可以被任何對象(包括:發送請求的用戶端,代理伺服器,等等)緩存,即使是通常不可緩存的内容。(例如:1.該響應沒有max-age指令或Expires消息頭;2. 該響應對應的請求方法是 POST 。) |
cache-control | private | 表明響應隻能被單個使用者緩存,不能作為共享緩存(即代理伺服器不能緩存它)。私有緩存可以緩存響應内容,比如:對應使用者的本地浏覽器。 |
cache-control | max-age=<1000> | 設定緩存存儲的最大周期,超過這個時間緩存被認為過期(機關秒)。與Expires相反,時間是相對于請求的時間。 |
-
不緩存
不緩存是最容易了解,每一次請求都會從服務端重新擷取,不進行任何緩存。
此政策隻需要賦予
響應頭即可。Cache-Control: no-store
-
強緩存
有些資源檔案,幾乎不會發生變化(比如已經
hash化命名的檔案
),則可以直接從本地緩存擷取,這就是所謂的強緩存;
通過
或者cache-control: public/private
都可以指定機制為強緩存。cache-control: max-age=<1000>
-
協商緩存
這是一種更為複雜緩存機制,無法再通過響應頭簡單粗暴地指定實作,而是需要前後端協作配合。
簡單來說,每次請求資源前前端會寫代前一次的響應
hash
,問詢服務端資源是否發生過變化,進而達到準确緩存的效果。
本文不贅述,如果有興趣,可以參考此文:juejin.cn/post/703078…
2.3 實際生産如何運用?
- 凡是名稱帶有
hash
值的資源,一律可以強緩存。
(畢竟内容一旦有變化,名稱的
也跟着變了)hash
- 凡是通過
cdn
引入的第三方庫,均建議攜帶版本資訊,這樣也可以強緩存。
(比如
切換為/xx/xx/jquery.min.js
)[email protected]/dist/jquery.min.js
- 凡是
、html
這類命名固定的檔案,建議一律不緩存或者協商緩存。ico
三、我的 Cookie
不可能這麼可愛!
Cookie
3.1 場景
"春哥春哥,為啥我登入成功了,請求還是
401
?"
"春哥春哥,為啥我存進
cookie
的值取不到?"
"春哥春哥,這破
是不是壞了,浏覽器裡看明明有值,為啥我通路不了?"
cookie
我:“兄弟,你有了解過一個叫
set-cookie
的響應頭嗎?”
是它!是它!就是它!關于
cookie
的各種異常,全靠它!
3.2 介紹
Cookie
曾經是
Web
開發無法繞開的一道門檻,而現在它的存在感越來越弱,但海量的存量項目并不會因為技術的趨勢而消失,它們依然很有價值,依然需要維護。
而
set-cookie
響應頭正是
Cookie
體系中最為核心的 第一主角。
Set-Cookie
: 是一個響應頭,服務端指派,讓浏覽器端産生
Cookie
,并限定
Cookie
的各種特性。
這些特性就包括:
- 過期時限;
Expires=<date>
- 存活周期;
Max-Age=<number>
在 cookie 失效之前需要經過的秒數。
或 0
直接失效;此屬性的優先級高于 -1
。Expires
- 域名;
Domain=<domain-value>
指定
隻能在什麼域下生成;(允許通配,這個屬性主要出于安全性)cookie
- 路徑;
Path=<path-value>
比
更為細緻的控制政策,甚至指定了 Domain
路徑下才能發送 xx
。Cookie
- 隻在
産生;Https
Secure
如果
頭中有 set-cookie
屬性,那麼浏覽器隻會在 Secure
環境産生和發送 Https
。Cookie
- 禁用
操作js
;API
HttpOnly
如果
頭中有 set-cookie
屬性,那麼 HttpOnly
屬性的生成、讀寫、發送就隻能由浏覽器通過 "響應頭" 控制了,不在允許前端通過 Cookie
操作 js
。Cookie
- 是否允許跨域攜帶;
SameSite=<samesite-value>
- 支援屬性包括
、Strict
、Lax
,分别表示:None
-
: 完全不能跨域攜帶;Strict
-
: 隻允許從外站導航到源站時攜帶 Lax
Cookie
-
:跨域也行,不限制。None
3.3 開發常見問題分析
- 為啥你登入成功了,請求還是
401
?
早期非常多的項目,使用
作為使用者身份識别的手段,比如 Cookie
項目就是通過給 Spring MVC
一個 Cookie
JSeesionId
的值作為識别,判斷你是否出于目前會話。
而 "登入了,卻還
401
" 這個現象,如果服務端沒有問題的話,多半是 浏覽器其實并未存儲Cookie。
換個說法,你每次發起請求,服務端都認為你是一次新的會話,和上一次 登入的你 并非同一人。
如果你正處于
環境,那你可能需要暫時移除 http
屬性。Secure
-
存不進、取不出?
先确認 是否有域的限制、是否有路徑的限制、是否有
HttpOnly
?
逐一排查下來,問題不難解決。