# الجلسات

تتيح لك الجلسات الاحتفاظ ببيانات المستخدم عبر طلبات متعددة. تعمل الجلسات عبر إنشاء وإرجاع ملف تعريف ارتباط فريد جنبًا إلى جنب مع استجابة HTTP عند تهيئة جلسة جديدة. ستكتشف المتصفحات هذا الملف تلقائيًا وتضمّنه في الطلبات المستقبلية. يتيح هذا لـ Vapor استعادة جلسة مستخدم محدد تلقائيًا في معالِج الطلب لديك.

تُعد الجلسات ممتازة لتطبيقات الويب الأمامية (front-end) المبنية بـ Vapor التي تخدم HTML مباشرةً إلى متصفحات الويب. أما بالنسبة لواجهات برمجة التطبيقات (APIs)، فنوصي باستخدام [المصادقة القائمة على الرموز (token-based authentication)](../security/authentication.md) عديمة الحالة (stateless) للاحتفاظ ببيانات المستخدم عبر الطلبات.

## الإعداد

لاستخدام الجلسات في مسار، يجب أن يمر الطلب عبر `SessionsMiddleware`. أسهل طريقة لتحقيق ذلك هي إضافة هذه الوسيطة على المستوى العام. يُوصى بإضافتها بعد تصريح مصنع ملفات تعريف الارتباط (cookie factory). ذلك لأن `Sessions` هو هيكل (struct)، وبالتالي فهو نوع قيمة (value type) وليس نوع مرجعية (reference type). وبما أنه نوع قيمة، يجب ضبط القيمة قبل استخدام `SessionsMiddleware`.

```swift
app.middleware.use(app.sessions.middleware)
```

إذا كان مجموعة فرعية فقط من مساراتك تستخدم الجلسات، فيمكنك بدلًا من ذلك إضافة `SessionsMiddleware` إلى مجموعة مسارات (route group).

```swift
let sessions = app.grouped(app.sessions.middleware)
```

يمكن إعداد ملف تعريف الارتباط الخاص بـ HTTP الذي تُنشئه الجلسات باستخدام `app.sessions.configuration`. يمكنك تغيير اسم ملف تعريف الارتباط والتصريح بدالة مخصصة لتوليد قيم ملفات تعريف الارتباط.

```swift
// Change the cookie name to "foo".
app.sessions.configuration.cookieName = "foo"

// Configures cookie value creation.
app.sessions.configuration.cookieFactory = { sessionID in
    .init(string: sessionID.string, isSecure: true)
}

app.middleware.use(app.sessions.middleware)
```

افتراضيًا، سيستخدم Vapor `vapor_session` كاسم لملف تعريف الارتباط.

## المُشغِّلات (Drivers)

تكون مُشغِّلات الجلسات مسؤولة عن تخزين واسترجاع بيانات الجلسة بواسطة المُعرِّف (identifier). يمكنك إنشاء مُشغِّلات مخصصة عبر التوافق مع بروتوكول `SessionDriver`.

!!! warning "تحذير"
    يجب إعداد مُشغِّل الجلسة _قبل_ إضافة `app.sessions.middleware` إلى تطبيقك.

### في الذاكرة (In-Memory)

يستخدم Vapor جلسات في الذاكرة افتراضيًا. تتطلب الجلسات في الذاكرة إعدادًا صفريًا ولا تُحفظ بين عمليات إطلاق التطبيق مما يجعلها ممتازة للاختبار. لتفعيل الجلسات في الذاكرة يدويًا، استخدم `.memory`:

```swift
app.sessions.use(.memory)
```

لحالات استخدام الإنتاج، ألقِ نظرة على مُشغِّلات الجلسات الأخرى التي تستخدم قواعد البيانات للاحتفاظ بالجلسات ومشاركتها عبر نسخ متعددة من تطبيقك.

### Fluent

يتضمن Fluent دعمًا لتخزين بيانات الجلسة في قاعدة بيانات تطبيقك. يفترض هذا القسم أنك قد [أعددت Fluent](../fluent/overview.md) ويمكنك الاتصال بقاعدة بيانات. الخطوة الأولى هي تفعيل مُشغِّل جلسات Fluent.

```swift
import Fluent

app.sessions.use(.fluent)
```

سيؤدي هذا إلى ضبط الجلسات لاستخدام قاعدة البيانات الافتراضية للتطبيق. لتحديد قاعدة بيانات معينة، مرّر مُعرِّف قاعدة البيانات.

```swift
app.sessions.use(.fluent(.sqlite))
```

أخيرًا، أضف ترحيل (migration) `SessionRecord` إلى ترحيلات قاعدة بياناتك. سيُهيّئ هذا قاعدة بياناتك لتخزين بيانات الجلسة في المخطط `_fluent_sessions`.

```swift
app.migrations.add(SessionRecord.migration)
```

تأكد من تشغيل ترحيلات تطبيقك بعد إضافة الترحيل الجديد. ستُخزَّن الجلسات الآن في قاعدة بيانات تطبيقك مما يتيح لها الاحتفاظ بها بين عمليات إعادة التشغيل ومشاركتها بين نسخ متعددة من تطبيقك.

### Redis

يوفر Redis دعمًا لتخزين بيانات الجلسة في نسخة Redis التي أعددتها. يفترض هذا القسم أنك قد [أعددت Redis](../redis/overview.md) ويمكنك إرسال أوامر إلى نسخة Redis.

لاستخدام Redis للجلسات، اخترها عند إعداد تطبيقك:

```swift
import Redis

app.sessions.use(.redis)
```

سيؤدي هذا إلى ضبط الجلسات لاستخدام مُشغِّل جلسات Redis بالسلوك الافتراضي.

!!! seealso "انظر أيضًا"
    راجع [Redis &rarr; Sessions](../redis/sessions.md) لمزيد من المعلومات التفصيلية حول Redis والجلسات.

## بيانات الجلسة

الآن بعد أن أُعدّت الجلسات، أصبحت جاهزًا للاحتفاظ بالبيانات بين الطلبات. تُهيَّأ الجلسات الجديدة تلقائيًا عند إضافة بيانات إلى `req.session`. يقبل معالِج المسار في المثال أدناه معامل مسار ديناميكيًا ويضيف القيمة إلى `req.session.data`.

```swift
app.get("set", ":value") { req -> HTTPStatus in
    req.session.data["name"] = req.parameters.get("value")
    return .ok
}
```

استخدم الطلب التالي لتهيئة جلسة بالاسم Vapor.

```http
GET /set/vapor HTTP/1.1
content-length: 0
```

يجب أن تتلقى استجابة مشابهة لما يلي:

```http
HTTP/1.1 200 OK
content-length: 0
set-cookie: vapor-session=123; Expires=Fri, 10 Apr 2020 21:08:09 GMT; Path=/
```

لاحظ أن ترويسة `set-cookie` قد أُضيفت تلقائيًا إلى الاستجابة بعد إضافة البيانات إلى `req.session`. سيؤدي تضمين ملف تعريف الارتباط هذا في الطلبات اللاحقة إلى إتاحة الوصول إلى بيانات الجلسة.

أضف معالِج المسار التالي للوصول إلى قيمة الاسم من الجلسة.

```swift
app.get("get") { req -> String in
    req.session.data["name"] ?? "n/a"
}
```

استخدم الطلب التالي للوصول إلى هذا المسار مع التأكد من تمرير قيمة ملف تعريف الارتباط من الاستجابة السابقة.

```http
GET /get HTTP/1.1
cookie: vapor-session=123
```

يجب أن ترى الاسم Vapor مُعادًا في الاستجابة. يمكنك إضافة البيانات إلى الجلسة أو إزالتها منها حسبما تراه مناسبًا. ستُزامَن بيانات الجلسة مع مُشغِّل الجلسة تلقائيًا قبل إرجاع استجابة HTTP.

لإنهاء جلسة، استخدم `req.session.destroy`. سيؤدي هذا إلى حذف البيانات من مُشغِّل الجلسة وإبطال ملف تعريف الارتباط الخاص بالجلسة.

```swift
app.get("del") { req -> HTTPStatus in
    req.session.destroy()
    return .ok
}
```
