التعامل مع الـ API
السلام عليكم ورحمة الله وبركاته
الفهرس
- المقدمة
- تجهيز قاعدة بيانات افتراضية مع API
- Methods / Actions
- Query
- كيف نقوم بعمل Query على الـ API ؟
- عمل Query بأكثر من شرط
- sort=value - ترتيب بيانات الـ Query
- fields=value1, value2 - اختيار خانات معينة
- page=n&limit=m - تقييد عدد النواتج
- إرسال Array و Object في الـ Query
- هل هذا كل شيء في الـ Query ؟
- Headers
المقدمة
في مقالة مفهوم الـ API قمنا بإعطاء نبذة عن ما هو الـ API
واعطينا مثال لكيفية التعامل معها
هنا سأحاول ان ادخل في تفاصيل أخرى في التعامل مع الـ API
في المثال الخاص بمقالة مفهوم الـ API استخدما الـ API
لإحضار بعض البيانات
هل هذا ما يفعله الـ API
فقط ؟
بالطبع لا، الـ API
كما قلنا هو الوسيط بينك وبين مصدر البيانات او الـ Server
بشكل عام
في الحياة الواقعية او في مجال العمل وليكن مجال الويب سيكون الـ API
الوسيط بين الـ Frontend
والـ Backend
- الـ
Backend
هو المسؤول عن الـServer
المسؤول عن تخزين البيانات ويصممAPI
- الـ
Frontend
يستخدم هذا الـAPI
ليقوم بإحضار بيانات او إضافة بيانات او تعديلها او حذفها
تجهيز قاعدة بيانات افتراضية مع API
فلنفترض ان صديقنا الـ Backend
اعطانا رابط API
افتراضي وليكن https//database.api/users
وقاعدة البيانات تحتوي على الآتي:-
{
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]"
},
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]"
}
]
}
على الـ Backend
ان يعطيك شرح تفصيلي لكيفية استخدام هذا الـ API
فلنفترض انه اخبرنا عن الـ endpoints
التي سيخدمها الـ Frontend
ليتعامل مع الـ API
ولتكن هكذا:-
- Get all users
endpoint: 'https://database.api/users'
method: 'GET'
- Get one user
endpoint: 'https://database.api/users/:id'
method: 'GET'
- Add user
endpoint: 'https://database.api/users'
method: 'POST'
body: {name, age, email}
- Update user (entirely)
endpoint: 'https://database.api/users/:id'
method: 'PUT'
body: {name, age, email} // must send all
- Update user (partial)
endpoint: 'https://database.api/users/:id'
method: 'PATCH'
body: {name, age, email} // at least send one field
- Delete user
endpoint: 'https://database.api/users/:id'
method: 'DELETE'
الـ
Backend
المحترف هو من يستطيع كتابة شرح تفصيلي وواضح لكيفية استخدام هذا الـAPI
ولكي لا يتسبب بازمة قلبية للـFrontend
حين يتعامل معه
الـ endpoints
هي نهايات رابط الـ API
فعلى سبيل المثال ان اردت كل المستخدمين فيكون الـ endpoint
هو /users
وان اردت شخص معين فيكون الـ endpoint
هو /users/:id
وهكذا
الـ Backend
يحدد لك ويصف لك الـ endpoints
التي سيستخدمها الـ Frontend
ليتعامل مع الـ API
سنشرح كل شيء بالتفصيل اثناء الشرح وسنستخدم هذا الـ
API
الافتراضي اثناء الشرح
Methods / Actions
الـ methods
او احيانا تسمى actions
هي مجموعة من الوظائف او الأوامر التي تُمرَر للـ API
ليعرف ما هو طلبك، هل تريد إحضار شيء ؟ او إضافة شيء ؟ او تعديل شيء ؟ او حذف شيء ؟
نوع الطلب يحدده الـ method
سنستخدم لغة
javascript
للتطبيق العملي لا اكثر، لكن كل ما سنشرحه هنا من أمور ومفاهيم يمكنكم عمله في أي لغة اخرى
async function handleAPI() {
let url = 'https//database.api/users';
let obj = await fetch(url, {
method: 'GET', // tell the api to get data (default)
});
}
handleAPI();
هنا عن طريق الـ method
سيقوم الـ API
بتنفيذ الطلب المطلوب منه
ان لم تعطيه أي method
فالقيمة الافتراضية تكون GET
وانواع الـ method
كثيرة سنأخذ اهم 5
انواع أساسية وهم:-
method | وظيفته |
---|---|
GET | تستخدم لإحضار البيانات فقط |
POST | تستخدم لإضافة بيانات جديدة |
PUT | تستخدم للقيام باستبدال بيانات عنصر معين بشكل كامل |
PATCH | تستخدم للقيام بتعديل بيانات عنصر معين بشكل جزئي |
DELETE | تستخدم لحذف شيء او عنصر من قاعدة البيانات |
GET
نستخدمها لإحضار البيانات ولا تقوم باي تعديل او تغير في قيمة البيانات على الاطلاق
ولا يمكن ارسال أي بيانات من خلالها
ان كانت البيانات موجود فيكون رمز الحالة 200 أي ان البيانات تم إحضارها بنجاح،
وتكون القيمة الراجعة من طلب الـ API
هي البيانات المطلوبة
وان لم تكن البيانات موجود يكون رمز الحالة 404 أي ان البيانات غير موجودة والقيمة الراجعة تكون بها بيانات عن نوع الخطأ بالتفصيل وغالبا ما تكون رسالة تقول انه لم يجد البيانات
محتوى القيمة الراجعة يكتبه الـ Backend
بنفسه ويصف فيه نوع الخطأ، الأمر عائد اليه ليصف لك الحالة بالتفصيل حين يحدث أي خطأ اثناء التعامل مع الـ API
كيف يكون الأمر بشكل عملي ؟
سنستعمل قاعدة البيانات الافتراضية التي انشأناها
وقلنا ان صديقنا الـ Backend
اعطانا الـ API
لها وهو https//database.api/users
انت كـ Frontend
تقوم باستخدام الـ API
لإحضار البيانات
تريد كل المستخدمين ؟ علينا الرجوع للتعليمات او الارشادات التي كتبها لنا الـ Backend
لنستخدم الـ API
- Get all users
endpoint: 'https://database.api/users'
method: 'GET'
هنا سنجد انه يقول لنا لكي نحضر كل المستخدمين نستخدم الـ endpoint
وهو https://database.api/users
و method
يجب ان يكون نوعه GET
async function handleAPI() {
let url = 'https//database.api/users'; // /users endpoint to get all users
let obj = await fetch(url, {
method: 'GET', // tell the api to get data (default)
});
let data = await obj.json();
console.log(data);
}
handleAPI();
الرد سيكون بيانات كل المستخدمين في قاعدة البيانات
والحالة ستكون 200
لان البيانات موجودة وتم إحضارها بنجاح
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]"
},
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]"
}
]
}
الـ
Backend
هو أيضًا المسؤول عن شكل البيانات الراجعة للـFrontend
وهنا كما نرى انه ارسل لنا بيانات زائدة لوصف وتوضيح البيانات مثلstatus, code, message
بجانب الـusers
تريد مستخدم معين ؟
- Get one user
endpoint: 'https://database.api/users/:id'
method: 'GET'
هنا ستجد ان الـ endpoint
يحتوي على :id
ومعنى هذا انه متغير يمكن ان يحتوي على أي رقم
والـ method
يجب ان يكون نوعه GET
async function handleAPI() {
let url = 'https//database.api/users/2'; // /users/:id endpoint to get user with id 2
let obj = await fetch(url, {
method: 'GET', // tell the api to get data (default)
});
let data = await obj.json();
console.log(data);
}
handleAPI();
الناتج سيكون المستخدم صاحب الـ id
رقم 2
{
"status": "success",
"code": 200,
"message": "User found",
"user": {
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]"
}
}
ان طلبت مستخدم غير موجود ؟
async function handleAPI() {
let url = 'https//database.api/users/4'; // user that doesn't exist
let obj = await fetch(url, {
method: 'GET',
});
let data = await obj.json();
console.log(data);
}
handleAPI();
الناتج سيكون بيانات عن نوع الخطأ بالتفصيل يكتبها الـ Backend
بنفسه ويصف فيه نوع الخطأ كما ذكرنا
{
"status": "error",
"code": 404,
"message": "User not found"
}
ملخص ما تعلمناه هو:
- الـ
Backend
يقوم بعمل الـAPI
ويحدد كيف نستخدمه وما محتوى البيانات التي سنستقبلها سواء ان نجح الطلب او حدث أي خطأ - الـ
Frontend
يقوم بالتعامل مع تلك البيانات الرجعة من الـAPI
بما يتناسب معه
اهم رموز الحالة في الـ GET
200
(OK
): تم إحضار البيانات بنجاح404
(Not Found
): لم يتم العثور على البيانات المطلوبة
POST
نستخدمها عندما نريد إضافة بيانات جديدة في قاعدة البيانات خاصتنا
هنا عندما ترسل البيانات الجديدة من خلال الـ API
على سبيل المثال نريد إنشاء مستخدم جديد
ان نجح الإنشاء فسيكون رمز الحالة 201 أي انه تم إنشاء البيانات بنجاح
الـ POST
تستخدم أيضًا لارسال بيانات للـ Backend
بشكل عام وليس شرطا ان يكون بغرض إنشاء شيء ما كإنشاء مستخدم جديد مثلًا او تخزين البيانات
قد نريد ارسال بيانات للـ Backend
ليقوم بعمل بعض العمليات عليها لا غير
كيف نرسل البيانات من خلال الـ API ؟
ان فكرت في الأمر فالـ Frontend
عندما يريد ان ينشيء مستخدم جديد في قاعدة البيانات
فعليه ان يقوم بإرسال البيانات الجديدة إلى الـ Backend
بطريقة ما من خلال الـ API
هنا يأتي الـ body
وهو حرفيا كما يوحي الإسم جسم الطلب الذي نخزن فيه البيانات التي نريد ارسالها مع الطلب إلى الـ Backend
ليتعامل معها
كيف يكون الأمر بشكل عملي ؟
لنرجع لارشادات صديقنا الـ Backend
- Add user
endpoint: 'https://database.api/users'
method: 'POST'
body: {name, age, email}
هنا سنلاحظ ان الـ endpoint
الخاص بإنشاء مستخدم جديد يشبه الـ endpoint
الخاص بإحضار جميع المستخدمين
والـ API
يفرق بين الـ endpoint
المتشابهه ويحدد نوع الطلب عن طريق الـ method
ان كان POST
فسيعرف انه يجب ان يقول للـ Backend
ان ينشيء مستخدم جديد وان كان GET
فسيعرف انه يجب ان يحصل على جميع المستخدمين
سنلاحظ انه يقول انه يحتاج body
مكون من name, age, email
والـ Backend
هو من يحدد ما البيانات التي يجب على الـ Frontend
ارسالها
async function handleAPI() {
let url = 'https//database.api/users';
let obj = await fetch(url, {
method: 'POST',
// send the data to the backend (json format)
body: JSON.stringify({
name: 'Osama',
age: 40,
email: '[email protected]',
}),
// headers contains extra information about the request
headers: {
'Content-Type': 'application/json',
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
لنحلل ما لدينا هنا، حددنا الـ endpoint
الخاص بإنشاء مستخدم جديد والـ method
جعلناها POST
الآن لدينا الـ body
يحتوي على البيانات التي نريد ارسالها للـ Backend
بصيغة json
// send the data to the backend (json format)
body: JSON.stringify({
name: 'Osama',
age: 40,
email: '[email protected]'
}),
يمكنك ان تحدد شكل وصيغة البيانات سواء نص عادي او json
وغيرها من الصيغ، هذا شيء يتفق عليه الـ Backend
معك
لكن غالب الأمر يكون بصيغة json
وهو الشكل المتعارف عليه في ارسال البيانات من الـ Frontend
إلى الـ Backend
الآن سنلاحظ شيء جديد ظهر معنا وهو الـ headers
// headers contains extra information about the request
headers: {
'Content-Type': 'application/json'
}
الـ headers
يحتوى على معلومات اضافية ترسل مع الطلب
من تلك المعلومات الاضافية لدينا Content-Type
نكتب فيه نوع البيانات التي ارسلناها للـ Backend
في الـ body
وبما ان البيانات نوعها json
نكتب application/json
هكذا وضحنا ان نوع البيانات سيكون json
يوجد قيم كثيرة لوصف البيانات في الـ Content-Type
بمختلف صيغها ومنها
سنتطرق لشرح مفصل عن الـ
headers
فيما بعد في هذه المقالة
ملحوظة
: الـContent-Type
نكتبه عندما نرسل بيانات في الـbody
مثل الـPOST
,PUT
,PATCH
او أي طلب يحتوى على بيانات سترسل إلى الـBackend
حسنًا بعد ان ارسلنا البيانات إلى الـ Backend
ستلاحظ اننا هنا نطبع قيمة راجعة من الطلب مع اننا فقط نرسل بيانات إلى الـ Backend
لا غير
let data = await obj.json();
console.log(data);
كما قلنا انه اذا نجح طلب الـ POST
او فشل كيف لنا ان نعرف ؟
هنا الـ Backend
يقوم بارجاع لنا معلومات توضح وتصف الحالة
في حالة النجاح سيكون ناتج الطباعة كهذا على سبيل المثال
{
"status": "success",
"code": 201,
"message": "User created successfully"
}
كما قلنا ان محتوى القيمة الراجعة والبيانات الموجودة بها الـ Backend
هو من يرسلها لنا لوصف ما حدث
اهم رموز الحالة في الـ POST
201
(Created
): تم إنشاء البيانات الجديدة بنجاح- ان ارسلنا بيانات للـ
Backend
فقط للقيام ببعض العمليات عليها لا غير فرموز الحالة ستكون كالأتي200
(OK
): تم تنفيذ العمليات بنجاح (دون القيام بإنشاء أي بيانات جديدة)
وسيرسل الـBackend
لنا البيانات الناتجة من تنفيذ تلك العملية204
(No Content
): تم تنفيذ العمليات بنجاح (دون القيام بإنشاء أي بيانات جديدة)
ولكن لم يرسل الـBackend
لنا أي بيانات خاصة بتلك العملية
- ان ارسلنا بيانات للـ
400
(Bad Request
): حدث خطأ في البيانات المرسلة للـBackend
الـFrontend
لم يرسل البيانات بشكل صحيح409
(Conflict
): لم تنجح عملية التعديل بسبب حصول تعارض أو تناقض في البيانات الجديدة والقديمة لسبب ما (وغالبا ما يكون السبب هو أنك تريد إضافة بيانات موجودة بالفعل)
PUT
نستخدمها عندما نريد ان نعدل بيانات عنصر ما في قاعدة البيانات
ان نجح التعديل فسيكون رمز الحالة 200 أي انه تم تعديل البيانات بنجاح وتخزينها
وان لم يكن هذا العنصر موجود فسيتم إنشاءه في قاعدة البيانات
اي ان PUT
يعمل عمل الـ POST
في حالة ان العنصر المراد تعديله غير موجود في قاعدة البيانات
كيف يكون الأمر بشكل عملي ؟
فلنفترض اننا نريد ان نعدل بيانات المستخدم رقم 1
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]"
}
فالنقل اننا نريد ان نغير العمر ونجعله 30
لنرجع لارشادات صديقنا الـ Backend
- Update user (entirely)
endpoint: 'https://database.api/users/:id'
method: 'PUT'
body: {name, age, email} // must send all
حسنًا الـ endpoint
يحتوى على :id
وهو رقم المستخدم الذي نريد تعديله
ثم سنلاحظ انه يقول انه يجب ان نرسل جميع بيانات المستخدم ان اردنا ان نعدل شيء
async function handleAPI() {
let url = 'https//database.api/users/1';
let obj = await fetch(url, {
method: 'PUT',
body: JSON.stringify({
name: 'Ahmed',
age: 30, // new value
email: '[email protected]',
}),
headers: {
'Content-Type': 'application/json',
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
هنا نكتب جميع بيانات المستخدم في الـ body
مع القيم الجديدة وفي حالتنا سنجعل العمر يساوي 30
نقول له ان الـ method
سيكون نوعه PUT
ثم نقوم بتحديد نوع البيانات في الـ Content-Type
ونجعلها application/json
{
"status": "success",
"code": 200,
"message": "User updated successfully",
"user": {
"id": 1,
"name": "Ahmed",
"age": 30,
"email": "[email protected]"
}
}
هنا الـ Backend
يقول انه تم تعديل البيانات بنجاح وتخزينها
وارسل لنا بيانات المستخدم الجديدة بعد التعديل
مشاكل حين نتعامل مع الـ PUT
ستلاحظ شيء هنا انه نحن فقط كنا نريد ان نعدل العمر لا غير، لكنا قمنا بارسال جميع البيانات
تخيل معي ان كانت قاعدة البيانات كبيرة والمستخدم يحتوى على بيانات متعددة منها الإسم والعمر والبريد الالكتروني والجنسية وعنوانه ومكان عمله وراتبه وغيرها...
ونحن نريد فقط تعديل شيء واحد فقط، ان استخدمنا الـ PUT
فيجب ان نرسل جميع البيانات كاملة
هذه قد تكون مشكلة كبيرة بحد ذاتها
وماذا سيحدث ان لم نرسل جميع البيانات في الـ body
؟
فالنقوم بعمل نفس الشيء لكن سنرسل في الـ body
فقط البيانات التي نريد تعديلها وهو الـ age: 30
body: JSON.stringify({
age: 30, // new value
}),
هل سيفشل الطلب ؟
لا الطلب سينجح لكن دعونا نرى الرد الذي ارسله الـ Backend
لنا
{
"status": "success",
"code": 200,
"message": "User updated successfully",
"user": {
"id": 1,
"age": 30
}
}
سنجد ان المستخدم لم يعد لديه إسم او بريد الكتروني
في حقيقة الأمر الـ PUT
يقوم باستبدال البيانات الجديدة المرسلة في الـ body
بالبيانات القديمة للمستخدم
يستبدلها بالكامل!، بالتالي ان ارسلنا بيانات ناقصة في الـ body
فلن يقوم بوضعها في البيانات الجديدة وسيقوم بحذفها بكل بساطة
بمعنى ان الـ
PUT
لا يقوم بعمل تعديل بشكل حرفي بل يقوم باستبدال كل البيانات القديمة بالجديدة
اهم رموز الحالة في الـ PUT
200
(OK
): تم تعديل البيانات بنجاح (او استبدالها بمعنى اصح)204
(No Content
): تم تعديل البيانات بنجاح ولكن لم يرسل الـBackend
لنا أي بيانات201
(Created
): تم إنشاء البيانات بنجاح (لانها لم تكن موجودة لذا تم إنشاءها)400
(Bad Request
): حدث خطأ في البيانات المرسلة للـBackend
الـFrontend
لم يرسل البيانات بشكل صحيح409
(Conflict
): لم تنجح عملية التعديل بسبب حصول تعارض أو تناقض في البيانات الجديدة والقديمة لسبب ما (وغالبا ما يكون السبب هو أنك تريد إضافة بيانات موجودة بالفعل)
PATCH
نستخدمها عندما نريد عن نعدل بيانات عنصر ما بشكل جزئي
وهي الطريقة الأكثر شيوعا للتعديل والموصى بها
بشرط ان يكون هذا العنصر موجود في قاعدة البيانات بالفعل
كيف يكون الأمر بشكل عملي ؟
الأمر سيكون مشابه للـ PUT
دعونا نرى ماذا يقول صديقنا الـ Backend
- Update user (partial)
endpoint: 'https://database.api/users/:id'
method: 'PATCH'
body: {name, age, email} // at least send one field
حسنًا الـ endpoint
يحتوى على :id
وهو رقم المستخدم الذي نريد تعديله
سنلاحظ انه يقول هنا انه على الاقل نرسل شيءً واحدًا
async function handleAPI() {
let url = 'https//database.api/users/1';
let obj = await fetch(url, {
method: 'PATCH',
body: JSON.stringify({
name: 'Ahmed_Tab', // new value
}),
headers: {
'Content-Type': 'application/json',
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
لاحظ اننا ارسلنا في الـ body
ما نريده تعديله وهو الإسم الجديد
هنا سيتم تعديل الإسم فقط لا غير
وباقي بيانات المستخدم ستظل كما هي ولن يتم مسحها كما حدث مع الـ PUT
رد الـ Backend
لنا سيكون كالتالي
{
"status": "success",
"code": 200,
"message": "User updated successfully",
"user": {
"id": 1,
"name": "Ahmed_Tab",
"age": 30,
"email": "[email protected]"
}
}
بما ان الـ Backend
ارجع لنا البيانات كاملة بهذا نتأكد انه لم يتم مسح أي بيانات قديمة
ملحوظة
: يفضل دائمًا عند التعديل استخدام الـPATCH
بدلًا من الـPUT
في حالة ضمان أن الذي تريد تعديله موجود في قاعدة البيانات بالفعل، لان الـPATCH
تتعامل مع ما هو موجود بالفعل، أما إن كان الذي تريد تعديله غير موجود فاستعمل الـPUT
أول الـPOST
وأرسل البيانات كامله لأنهما إن لم يجدا الشيء الذي تريد تعديله فسيقومان بإنشاءه من جديد
اهم رموز الحالة في الـ PATCH
200
(OK
): تم تعديل البيانات بنجاح204
(No Content
): تم تعديل البيانات بنجاح ولكن لم يرسل الـBackend
لنا أي بيانات400
(Bad Request
): حدث خطأ في البيانات المرسلة للـBackend
الـFrontend
لم يرسل البيانات بشكل صحيح409
(Conflict
): لم تنجح عملية التعديل بسبب حصول تعارض أو تناقض في البيانات الجديدة والقديمة لسبب ما (وغالبا ما يكون السبب هو أنك تريد إضافة بيانات موجودة بالفعل)
DELETE
بديهي ان نستخدم الـ DELETE
لحذف عنصر من قاعدة البيانات
لا يحتوى على body
بحكم انك تحذف بيانات ولا ترسل شيء للـ Backend
كيف يكون الأمر بشكل عملي ؟
بدأنا نعتاد على الأمر لانه اصبح يتكرر ومتشابه في العديد من الحالات
دعونا نرى ماذا يقول صديقنا الـ Backend
- Delete user
endpoint: 'https://database.api/users/:id'
method: 'DELETE'
هنا هو يريد فقط id
المستخدم الذي نريد حذفه
فالنقل اننا نريد حذف المستخدم رقم 1
async function handleAPI() {
let url = 'https//database.api/users/1';
let obj = await fetch(url, {
method: 'DELETE',
});
let data = await obj.json();
console.log(data);
}
لاحظ انه لا يوجد body
ولا حتى Content-Type
لاننا لا نرسل شيء وهذا شئ بديهي
ان نجح سيرسل لنا الـ Backend
بيانات انه تم الحذف بنجاح
{
"status": "success",
"code": 200,
"message": "User deleted successfully",
"user": {
"id": 1,
"name": "Ahmed_Tab",
"age": 30,
"email": "[email protected]"
}
}
اهم رموز الحالة في الـ DELETE
200
(OK
): تم حذف البيانات بنجاح204
(No Content
): تم حذف البيانات بنجاح ولكن لم يرسل الـBackend
لنا البيانات404
(Not Found
): لم يتم العثور على البيانات المطلوبة (اي انها محذوفة مسبقًا)
Query
حسنا ما هو الـ Query
؟
كما يوضح الإسم فأنك تستطيع عمل عمليات مخصصة للبيانات، على سبيل المثال نريد جميع الأشخاص الذي يعيشون في مصر
أو نريد الأشخاص الذي يزيد راتبهم عن 3000
أو الأشخاص الذي أعمارهم 25
عمليات مخصص ومحددة مثل هذه نسميها Query
لنفترض أن قاعدة البيانات خاصتنا أصبحت بهذا الشكل
{
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]",
"salary": 3000,
"country": "Palestine"
},
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]",
"salary": 4000,
"country": "Egypt"
},
{
"id": 4,
"name": "Omar",
"age": 35,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
},
{
"id": 5,
"name": "Osama",
"age": 30,
"email": "[email protected]",
"salary": 5000,
"country": "Palestine"
}
]
}
سوف نقوم باستكمال شرح الـ query
على قاعدة البيانات تلك
على نفس الرابط https//database.api/users
ملحوظة
: يجب على الـBackend
أن يجعل الـAPI
يمكن القيام بعملquery
عليه
لأنه ليس كلAPI
يقبل بالـquery
الأمر عائد للـBackend
ليجعله يقبل بالـquery
ام لا
كيف نقوم بعمل Query على الـ API ؟
نقوم بها عن طريق أننا نختار الـ endpoint
الذي نريد أن نقوم بعمل عليه عملية الـ query
ثم نكتب بعده علامة استفهام ?
ثم نكتب الـ query
الأمر يبدو كهذا /endpoint?key=value
يمكنك أن ترى تطبيقًا عمليا على هذا في محرك البحث جوجل
حاول أن تبحث عن كلمة تعلم البرمجة بالعربي
على سبيل المثال
أنظر الى الرابط ستجده هكذا
https://www.google.com.eg/search?q=تعلم+البرمجة+بالعربي
ستجد أن لديهم endpoint
تدعى search
ثم قام بعمل عليها query
هنا الـ key
هو q
والقيمة هى التي كتبناها في البحث تعلم البرمجة بالعربي
في حالتنا سيكون الـ users
ثم نكتب بعده علامة استفهام ?
ثم نكتب الـ query
ثم نكتب الـ query
مثال نريد الأشخاص الذين يعيشون في مصر سيكون شكل الـ query
هكذا
async function handleAPI() {
let url = 'https//database.api/users?country=Egypt'; // query
let obj = await fetch(url, {
method: 'GET',
});
let data = await obj.json();
console.log(data);
}
لاحظ أننا نقوم بعمل طلب عن طريق الـ API
بشكل اعتيادي
لكن في نهاية الـ endpoint
كتبنا الـ query
بعد الـ ?
هكذا users?country=Egypt
وهذا معناه كالأتي أحضر لي كل المستخدمين الذين في مصر
الناتج سيكون هكذا
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
},
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]",
"salary": 4000,
"country": "Egypt"
},
{
"id": 4,
"name": "Omar",
"age": 35,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
}
]
}
لاحظ انه أحضر فقط ثلاث أشخاص وهم الذين يعيشون في مصر فقط، لأنهم يحققون الشرط الذي وضعناه users?country=Egypt
لنقم بعمل مثال آخر أحضر الأشخاص الذي اعمارهم تساوي 30
سيكون الـ query
هكذا users?age=30
لا داعي لكتابة الكود لانك فهمت الأمر بالفعل
ناتج الـ query
سيكون هكذا
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]",
"salary": 3000,
"country": "Palestine"
},
{
"id": 5,
"name": "Osama",
"age": 30,
"email": "[email protected]",
"salary": 5000,
"country": "Palestine"
}
]
}
تم إحضار شخصين عمرهم 30
ويحققان الشرط بالفعل
عمل Query بأكثر من شرط
يمكننا ان نحدد أكثر من شرط عن طريق فصل كل شرط ب &
هكذا users?salary=3000&country=Palestine
الناتج
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]",
"salary": 3000,
"country": "Palestine"
}
]
}
تم إحضار الناتج الذي حقق الشروط
sort=value - ترتيب بيانات الـ Query
يمكننا في أثناء تنفيذنا لعملية الـ query
أن نطلب منه ان يترتب لنا البيانات تصاعديًا اوتنازليًا عن طريق كتابة كلمة sort
ثم نختار الحقل الذي سيترتب على أساسه
مثال users?sort=age
سيحضر جميع الأشخاص ويرتبهم تصاعديًا بحسب العمر
ان أردنا ترتيب تنازلي ؟ نقوم بوضع علامة -
هكذا users?sort=-age
سيحضر جميع الأشخاص ويرتبهم تنازليًا بحسب العمر
أحضر جميع الأشخاص الذي راتبهم يساوي 3000
ورتبهم تنازلي بحسب العمر
الـ query
ستكون هكذا users?salary=3000&sort=-age
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 4,
"name": "Omar",
"age": 35,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]",
"salary": 3000,
"country": "Palestine"
},
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
}
]
}
fields=value1, value2 - اختيار خانات معينة
يمكننا في الـ query
أن نختار خانات معينة فمثلا نحن نريد الإسم فقط ولا نريد باقي البيانات
في هذه الحالة نستخدم fields
ثم نختار الخانات التي نريدها
مثال users?fields=name
سيحضر أسماء جميع الأشخاص
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed"
},
{
"id": 2,
"name": "Mohamed"
},
{
"id": 3,
"name": "Ali"
},
{
"id": 4,
"name": "Omar"
},
{
"id": 5,
"name": "Osama"
}
]
}
نريد الإسم والعمر فقط
نستطيع اختيار أكثر من خانة مفصولة بـ ,
مثال users?fields=name,age
سيحضر أسماء وأعمار جميع الأشخاص
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25
},
{
"id": 2,
"name": "Mohamed",
"age": 30
},
{
"id": 3,
"name": "Ali",
"age": 35
},
{
"id": 4,
"name": "Omar",
"age": 35
},
{
"id": 5,
"name": "Osama",
"age": 30
}
]
}
نريد كل البيانات ما عادا الراتب والدولة
نقوم بوضع علامة -
لكي نستثني بعض الخانات هكذا users?fields=-salary,-country
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]"
},
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]"
},
{
"id": 4,
"name": "Omar",
"age": 35,
"email": "[email protected]"
},
{
"id": 5,
"name": "Osama",
"age": 30,
"email": "[email protected]"
}
]
}
page=n&limit=m - تقييد عدد النواتج
عندما يكون لديك بيانات كثيرة على سبيل المثال ألف مستخدم فمن غير المنطقي أن تجلب كل المستخدمين الذي لديك
سيكون حجم البيانات كبير جدًا وغالبا الموقع لن يستطيع التعامل معه
لذا نلجأ لتقييد عدد البيانات بمعنى تقليلها بعدد معين
فبدلًا أن نحصل على ألف مستخدم، نحصل على 10
فقط
هذا العدد يحدده الـ Backend
بالطبع
وتستطيع التحكم بهذا العدد عن طريق limit
فإن كنا نريد أول شخصين فقط فسنحصل على أول شخصين فقط
مثال users?limit=2
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 1,
"name": "Ahmed",
"age": 25,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
},
{
"id": 2,
"name": "Mohamed",
"age": 30,
"email": "[email protected]",
"salary": 3000,
"country": "Palestine"
}
]
}
الآن حصلنا على أول شخصيين حسنا إن أردنا الشخصيين التاليين ؟
كأنك تقول بعد ما قسمت الأشخاص لشخصين فقط، نريد المجموعة الثانية من هذا التقسيم
هنا ظهرت فكرة page
وهي بعد ما استخدمنا limit
لتحديد عدد النتاج نريد أن نختار المجموعة التي نريدها
يمكنك أن تتخيل أن limit
كأنها تقسم الناتج لصفحات و page
تختار لك الصفحة التي تريدها
تريد المجموعة الثانية ؟
أظنك توقعت شكل الـ query
بالفعل users?limit=2&page=2
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 3,
"name": "Ali",
"age": 35,
"email": "[email protected]",
"salary": 4000,
"country": "Egypt"
},
{
"id": 4,
"name": "Omar",
"age": 35,
"email": "[email protected]",
"salary": 3000,
"country": "Egypt"
}
]
}
تريد المجموعة الثالثة ؟
users?limit=2&page=3
{
"status": "success",
"code": 200,
"message": "Users retrieved successfully",
"users": [
{
"id": 5,
"name": "Osama",
"age": 30,
"email": "[email protected]",
"salary": 5000,
"country": "Palestine"
}
]
}
حصلنا على شخص واحد لان لدينا 5
أشخاص فقط في قاعدة البيانات
فبعد ما استخدمنا limit=2
فسمنا الأشخاص بهذا الشكل (1, 2) (3, 4) (5)
والمجموعة الثالثة هنا بها شخص واحد
بالطبع إن تجاوزت العدد المحدد فمثلا كتبت page=50
فغالبا ستحصل على بيانات فارغة
إرسال Array و Object في الـ Query
ملحوظة
: هذا الجزء من الشرح سيكون مناسب للـFrontend
ليدرك كيف يستقبل الـBackend
الـquery
باشكالها المختلفة
هناك شكل متقدم قليلًا لشكل البيانات التي نرسلها في الـ query
وهي اننا نستخدم اقواص الأراي في الـ query
بهذا الشكل users?name[]=value
ما معنى هذا الشكل ؟
أولًا قبل أن نجيب، هل فكرت كيف يستقبل صديقك الـ Backend
الـ query
؟
سنمسك شكل شكل ونحلله قليلًا
- أبسط شكل للـ
query
هو الشكل المعتاد لنا وهو هذا الشكل البسيط:users?name=value
صديقك الـ Backend
سيستقبلها بهذا الشكل
{
"name": "value"
}
هذا فقط هو الشكل الاعتيادي لما يستقبله الـ Backend
لا أظن ان هاك كلام نستطيع ان نضيفه هنا
- أما عندما ترسلها مع
[]
بهذا الشكل:users?name[]=value
{
"name": ["value"]
}
ستلاحظ أنه هنا استقبل القيمة في أراي أراي هذه المرة
بمعنى أنه بوجود []
فإن القيمة سترسل إلى الـ Backend
داخل أراي
- إرسال أكثر من عنصر داخل الأراي:
users?name[]=value1&name[]=value2&name[]=value3
{
"name": ["value1", "value2", "value3"]
}
ميزة وضع []
مع الـ key
سمحت لنا بإرسال أكثر من قيمة لنفس الـ key
فهنا كما ترى بما أن name[]
اصبح أراي
فيمكننا إضافة اكثر من عنصر فيه، بارسال اكثر من قيمة يحملون نفس الـ key
كما رأيت في الـ query
السابقة
- إرسال
Object
في الـQuery
:users?filter[key]=value
هنا لن يتحول الـ filter
إلى أراي لأن عندما تستقبل الـ []
أي key
هنا ستتحول لـ object
{
"filter": { "key": "value" }
}
كما ترى فالـ filter
اصبحت بالنسبة للـ Backend
عبارة عن الـ object
يحمل key
بقيمة معينة
- طبعًا
filter
أوname
مجرد اسماء متغيرة استخدمها للشرح لا أكثر
- إرسال أكثر من عنصر لنفس الـ
Key
داخل الـObject
:users?filter[key]=value1&filter[key]=value2&filter[key]=value3
عندما نرسل قيم مختلفة لنفس الـ key
ماذا سيحدث برأيك ؟
الأمر سيكون مشابه للرقم 3
{
"filter": {
"key": ["value1", "value2", "value3"]
}
}
عندما نثبت الـ key
ونرسل اكثر من قيمة له
فسيتحول هذا الـ key
لأراي كما ترى
وسيظل الـ filter
كما هو object
يضم هذا الـ key
- إرسال أكثر من
Key
داخل الـObject
:users?filter[key1]=value&filter[key2]=value&filter[key3]=value
حسنًا أظن هذه ستكون سهلة وتستطيع ان تستنتج شكلها
{
"filter": {
"key1": "value",
"key2": "value",
"key3": "value"
}
}
بطبع لاننا أنشأنا keys
مختلفة فستكون الـ filter
عبارة عن object
يضم هذه الـ keys
المختلفة
وكل key بالطبع سيحتوي على القيمة التي استندت له
هل هذا كل شيء في الـ Query ؟
بالطبع لا، هناك ملحوظة مهمة هنا عليك الانتباه لها جيدًا، الـ Query
شكلها وطريقتها وخواصها ومميزاتها يحددها الـ Backend
هو من يحدد ما الـ Query
المسموح بها وكيفية عملها وإلى أخره من التفاصيل التي يحددها الـ Backend
وقد تجد API
لا يدعم أي query
من الأساس
أو قد تجده لا يدعم fields
على سبيل المثال أو مثلا يغير اسمه إلى select
بدلًا من fields
أو تجده يدعم بعض المميزات ومميزات لا
كل
API
قد تجد الـquery
خاصته مختلفة تمامًا لذا عليك دائمًا الرجوع لتعليمات الـBackend
قبل استخدامك للـAPI
Headers
دعونا نتكلم عن الـ Headers
بشيء من التفاصيل
ذكرنا ان الـ headers
يحتوى على معلومات اضافية ترسل مع الطلب
تلك المعلومات الإضافية قد تكون أي شيء تريد إرسالها إلى الـ Backend
على سبيل المثال أريد إرسال أسمي في الـ header
وأن أرسل رسالة I love you, backend man
فأقوم بكتابتها في الـ headers
بهذا الشكل
headers: {
name: 'Ahmed',
message: 'I love you, backend man'
}
تلك البيانات سترسل إلى الـ backend
بنجاح،
لكن هل الـ backend
يحتاجُها ؟ لا، غالبًا لن يعمل معك مجددًا وسيقدم استقالته
عليك دائمًا إرسال البيانات التي يطلب الـ
backend
منك إرسالها في الـheaders
الأمر مشابه للـbody
لكن مع بعض الخواص
Content-Type
من تلك البيانات التي يمكننا إرسالها في الـ headers
لدينا Content-Type
ونكتب فيها نوع البيانات التي ارسلناها في الـ body
body: JSON.stringify({
name: 'Ahmed',
age: 30,
email: '[email protected]',
}),
headers: {
'Content-Type': 'application/json',
},
هنا ارسلنا للـ Backend
بيانات في الـ body
على شكل JSON
لذا كان يجب ان نوضح في الـ headers
نوع البيانات التي نريد ارسالها
لذا كتبنا داخل الـ headers
نوع البيانات 'Content-Type': 'application/json'
إن كانت البيانات المرسلة في الأ body
نوعها HTML
فقط نكتب 'Content-Type': 'text/html'
وإن كانت XML
نكتب 'Content-Type': 'text/xml'
أو 'Content-Type': 'application/xml'
... وهكذا
يوجد قيم كثيرة لوصف البيانات في الـ Content-Type
وهذه بعضها
text/html
text/plain
application/json
images/jpeg
images/png
audio/mp3
video/mp4
... ect
نكتب تلك القيم في الـ Content-Type
بحسب نوع البيانات التي نريد ارسالها في الـ body
content-type
هي كلمة متعارف عليها في الـheaders
بأنها تحدد نوع البيانات التي سترسل إلى الـbackend
في الـbody
, لذا لا تستخدمها لإرسال بيانات أخرى عشوائية غير البيانات التي من المفترض انها تتعامل معها
Authorization
يحتوي الـ headers
على بيانات أخرى مثل بيانات الـ Authorization
ليعرف الـ Backend
هل لديك صلاحية لاستخدام هذا الـ API
ام لا
في غالب الأمر عندما ينشيء الـ Backend
الـ API
يضع له رمز أمان ندعوه بـ API-KEY
وهو رمز يضعه الـ الـ Backend
بشكل معين لكي لا يتمكن أحد من استخدام الـ API
من لديهم الرمز هم فقط من يستطيعون استخدام الـ API
Unauthorized 401
لنفرض ان صديقنا الـ Backend
وجد نفسه متفرغا فقرر ان يضع API-KEY
للـ API
وليكن بهذا الشكل
"API-KEY": "ajmad-sharh-api-fe-el-3alam"
فأنت يا عزيزي الـ Frontend
تقوم بكل أمان الله بعمل طلب GET
بسيط على الـ API
فتفاجئ بهذا الرد
{
"status": "error",
"code": 401,
"message": "Unauthorized, You are not allowed to access this resource"
}
بأنك لا تملك صلاحية لاستخدام هذا الـ API
، ويكون رمز الحالة 401 ومعناه انه تم انتهاء صلاحيتك لاستخدام هذا الـ API
هنا تذهب وتصرخ للـ Backend
عن سبب هذا
فيعطيك الـ Backend
الرمز ويقول لك ضع هذا الرمز في الـ headers
تحت مسمى API-KEY
فتذهب وتعيد كتابة الكود بهذا الشكل
async function handleAPI() {
let url = 'https//database.api/users';
let obj = await fetch(url, {
method: 'GET',
headers: {
'API-KEY': 'ajmad-sharh-api-fe-el-3alam', // add API-Key in the headers
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
عند ارسال الطلب سيذهب الـ Backend
إلى الـ headers
ويبحث عن الرمز المرسل في الـ API-KEY
ويقارنه ان كان الرمز صالحًا سيتم تنفيذ الطلب بنجاح وان لم يكن الرمز صالحًا سيتم رفض الطلب ويرسل لك انك لا تملك الصلاحية للوصول إلى هذه البيانات
لذا ان كان الـ API
الذي تستخدمه محمي من API-KEY
عليك ان تحرص على كتابته في كل طلب ترسله في الـ API
عليك ايضًا ان تحرص على استخدام المسمى الذي حدده لنا الـ
Backend
وهو الـAPI-KEY
وهذا المسمى يحدده الـBackend
قد يكون باي اسم اخر قد يكونAPI KEY
أوKey
أوAPI Token
أو أي شيء انه مجرد مسمى يختاره الـBackend
لا أكثر ولا أقل
أحيانًا ينتهي صلاحية الـ API-KEY
لانه يملك تاريخ انتهاء للصلاحية يحددها الـ Backend
ففي تلك الحالة عليك طلب رمز جديد من الـ Backend
وأحيانًا يكون أبدي أي ليس له تاريخ انتهاء الصلاحية
Forbidden 403
فلنفترض ان صديقك اللدود وجد رابط الـ API
الخاص بشركتك ووجد أيضًا الـ API-KEY
وقررت ان يفسد مشروعكم ويمسح جميع البيانات في قاعدة البيانات خاصتكم فيكتب الكود بهذا الشكل
async function handleAPI() {
let url = 'https//database.api/users';
let obj = await fetch(url, {
method: 'DELETE',
headers: {
'API-KEY': 'ajmad-sharh-api-fe-el-3alam',
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
فيفاجئ بهذه الرسالة
{
"status": "error",
"code": 403,
"message": "Forbidden, You are not allowed to do this operation"
}
ما معنى هذا ؟
برغم بأنه استخدم الـ API-KEY
بشكل صحيح إلا انه لم يكن مصرح له تنفيذ عملية المسح
بمعنى انه يمكن ان تكون تملك الـ API-KEY
لاستخدام بعض العمليات على الـ API
وليس كلها
هناك عمليات قد تكون محظورة عليك برغم من انك تملك الـ API-KEY
فعندما تحاول القيام بعمليات غير المصرح لك استعمالها فسيقوم صديقك الـ Backend
بإرسال رمز الحالة 403 أي أنت غير مصرح لك أن تستخدم هذه العملية
إذا كان من يملك الـ
API-KEY
لا يمكنه القيام بكل العمليات، حسنًا إذا كنا نريد القيام بكل العمليات ماذا نفعل ؟
هنا يوجد عدة حلول منها أن يقوم الـ Backend
بعمل API-KEY
أخرة يستخدمها أشخاص معينين في الشركة أصحاب رتبة أعلى او متخصصين بعمل عمليات حساسة جدا على قاعدة البيانات كمسح البيانات بالكامل
فيكون هناك شخص معين لديه API-KEY
خاص به يعطيه صلاحيات أكثر من الـ API-KEY
العادي
هذه الطريقة تجعل الـ
Backend
يقوم بعمل أكثر منAPI-KEY
Token
الحل الآخر هو ان يقوم الـ Backend
بعمل token
بجانب الـ API-KEY
ويعطي token
لكل شخص يستخدم الـ API
ويعطي صلاحيات معينة لكل token
على حسب وظيفة الشخص الذي يستخدم الـ API
هل هو شخص عادي او شخص مسؤول عن عمليات حساسة ومهمة فنعطيه صلاحيات أكثر وهكذا
الـ token
يقوم الـ Frontend
بتخزينه في الـ الـ LocalStorage
ويضعه في الـ headers
مع كل Request
عندما يرسل أي Request
أو يمكننا أن نخزنه في الـ cookies
الأمر عائد لكما كـ Frontend
و Backend
كيف تديران الأمر
الـ token
أيضًا قد ينتهي صلاحية استخدامه ويحتاج إلى التجديد من قبل الـ Backend
هذه الطريقة تجعل الـ
Backend
يقوم بعملAPI-KEY
واحد فقط يستخدمه الـFrontend
ويتم التفريق بين المستخدمين وصلاحيتهم داخل التطبيق بالـtoken
مثال الشركة (Unauthorized vs Forbidden)
دعونا نسترجع الفرق بين الـ Unauthorized
والـ Forbidden
بمثال
تخيل ان هناك شركة ولنمثل هذه الشركة بالـ API
وانت شخص عادي تريد دخول الشركة، وعندما حاولت الدخول وجدت البواب يقول لك أنت لست موظف في الشركة
وهذا هو الـ Unauthorized
أنك لست مصرح لك من الأساس بدخول الشركة
وفي تلك الحالة عليك يجب ان يتم توظيفك في الشركة وتحصل على بطاقة شخصية تثبت أنك موظف في الشركة
هذه البطاقة تمثل الـ API-KEY
بعد ما حصلت على الوظيفة والبطاقة ودخلت الشركة بنجاح
فأنت مصرح لك بدخول الشركة وان تعمل في بعض الأمور فيها أي انك مصرح لك ان تستخدم الـ API
وتقوم بعمل بعض العمليات عليها
أنت الآن حاولت إلى طابق المدراء او طابق خاص بموظفين معينين، فوجدت شخص ما على باب المصعد يقول لك آسف هذا الطابق للمدراء والموظفين الأعلى رتبة فقط
هذا هو الـ Forbidden
أي أنه برغم من أنك موظف في الشركة لكن هناك بعض الأمور المحظورة عليك بما أنك موظف عادي
وتلك الأمور للموظفين الأعلى رتبة فقط
رتبتك تمثل الـ token
فالرتبة تحدد لك صلاحياتك في الشركة
فهكذا في الـ API
هناك عمليات لا تملك الصلاحية للقيام بها لأن الـ token
الخاص بك لا يملك صلاحيات كافية لهذه العملية
الآن أنت نائب مدير الشركة وتملك token
بكل الصلاحيات
فيأتي صديقك اللدود ويستولى على جهازك ويعيد الكرة بأن يمسح كل البيانات
async function handleAPI() {
let url = 'https//database.api/users';
let obj = await fetch(url, {
method: 'DELETE',
headers: {
'API-KEY': 'ajmad-sharh-api-fe-el-3alam',
// the token is stored in the cookies or localStorage
},
});
let data = await obj.json();
console.log(data);
}
handleAPI();
وهكذا تم رفضك من الشركة وأصبحت مشردًا هنا وهناك لذا أحرص دائما على إخفاء الـ API-KEY
والـ token
والخاص بك