HTTP 協(xié)議中有一個(gè)用來表示頁面或資源來源的請求頭,由 Philip Hallam-Baker 于上世紀(jì) 90 年代提出來蓄坏,他當(dāng)時(shí)把這個(gè)請求頭叫做Referer价捧,并最終寫進(jìn)了 RFC1945,也就是 HTTP/1.0 協(xié)議:
The Referer request-header field allows the client to specify, for the server's benefit, the address (URI) of the resource from which the Request-URI was obtained.
有趣的是涡戳,當(dāng)時(shí)這個(gè)單詞被他拼錯(cuò)了结蟋,正確的拼寫應(yīng)該是Referrer。但是這個(gè)錯(cuò)誤被發(fā)現(xiàn)之前渔彰,已經(jīng)被大量使用嵌屎,如果要改過來需要所有服務(wù)端、客戶端的一致配合恍涂,還有大量的代碼需要排查修改编整。于是,HTTP 的標(biāo)準(zhǔn)制定者們決定將錯(cuò)就錯(cuò)乳丰,不改了掌测。下面這段描述來自于 RFC2616,也就是著名的 HTTP/1.1 協(xié)議:
The Referer[sic] request-header field allows the client to specify, for the server's benefit, the address (URI) of the resource from which the Request-URI was obtained (the "referrer", although the header field is misspelled.)
可以看到,相比 HTTP/1.0汞斧,HTTP/1.1 除了加上了對這個(gè)錯(cuò)誤的說明之外夜郁,沒有其他變化。另外粘勒,那個(gè)[sic]是拉丁文里「原文如此」的意思竞端。很多其他標(biāo)準(zhǔn)在表述 HTTP 中的Referer請求頭時(shí),都會(huì)加上[sic]庙睡,避免引起讀者誤解事富。
由此可見,HTTP 標(biāo)準(zhǔn)制定者奉行實(shí)用主義乘陪,能用就行统台。由于 HTTP 協(xié)議繼續(xù)拼錯(cuò),瀏覽器當(dāng)然只好按錯(cuò)的來啡邑,服務(wù)端收到的也是拼錯(cuò)的贱勃,所以大部分 Web Server、服務(wù)端語言或框架谤逼,都跟著拼錯(cuò)贵扰。舉幾個(gè)例子:
Nginx:ngx_http_referer_module - used to block access to a site for requests with invalid values in the "Referer" header field;
PHP:$_SERVER['HTTP_REFERER'] - The address of the page (if any) which referred the user agent to the current page流部;
Django:HttpRequest.META.HTTP_REFERER – The referring page, if any戚绕;
ThinkJS:Controller.referer() - 獲取 referer;
JavaScript 中的 Referrer
這里說的 JavaScript枝冀,都是針對宿主為瀏覽器的場景列肢,獲取到的 referrer 屬性都是由瀏覽器提供的。這一次宾茂,瀏覽器們比較齊心,都采用了正確的拼寫方式拴还,沒有讓這個(gè)錯(cuò)誤在 JavaScript 中延續(xù)跨晴。
例如 DOM Level 2 里定義的document.referrer:
Returns the URI [IETF RFC 2396] of the page that linked to this page. The value is an empty string if the user navigated to the page directly (not through a link, but, for example, via a bookmark).
最新的 Fetch API 中的 Request 接口,也有一個(gè)名為referrer的屬性:
The referrer attribute's getter must return the empty string if request's referrer is no referrer, "about:client" if request's referrer is client and request's referrer, serialized, otherwise.
更多關(guān)于 Fetch API 的介紹可以查看月影大大翻譯的這篇文章:這個(gè)API很“迷人”——(新的Fetch API)片林。
其他標(biāo)準(zhǔn)中的 Referrer
其他標(biāo)準(zhǔn)端盆,例如Referrer Policy,也采用了正確的寫法费封,并且明確表示不會(huì)兼容錯(cuò)誤的拼寫焕妙,例如在Delivery via CSP這一節(jié)寫著:
Note: The directive name does not share the HTTP header's misspelling.
結(jié)論
HTTP 請求中的Referer是一個(gè)典型的拼寫錯(cuò)誤,歷史悠久弓摘,可以預(yù)見還會(huì)一直錯(cuò)下去焚鹊。也許以后Referer會(huì)變成一個(gè)專有名詞也說不定。所以韧献,一般涉及到讀取 HTTP 請求頭的場景末患,我們需要用Referer這種錯(cuò)誤拼寫研叫;除此之外一般都要用Referrer這種正確的拼寫。
(查看來源)