يوفر Bun واجهات برمجة تطبيقات أصلية للتعامل مع ملفات تعريف الارتباط HTTP من خلال Bun.Cookie و Bun.CookieMap. توفر واجهات برمجة التطبيقات هذه طرقًا سريعة وسهلة الاستخدام لتحليل وإنشاء والتلاعب بملفات تعريف الارتباط في طلبات واستجابات HTTP.
فئة CookieMap
يوفر Bun.CookieMap واجهة شبيهة بـ Map للتعامل مع مجموعات ملفات تعريف الارتباط. يطبق واجهة Iterable، مما يسمح لك باستخدامه مع حلقات for...of وطرق التكرار الأخرى.
// خريطة ملفات تعريف ارتباط فارغة
const cookies = new Bun.CookieMap();
// من سلسلة ملف تعريف ارتباط
const cookies1 = new Bun.CookieMap("name=value; foo=bar");
// من كائن
const cookies2 = new Bun.CookieMap({
session: "abc123",
theme: "dark",
});
// من مصفوفة أزواج الاسم/القيمة
const cookies3 = new Bun.CookieMap([
["session", "abc123"],
["theme", "dark"],
]);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
في خوادم HTTP
في خادم HTTP الخاص بـ Bun، خاصية cookies في كائن الطلب (في routes) هي مثيل من CookieMap:
const server = Bun.serve({
routes: {
"/": req => {
// الوصول إلى ملفات تعريف ارتباط الطلب
const cookies = req.cookies;
// الحصول على ملف تعريف ارتباط محدد
const sessionCookie = cookies.get("session");
if (sessionCookie != null) {
console.log(sessionCookie);
}
// التحقق من وجود ملف تعريف ارتباط
if (cookies.has("theme")) {
// ...
}
// تعيين ملف تعريف ارتباط، سيتم تطبيقه تلقائيًا على الاستجابة
cookies.set("visited", "true");
return new Response("Hello");
},
},
});
console.log("الخادم يستمع على: " + server.url);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
الطرق
get(name: string): string | null
يسترجع ملف تعريف ارتباط بالاسم. يُرجع null إذا لم يكن ملف تعريف الارتباط موجودًا.
// الحصول بالاسم
const cookie = cookies.get("session");
if (cookie != null) {
console.log(cookie);
}2
3
4
5
6
has(name: string): boolean
يتحقق من وجود ملف تعريف ارتباط بالاسم المعطى.
// التحقق من وجود ملف تعريف الارتباط
if (cookies.has("session")) {
// ملف تعريف الارتباط موجود
}2
3
4
set(name: string, value: string): void
set(options: CookieInit): void
set(cookie: Cookie): void
يضيف أو يحدث ملف تعريف ارتباط في الخريطة. ملفات تعريف الارتباط الافتراضية { path: "/", sameSite: "lax" }.
// التعيين بالاسم والقيمة
cookies.set("session", "abc123");
// التعيين باستخدام كائن الخيارات
cookies.set({
name: "theme",
value: "dark",
maxAge: 3600,
secure: true,
});
// التعيين باستخدام مثيل Cookie
const cookie = new Bun.Cookie("visited", "true");
cookies.set(cookie);2
3
4
5
6
7
8
9
10
11
12
13
14
delete(name: string): void
delete(options: CookieStoreDeleteOptions): void
يزيل ملف تعريف ارتباط من الخريطة. عند تطبيقه على استجابة، يضيف هذا ملف تعريف ارتباط بقيمة سلسلة فارغة وتاريخ انتهاء في الماضي. سيتم حذف ملف تعريف الارتباط بنجاح على المتصفح فقط إذا كان النطاق والمسار نفسهما عندما تم إنشاء ملف تعريف الارتباط.
// الحذف بالاسم باستخدام النطاق والمسار الافتراضيين.
cookies.delete("session");
// الحذف مع خيارات النطاق/المسار.
cookies.delete({
name: "session",
domain: "example.com",
path: "/admin",
});2
3
4
5
6
7
8
9
toJSON(): Record<string, string>
يحول خريطة ملفات تعريف الارتباط إلى تنسيق قابل للتسلسل.
const json = cookies.toJSON();toSetCookieHeaders(): string[]
يُرجع مصفوفة من قيم رؤوس Set-Cookie التي يمكن استخدامها لتطبيق جميع تغييرات ملفات تعريف الارتباط.
عند استخدام Bun.serve()، لا تحتاج إلى استدعاء هذه الطريقة صراحةً. أي تغييرات تُجرى على خريطة req.cookies يتم تطبيقها تلقائيًا على رؤوس الاستجابة. هذه الطريقة مفيدة بشكل أساسي عند العمل مع تطبيقات خادم HTTP الأخرى.
import { createServer } from "node:http";
import { CookieMap } from "bun";
const server = createServer((req, res) => {
const cookieHeader = req.headers.cookie || "";
const cookies = new CookieMap(cookieHeader);
cookies.set("view-count", Number(cookies.get("view-count") || "0") + 1);
cookies.delete("session");
res.writeHead(200, {
"Content-Type": "text/plain",
"Set-Cookie": cookies.toSetCookieHeaders(),
});
res.end(`تم العثور على ${cookies.size} ملفات تعريف ارتباط`);
});
server.listen(3000, () => {
console.log("الخادم يعمل على http://localhost:3000/");
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
التكرار
يوفر CookieMap عدة طرق للتكرار:
// التكرار على إدخالات [name, cookie]
for (const [name, value] of cookies) {
console.log(`${name}: ${value}`);
}
// استخدام entries()
for (const [name, value] of cookies.entries()) {
console.log(`${name}: ${value}`);
}
// استخدام keys()
for (const name of cookies.keys()) {
console.log(name);
}
// استخدام values()
for (const value of cookies.values()) {
console.log(value);
}
// استخدام forEach
cookies.forEach((value, name) => {
console.log(`${name}: ${value}`);
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
الخصائص
size: number
يُرجع عدد ملفات تعريف الارتباط في الخريطة.
console.log(cookies.size); // عدد ملفات تعريف الارتباطفئة Cookie
يمثل Bun.Cookie ملف تعريف ارتباط HTTP مع اسمه وقيمته وسماته.
import { Cookie } from "bun";
// إنشاء ملف تعريف ارتباط أساسي
const cookie = new Bun.Cookie("name", "value");
// إنشاء ملف تعريف ارتباط مع خيارات
const secureSessionCookie = new Bun.Cookie("session", "abc123", {
domain: "example.com",
path: "/admin",
expires: new Date(Date.now() + 86400000), // يوم واحد
httpOnly: true,
secure: true,
sameSite: "strict",
});
// التحليل من سلسلة ملف تعريف ارتباط
const parsedCookie = new Bun.Cookie("name=value; Path=/; HttpOnly");
// إنشاء من كائن خيارات
const objCookie = new Bun.Cookie({
name: "theme",
value: "dark",
maxAge: 3600,
secure: true,
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
المنشئات
// المنشئ الأساسي مع الاسم/القيمة
new Bun.Cookie(name: string, value: string);
// المنشئ مع الاسم والقيمة والخيارات
new Bun.Cookie(name: string, value: string, options: CookieInit);
// المنشئ من سلسلة ملف تعريف ارتباط
new Bun.Cookie(cookieString: string);
// المنشئ من كائن ملف تعريف ارتباط
new Bun.Cookie(options: CookieInit);2
3
4
5
6
7
8
9
10
11
الخصائص
cookie.name; // string - اسم ملف تعريف الارتباط
cookie.value; // string - قيمة ملف تعريف الارتباط
cookie.domain; // string | null - نطاق النطاق (null إذا لم يتم تحديده)
cookie.path; // string - نطاق مسار URL (الافتراضي "/")
cookie.expires; // number | undefined - طابع زمني للانتهاء (مللي ثانية منذ العصر)
cookie.secure; // boolean - تطلب HTTPS
cookie.sameSite; // "strict" | "lax" | "none" - إعداد SameSite
cookie.partitioned; // boolean - ما إذا كان ملف تعريف الارتباط مقسمًا (CHIPS)
cookie.maxAge; // number | undefined - العمر الأقصى بالثواني
cookie.httpOnly; // boolean - يمكن الوصول إليه عبر HTTP فقط (ليس JavaScript)2
3
4
5
6
7
8
9
10
الطرق
isExpired(): boolean
يتحقق مما إذا كان ملف تعريف الارتباط قد انتهى.
// ملف تعريف ارتباط منتهي (التاريخ في الماضي)
const expiredCookie = new Bun.Cookie("name", "value", {
expires: new Date(Date.now() - 1000),
});
console.log(expiredCookie.isExpired()); // true
// ملف تعريف ارتباط صالح (استخدام maxAge بدلاً من expires)
const validCookie = new Bun.Cookie("name", "value", {
maxAge: 3600, // ساعة واحدة بالثواني
});
console.log(validCookie.isExpired()); // false
// ملف تعريف ارتباط الجلسة (بدون انتهاء)
const sessionCookie = new Bun.Cookie("name", "value");
console.log(sessionCookie.isExpired()); // false2
3
4
5
6
7
8
9
10
11
12
13
14
15
serialize(): string
toString(): string
يُرجع تمثيلًا نصيًا لملف تعريف الارتباط مناسبًا لرأس Set-Cookie.
const cookie = new Bun.Cookie("session", "abc123", {
domain: "example.com",
path: "/admin",
expires: new Date(Date.now() + 86400000),
secure: true,
httpOnly: true,
sameSite: "strict",
});
console.log(cookie.serialize());
// => "session=abc123; Domain=example.com; Path=/admin; Expires=Sun, 19 Mar 2025 15:03:26 GMT; Secure; HttpOnly; SameSite=strict"
console.log(cookie.toString());
// => "session=abc123; Domain=example.com; Path=/admin; Expires=Sun, 19 Mar 2025 15:03:26 GMT; Secure; HttpOnly; SameSite=strict"2
3
4
5
6
7
8
9
10
11
12
13
toJSON(): CookieInit
يحول ملف تعريف الارتباط إلى كائن عادي مناسب لتسلسل JSON.
const cookie = new Bun.Cookie("session", "abc123", {
secure: true,
httpOnly: true,
});
const json = cookie.toJSON();
// => {
// name: "session",
// value: "abc123",
// path: "/",
// secure: true,
// httpOnly: true,
// sameSite: "lax",
// partitioned: false
// }
// يعمل مع JSON.stringify
const jsonString = JSON.stringify(cookie);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
الطرق الثابتة
Cookie.parse(cookieString: string): Cookie
تحلل سلسلة ملف تعريف ارتباط إلى مثيل Cookie.
const cookie = Bun.Cookie.parse("name=value; Path=/; Secure; SameSite=Lax");
console.log(cookie.name); // "name"
console.log(cookie.value); // "value"
console.log(cookie.path); // "/"
console.log(cookie.secure); // true
console.log(cookie.sameSite); // "lax"2
3
4
5
6
7
Cookie.from(name: string, value: string, options?: CookieInit): Cookie
طريقة المصنع لإنشاء ملف تعريف ارتباط.
const cookie = Bun.Cookie.from("session", "abc123", {
httpOnly: true,
secure: true,
maxAge: 3600,
});2
3
4
5
الأنواع
interface CookieInit {
name?: string;
value?: string;
domain?: string;
/** الافتراضي '/'. للسماح للمتصفح بتعيين المسار، استخدم سلسلة فارغة. */
path?: string;
expires?: number | Date | string;
secure?: boolean;
/** الافتراضي `lax`. */
sameSite?: CookieSameSite;
httpOnly?: boolean;
partitioned?: boolean;
maxAge?: number;
}
interface CookieStoreDeleteOptions {
name: string;
domain?: string | null;
path?: string;
}
interface CookieStoreGetOptions {
name?: string;
url?: string;
}
type CookieSameSite = "strict" | "lax" | "none";
class Cookie {
constructor(name: string, value: string, options?: CookieInit);
constructor(cookieString: string);
constructor(cookieObject?: CookieInit);
readonly name: string;
value: string;
domain?: string;
path: string;
expires?: Date;
secure: boolean;
sameSite: CookieSameSite;
partitioned: boolean;
maxAge?: number;
httpOnly: boolean;
isExpired(): boolean;
serialize(): string;
toString(): string;
toJSON(): CookieInit;
static parse(cookieString: string): Cookie;
static from(name: string, value: string, options?: CookieInit): Cookie;
}
class CookieMap implements Iterable<[string, string]> {
constructor(init?: string[][] | Record<string, string> | string);
get(name: string): string | null;
toSetCookieHeaders(): string[];
has(name: string): boolean;
set(name: string, value: string, options?: CookieInit): void;
set(options: CookieInit): void;
delete(name: string): void;
delete(options: CookieStoreDeleteOptions): void;
delete(name: string, options: Omit<CookieStoreDeleteOptions, "name">): void;
toJSON(): Record<string, string>;
readonly size: number;
entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
forEach(callback: (value: string, key: string, map: CookieMap) => void): void;
[Symbol.iterator](): IterableIterator<[string, string]>;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77