CodeIgniter4 內(nèi)容協(xié)商

2020-08-13 16:26 更新

內(nèi)容協(xié)商是一種用來(lái)根據(jù)客戶端和服務(wù)端可處理的資源類型,來(lái)決定返回給客戶端哪種類型的內(nèi)容的機(jī)制。 該機(jī)制可用來(lái)決定客戶端是想要 HTML 還是想要 JSON ,一個(gè)圖片是應(yīng)該以 JPG 還是以 PNG 格式返回,或者支持哪種類型的壓縮方法等。 這些決策是通過(guò)分析四個(gè)不同的請(qǐng)求頭,而這些請(qǐng)求頭里支持多個(gè)帶有優(yōu)先級(jí)的值選項(xiàng)。手動(dòng)對(duì)這些值選項(xiàng)進(jìn)行優(yōu)先級(jí)匹配通常是較有挑戰(zhàn)性的,因此 CodeIgniter提供了 Negotiator 來(lái)處理以上過(guò)程。

加載類文件

你可以通過(guò) Service 類來(lái)手動(dòng)加載一個(gè)該類的實(shí)例:

$negotiator = \Config\Services::negotiator();

以上操作會(huì)獲取所有的請(qǐng)求實(shí)例并自動(dòng)將其自動(dòng)注入到 Negotiator (協(xié)商,下同)類中。

該類并不需要主動(dòng)加載。而是通過(guò)請(qǐng)求的 IncomingRequest 實(shí)例來(lái)進(jìn)行范文。 盡管你并不能通過(guò)這一過(guò)程直接訪問(wèn)該實(shí)例,你可以通過(guò) negotiate() 方法來(lái)調(diào)用它的所有方法:

$request->negotiate('media', ['foo', 'bar']);

當(dāng)通過(guò)該方法訪問(wèn)實(shí)例時(shí),第一個(gè)參數(shù)是你需要匹配的內(nèi)容的類型,第二個(gè)是所支持的類型值構(gòu)成的數(shù)組。

協(xié)商

本節(jié)中,我們將討論四種可以用來(lái)協(xié)商的類型,并展示如何通過(guò)上述兩種方法來(lái)進(jìn)行內(nèi)容協(xié)商。

媒體

第一層首先要看的就是媒體協(xié)商。該協(xié)商方式是通過(guò) Accept 請(qǐng)求頭進(jìn)行的,并且是可用的請(qǐng)求頭中最為復(fù)雜的類型之一。 一個(gè)常見的例子就是客戶端告訴服務(wù)端其所需要的數(shù)據(jù)格式,而這種操作在 API 中最為常見。例如,一個(gè)客戶端可能從一個(gè) API 終點(diǎn)請(qǐng)求 JSON 編碼的數(shù)據(jù):

GET /foo HTTP/1.1
Accept: application/json

該服務(wù)器需要提供一個(gè)所支持的該內(nèi)容的類型列表。在本例中,API 可能需要返回像原生 HTML ,JSON 或者是 XML 格式的數(shù)據(jù)。而根據(jù)客戶端偏好,該列表應(yīng)順序返回:

$supported = [
        'application/json',
        'text/html',
        'application/xml'
];


$format = $request->negotiate('media', $supported);
// 或者是
$format = $negotiate->media($supported);

在本例中,客戶端和服務(wù)器協(xié)商一致,將數(shù)據(jù)以 JSON 的格式返回,因此 ‘json’ 就會(huì)從協(xié)商方法中返回。默認(rèn)情況下,如果沒(méi)有匹配到,在 $support 數(shù)組中的第一個(gè)成員就會(huì)返回。 盡管在某些情況下,你可能會(huì)強(qiáng)制要求服務(wù)端進(jìn)行嚴(yán)格匹配格式。因此如果你將 true 作為最后參數(shù)傳入時(shí),在匹配不到時(shí)就會(huì)返回空字符串:

$format = $request->negotiate('media', $supported, true);
// 或
$format = $negotiate->media($supported, true);

語(yǔ)言

另一個(gè)常見的用法就是用于決定需要返回的內(nèi)容的語(yǔ)言。如果你運(yùn)行的是一個(gè)單語(yǔ)言網(wǎng)站,該功能顯然并沒(méi)有什么影響。 但是如果對(duì)于那些提供多語(yǔ)言內(nèi)容的網(wǎng)站來(lái)說(shuō),該功能就會(huì)變得非常有用,基于瀏覽器將通常會(huì)在 Accept-Language 請(qǐng)求頭中發(fā)送偏好的語(yǔ)言類型:

GET /foo HTTP/1.1
Accept-Language: fr; q=1.0, en; q=0.5

本例中,瀏覽器偏好法語(yǔ),并次偏好英語(yǔ)。如果你的網(wǎng)站支持英語(yǔ)或德語(yǔ),那么你就會(huì)如下操作:

$supported = [
        'en',
        'de'
];


$lang = $request->negotiate('language', $supported);
// 或
$lang = $negotiate->language($supported);

本例中,”en”將作為當(dāng)前語(yǔ)言返回。如果沒(méi)有產(chǎn)生匹配,就會(huì)返回 $supported 數(shù)組的第一個(gè)成員,因此該成員將會(huì)一直作為偏好語(yǔ)言。

編碼

Accept-Encoding 請(qǐng)求頭包含了客戶端所期望接收到的字符集,用于確定客戶端支持哪種類型的壓縮方式:

GET /foo HTTP/1.1
Accept-Encoding: compress, gzip

你的 web 服務(wù)器將會(huì)定義可以使用的壓縮類型。某些服務(wù)器,例如 Apache , 只支持了 gzip

$type = $request->negotiate('encoding', ['gzip']);
// 或
$type = $negotiate->encoding(['gzip']);

更多信息,參閱 Wikipedia.

字符集

所期待的字符集類型會(huì)通過(guò) Accept-Charset 請(qǐng)求頭來(lái)傳值:

GET /foo HTTP/1.1
Accept-Charset: utf-16, utf-8

默認(rèn)情況下,如果沒(méi)有匹配的話就會(huì)返回 utf-8

$charset = $request->negotiate('charset', ['utf-8']);
// 或者是
$charset = $negotiate->charset(['utf-8']);
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)