انتقل إلى المحتوى

WHATWG Fetch

⁦Blob⁩ و⁦File⁩ و⁦Headers⁩ و⁦FormData⁩ والأجسام والطلبات والاستجابات و⁦fetch⁩.

في هذه الصفحة

يكشف ⁦Elide⁩ ‏⁦Blob⁩ و⁦File⁩ و⁦Headers⁩ و⁦FormData⁩ و⁦Request⁩ و⁦Response⁩ و⁦fetch⁩ بوصفها متغيرات عامة.

⁦Blob⁩ و⁦File⁩

const blob = new Blob(["hello"]);
await blob.text(); // "hello"
await blob.bytes(); // Uint8Array(5)

const file = new File(["hello"], "greeting.txt", {
  type: "text/plain",
  lastModified: 1700000000000,
});
file instanceof Blob; // true

تشمل قارئات ⁦Blob⁩ ‏⁦text()⁩ و⁦arrayBuffer()⁩ و⁦bytes()⁩ و ⁦stream()⁩. ويعيد ⁦slice()⁩ كائن ⁦Blob⁩. ويضيف ⁦File⁩ ‏⁦name⁩ و ⁦lastModified⁩.

Headers

const headers = new Headers([["X-Custom", "1"]]);
headers.append("X-Custom", "2");
headers.get("x-custom"); // "1, 2"

headers.append("Set-Cookie", "a=1");
headers.getSetCookie(); // ["a=1"]

الأسماء لا تميّز حالة الأحرف. ويحوّل التكرار الأسماء إلى أحرف صغيرة ويرتّبها، ويدمج معظم القيم المكررة، ويُبقي قيم ⁦Set-Cookie⁩ منفصلة. وترمي الأسماء أو القيم غير الصالحة ⁦TypeError⁩. وتقيّد حراسات الطلب والاستجابة و⁦no-CORS⁩ وعدم القابلية للتغيير التعديلات حيثما انطبق ذلك.

FormData

‏⁦FormData⁩ قائمة مرتّبة حسب الإدراج من قيم السلاسل النصية أو ⁦File⁩.

const form = new FormData();
form.append("tag", "first");
form.append("tag", "second");
form.getAll("tag"); // ["first", "second"]

form.append("upload", new Blob(["hello"], { type: "text/plain" }));
form.get("upload").name; // "blob"

يُطبَّع ⁦Blob⁩ إلى ⁦File⁩ عند إلحاقه. ويستبدل ⁦set()⁩ أول مدخل مطابق ويحذف المكررات اللاحقة.

أجسام ⁦Request⁩ و⁦Response⁩

تكشف كلتا الفئتين ⁦body⁩ و⁦bodyUsed⁩ و⁦arrayBuffer()⁩ و⁦blob()⁩ و⁦bytes()⁩ و⁦formData()⁩ و⁦json()⁩ و⁦text()⁩.

تشمل مدخلات الأجسام المدعومة السلاسل النصية وكائنات ⁦Blob⁩ ومصادر المخازن المؤقتة و⁦FormData⁩ و⁦URLSearchParams⁩ و⁦ReadableStream⁩. وترفض طلبات ⁦GET⁩ و⁦HEAD⁩ أي جسم غير فارغ. ويتطلب جسم الطلب المتدفق ⁦duplex: "half"⁩.

const request = new Request("https://example.invalid/", {
  method: "POST",
  body: "hello",
});
await request.text(); // "hello"

const response = Response.json({ ok: true });
await response.json(); // { ok: true }

يجب أن تكون عناوين ⁦URL⁩ للطلبات مطلقة. وتقتصر حالات مُنشئ ⁦Response⁩ على 200–599. ويتطلب ⁦Response.redirect()⁩ أيضًا عنوان ⁦URL⁩ مطلقًا. وتتوفر ⁦Response.error()⁩ و⁦Response.redirect()⁩ و⁦Response.json()⁩ و ⁦clone()⁩.

fetch

يقبل ⁦fetch(input, init?)⁩ عنوان ⁦URL⁩ أو سلسلة ⁦URL⁩ أو ⁦Request⁩ ويعيد ⁦Promise⁩ يُحَل عند وصول ترويسات الاستجابة. وجسم الاستجابة ⁦ReadableStream⁩: إذ تصبح الأجزاء متاحة قبل أن ينتهي الخادم من إرسال الاستجابة. وتستهلك توابع مثل ⁦response.text()⁩ التدفق حتى نهايته.

يمكن أن تكون أجسام الطلبات تدفقات أيضًا. وإلغاء جسم استجابة يغلق تدفقها الشبكي؛ ويمكن لـ ⁦AbortSignal⁩ إلغاء الإرسال أو قراءات الجسم اللاحقة. وتُطبَّق أوضاع إعادة التوجيه وبيانات السلامة الوصفية أثناء الإرسال. ويخزّن التحقق من السلامة حتى 100 ⁦MiB⁩ مؤقتًا ويكتمل قبل كشف الاستجابة.

تُفك ترميزات استجابات ⁦Gzip⁩ و⁦deflate⁩ مرة واحدة مع الاحتفاظ بترويسات الاستجابة. ويتحقق ⁦HTTPS⁩ من سلاسل الشهادات وأسماء المضيفين افتراضيًا؛ وإعدادات الثقة الإضافية مدرجة في متغيرات بيئة التشغيل.

يتحدث ⁦fetch⁩ ‏⁦HTTP/1.1⁩ و⁦HTTP/2⁩ عبر طبقة النقل الأصلية في ⁦Elide⁩. استخدم ⁦elide info⁩ لفحص طبقة النقل ومزوّد ⁦TLS⁩ المختارين. وتُدعم وكلاء ⁦HTTP⁩ التي يختارها ⁦ProxySelector⁩ الخاص بالمضيف، بما في ذلك ⁦HTTPS CONNECT⁩. أما الوكلاء التي تتطلب مصادقة و أنواع الوكلاء غير المدعومة فتفشل صراحة.

الضغط موثَّق بشكل منفصل في تدفقات الضغط. وتنتمي خيارات خادم ⁦HTTP⁩ و دورة حياته إلى مرجع الكائن العام ⁦Elide⁩.

افتراضيات ⁦HTTP⁩ والضغط

يرسل ⁦Fetch⁩ ‏⁦User-Agent: Elide/<version>⁩ و⁦Accept: */*⁩. تجاوز أيًّا منهما بترويسات طلب عادية:

await fetch(url, { headers: { "User-Agent": "my-service/1.0" } });

اضبط ⁦ELIDE_HTTP_USER_AGENT⁩ لتغيير القيمة الافتراضية للعملية. ويمكن لمضمِّني ⁦JVM⁩ استخدام خاصية النظام ⁦elide.http.userAgent⁩؛ ولها الأسبقية على البيئة. وللترويسة الخاصة بكل طلب الأسبقية على أيٍّ من الإعدادين. ويجب أن تكون القيم المضبوطة أحرف ⁦ASCII⁩ قابلة للطباعة.

يعلن ⁦Fetch⁩ عن ⁦gzip⁩ و⁦deflate⁩ و⁦Brotli⁩ و⁦Zstandard⁩ ويفك ترميزها باستخدام برامج الترميز المتاحة في بيئة التشغيل. ويعلن بديل الضغط المقتصر على ⁦JDK⁩ عن ⁦gzip⁩ و⁦deflate⁩. وتُحفظ ترويسات ⁦Accept-Encoding⁩ الصريحة. والقيمة الافتراضية لطلبات النطاق هي ⁦identity⁩. وتصف ترويسات الاستجابة الاستجابة المرمّزة حتى بعد فك ترميز الجسم.

const response = await fetch(url, { decompress: false });
const encodedBytes = await response.arrayBuffer();

مع ⁦decompress: false⁩، تكون قيمة ⁦Accept-Encoding⁩ الافتراضية ⁦identity⁩؛ والخادم الذي يظل يرسل محتوى مضغوطًا يُعاد محتواه دون تغيير. وهذا مفيد عند تمرير الاستجابات المرمّزة عبر وكيل. وفي غير ذلك يبقى فك الترميز التلقائي متدفقًا ويرفض الأجسام المضغوطة المشوّهة.

تُرسل الترويسات الشرطية مثل ⁦If-None-Match⁩ و⁦If-Modified-Since⁩ بشكل عادي. وتحتفظ استجابة ⁦304⁩ بترويساتها ولا جسم لها؛ ولا يحتفظ ⁦fetch⁩ بذاكرة ⁦HTTP⁩ مؤقتة على غرار المتصفحات.

عند التقديم، تبقى الاستجابات المرمّزة تحت تحكم التطبيق: أرسل الجسم المرمّز مع ⁦Content-Encoding⁩ الخاص به، واستخدم ⁦Vary: Accept-Encoding⁩ عند التفاوض على التمثيلات. ولا يعيد ⁦Elide⁩ ضغط أجسام الاستجابات بصمت.

Reference

Status: Full · 1,455 of 2,511 suite tests pass (57.9%) · since 1.1.0

Exports

ExportKindStatusNotes
HeadersclassFullappend(), delete(), get(), getSetCookie(), has(), set(), iteration
RequestclassFullmethod, url, headers, destination, referrer, referrerPolicy, mode, credentials, cache, redirect, integrity, keepalive, signal, duplex, clone(), body, bodyUsed, arrayBuffer(), blob(), bytes(), formData(), json(), text()
ResponseclassFullResponse.error(), Response.redirect(), Response.json(), type, url, redirected, status, ok, statusText, headers, clone(), body, bodyUsed, arrayBuffer(), blob(), bytes(), formData(), json(), text()
BlobclassFullsize, type, slice(), text(), arrayBuffer(), bytes(), stream()
FileclassFullname, lastModified
FormDataclassFullappend(), delete(), get(), getAll(), has(), set(), iteration

Tests: wpt-wintertc fetch: 1,455 pass, 1,043 fail, 13 error, 400 skipped. Failing: fetch/api/basic/request-forbidden-headers.any.js (96), fetch/api/redirect/redirect-referrer-override.any.js (91), fetch/data-urls/processing.any.js (68), fetch/api/headers/header-values-normalize.any.js (57), fetch/api/cors/cors-keepalive.any.js (51), fetch/api/cors/cors-preflight-star.any.js (34), fetch/api/redirect/redirect-origin.any.js (30), fetch/api/cors/cors-preflight-status.any.js (27), and 110 more.

هل كانت هذه الصفحة مفيدة؟