Fetch API是一種從邊緣節點擷取資料的方法。通過Fetch API,您可以使用HTTP或HTTPS協議從邊緣節點請求資料,並將資料返回給使用者。它類似於瀏覽器環境中的Fetch API,可以用於動態載入內容、與後端服務進行互動、實現A/B測試等情境。
Fetch API方法定義
Fetch是完全非同步線程,只要您不使用await,Fetch就不會阻塞指令碼執行。目前每次可以發起4個子請求。由於底層採用的是長串連,您無需擔心效能,也不用主動處理串連池。
Fetch可以進行HTTP或HTTPS請求,每一次redirect都算一次請求。每一個Fetch最多可以支援12次redirect。
方法定義
fetch(arg, init),Fetch的詳細定義請參見MDN官方文檔WorkerOrGlobalScope.fetch()。方法限制
目前Fetch API只支援網域名稱,不支援IP地址。HTTP請求對應的連接埠為80,HTTPS請求對應的連接埠為443。
init參數內部的credentials、referrer、referrerPolicy、cache和integrity無任何意義。redirect預設值為follow,即fetch時如果來源站點返回3xx會直接跟隨。如果不需要跟隨3xx,需將redirect設定為manual。
說明對瀏覽器內部的多種Fetch模式不做區分,例如
CROS fetch,在CDN/DCDN/ESA上您可以Fetch任何來源站點。如果需要4個及以上的子請求時,請提交工單申請配額。
請求URL的總長度不超過4 KB。
函數通過Fetch擷取的gzip壓縮資源預設解壓。如不希望預設解壓內容,請參見下方Decompress章節添加
manual參數。
設定逾時時間
Timeout函數
/** * 請求逾時控制實現 * * @param {Number} timeout 逾時等待時間,單位ms * @param {Object} config 逾時配置 * - @param {Object|Funtion} handler 逾時返回 * @returns */ const RequestTimeout = (timeout, config) => { return new Promise((resolve) => { const { handler = null } = config; let timer = setTimeout(() => { clearTimeout(timer); timer = null; const defaultRes = (typeof handler === 'function' ? handler() : handler) || {}; resolve(defaultRes); }, timeout); }); };調用樣本
const KV_TIMEOUT = 1000; let edgekv = new EdgeKV({ namespace: KV_NS, }); let kvRequest = edgekv.get(key, getType); let timeoutPromise = RequestTimeout(KV_TIMEOUT, { handler: { res: {}, errorMessage: `kv request timeout (${KV_TIMEOUT}ms)`, } }); let resp = await Promise.race([ kvRequest, timeoutPromise, ]); if (resp === undefined) { return "kv not found, key = " + key; } else { return resp; }
Redirect
Fetch運行支援3xx跟隨,即3xx重新導向。3xx包含的status code有301、302、303、307和308。根據標準您可以指定以下三種行為。
{redirect: "manual"}:不跟隨3xx,您自己處理。{redirect: "error"}:3xx直接報錯。{redirect: "follow"}:(預設值)跟隨3xx,最多支援20次。
重新導向方案見下表。
狀態代碼 | 重新導向說明 |
301、302、303、308 | 要求方法改成GET,body被忽略。 |
307 | 只跟隨GET方法,其他方法會報錯。 |
重新導向的地址來源於Location頭,Location必須出現,否則會報錯。
Location可以含有由一個英文逗號,分割的URL表單,但只有第一個會被使用,其他均被忽略。Location可以含有絕對URL或者相對URL。
Decompress
Fetch允許您配置API的解壓縮模式,例如fetch("https://www.example.com",{decompress: "manual"})。Fetch的decompress參數有以下三種值:
manual:不解壓縮。如果Fetch的伺服器將壓縮後的資料發送回來,則在ER中會讀取到被壓縮的資料。
decompress(預設值):自動解壓縮。目前Fetch支援Gzip壓縮模式,ER會根據content-encoding頭自動偵測或者使用解壓縮。ER如果執行瞭解壓縮,會自動修改content-encoding的值。如果刪除了其中的Gzip項,為了防止透傳時出現錯誤,您可以在下面兩種方式中任選一種進行設定:
content-encoding:gzip表示可以被ER識別。content-encoding:gzip, identity表示可以被ER識別。
說明其他非Gzip的演算法,目前會報錯。
fallbackIdentity:類似decompress,如果無法識別壓縮,則預設不解壓縮。
Fetch自動壓縮後如果回複中有content-length頭,不能隨意透傳content-length頭,因為此時content-length表示未被解壓縮前的字元大小,不再反映解壓縮完成後的資料大小。
content-length
如果您使用Fetch請求資料時設定了content-length,Fetch會採用content-length的編碼,同時會改變Fetch發送body的預設行為。如果您不設定content-length,Fetch會主動把body流的所有資料讀取出來並發送,發送使用chunk-encoding。
content-length設定content-length為非負數:根據您設定的值從發送的body流讀取相應的位元組後發送,發送採用content-length。如果content-length為0,則不發送任何資料。content-length為非法值:繼續使用chunk-encoding發送所有body的值。
舉例說明
Fetch會自動解壓縮內容,解壓縮後response的
content-length仍然存在,該content-length表示未被解壓縮前的資料大小。如果您改動body後再使用Fetch需注意content-length,否則發送的內容可能會出錯。以下樣本中,假設用戶端發送了一個POST請求,且header中包含了
content-length。當您使用Fetch進行請求時,由於body複用了用戶端request的header對象,會導致content-length的值和當前發送的body實際資料大小不一致。您透傳header時一定要關注body的實際大小是否發生改變。export default { fetch(request) { return handleRequest(request) } } async function handleRequest(request) { return fetch("http://www.example.com", { headers: request.headers, method: request.method, body: "SomeData" }); }
Headers
定義
Headers的定義,請參見MDN官方文檔Headers。
限制
header內部會記錄記憶體消耗,header對象可以儲存的最大header是8 KB。如果單個header對象超用,會觸發JS exception。
黑名單
header有黑名單,無法讀寫以下頭,如果您讀取會造成exception。
expect
te
trailer
upgrade
proxy-connection
connection
keep-alive
dnt
host
其他內部頭
Request
定義
Request的定義,請參見MDN官方文檔Request。
限制
Request對象的以下屬性沒有實現,在CDN/DCDN/ESA上下文中沒有意義。
context
credentials
destination
integrity
mode
referrer
referrerPolicy
cache
常見使用
獲得要求方法:
request.method。獲得請求url:
request.url。獲得要求標頭:
request.headers。獲得請求負載:
request.body,body是一個ReadableStream對象。獲得JSON:
await request.json()。獲得表單資料:
await request.formData()。獲得UTF8字串:
await request.text()。
Request介面是標準的擴充,既可以忽略body,又確保body可以讀完,且不會將記憶體讀入JavaScript虛擬機器,從而避免了GC造成的延時,確保請求流的body從底層的socket中全部讀出。對於
await request.ignore(),如果您不需要讀取Fetch的body或者不感興趣,建議所有的Fetch請求都調用request.ignore,可以有效提高效能,因為運行時會自動把讀取完body的請求發送至串連池中供下次複用。
Response
定義
Response的定義,請參見MDN官方文檔Response。
限制
Response對象的useFinalURLS和error屬性沒有實現,在CDN/DCDN/ESA上下文中沒有意義。
常見使用
獲得回複碼:
response.status。獲得回複reason phrase:
response.statusText。獲得回複頭:
response.headers。獲得回複URL:
response.url,表示該回複是對應的URL發送的。獲得所有redirect的URL list,屬於非標準:
response.urlList,類似Request對象實現了body mixin,使用類似方法您可以獲得body對象。
FormData
定義
FormData的定義,請參見MDN官方文檔FormData。
限制
FormData類似Header,有內部大小限制,如果過大FormData會出現異常。如果把FormData當作HTTP body發送,預設的
content-type是form-data/multipart。
URLSearchParams
定義
URLSearchParams的定義,請參見MDN官方文檔URLSearchParams()。
限制
如果把URLSearchParams當作HTTPbody發送,預設的
content-type是application/x-www-form-urlencode,最大限制為1000位元組。