اذهب إلى المحتوى

التعامل مع طلبات HTTP في Node.js


Hassan Hedr

تحتاج معظم التطبيقات حاليًا إلى التواصل مع بعض الخوادم لجلب البيانات منها أو لإتمام بعض المهام، فمثلًا في تطبيق ويب لشراء الكتب سيحتاج للتواصل مع خادم إدارة طلبات الزبائن وخادم مستودع الكتب وخادم إتمام الدفع، حيث تتواصل تلك الخدمات مع بعضها عن طريق الويب عبر الواجهات البرمجية API وتتبادل البيانات برمجيًا.

توفر نود دعمًا للتواصل عن طريق طلبات HTTP مع واجهات API عبر الويب، فتتيح الوحدة البرمجية ‎http‎ والوحدة ‎https‎، حيث تحتوي كل منهما على التوابع اللازمة لإنشاء خادم HTTP لمعالجة الطلبات الواردة إلى الخادم، وتوابع لإنشاء طلبات HTTP وإرسالها إلى الخوادم الأخرى، حيث تسمح هاتين الميزتين بتطوير تطبيقات ويب حديثة تعتمد على الواجهات البرمجية API للتواصل بينها، ولا حاجة لتثبيت أي وحدة برمجية خارجية حيث تأتي تلك الوحدات جاهزة مع نود افتراضيًا.

سنتعلم في هذا المقال كيف يمكننا الاستفادة من الوحدة ‎https‎ لإرسال طلبات HTTP بمثال عن التعامل مع خادم JSON Placeholder وهو واجهة برمجية API وهمية تستخدم في عمليات التدريب والاختبار، حيث سنتعلم طريقة إرسال طلب HTTP لطلب البيانات من نوع ‎GET‎، ثم سنتعرف على طرق تخصيص الطلب المرسل كإضافة الترويسات، وسنتعرف أيضًا على الطلبات بمختلف أنواعها مثل ‎POST‎ و ‎PUT‎ و ‎DELETE‎ والتي تستخدم لتعديل البيانات على الخوادم الأخرى.

المستلزمات

  • نسخة نود مثبتة على جهازك، حيث استخدمنا في هذا المقال الإصدار رقم 10.19.0.
  • تعتمد توابع إرسال طلبات HTTP على واجهة مجرى البيانات stream في نود وهي بدورها نسخة من كائن مرسل الأحداث event emitter، لذا يمكن التعامل مع البيانات الواردة منها بنفس طريقة تعاملنا مع الأحداث المرسلة، وللتعرف على مرسل الأحداث وطريقة التعامل معه يمكنك مراجعة المقال التاسع من هذه السلسلة.

إرسال طلب من نوع ‎GET‎

إن أردنا طلب بيانات من خادم ويب ما عبر واجهته البرمجية API نرسل إليه عادة طلب HTTP من نوع ‎GET‎، ففي هذه الفقرة سنتعلم طريقة إرسال تلك الطلبات في نود وتحديدًا لجلب مصفوفة بيانات بصيغة JSON تحتوي على بيانات حسابات شخصية لمستخدمين وهميين من واجهة برمجية API متاحة للعموم، حيث تحوي الوحدة البرمجية ‎https‎ على تابعين يمكن استخدامهما لإرسال طلبات من نوع ‎GET‎ هما التابع ‎get()‎، والتابع ‎request()‎ الذي يمكن استخدامه لإرسال طلبات من أنواع متعددة أخرى كما سنتعلم لاحقًا، ولنبدأ أولًا بالتعرف على التابع ‎get()‎.

إرسال الطلبات باستخدام التابع ‎get()‎

صيغة استخدام التابع ‎get()‎ تكون كالتالي:

https.get(URL_String, Callback_Function) {
    Action
}

حيث نمرر له سلسلة نصية كمعامل أول تحوي المسار الذي سنرسل الطلب إليه، والمعامل الثاني يكون دالة رد النداء callback function لمعالجة نتيجة الطلب.

سنبدأ بإنشاء مجلد جديد للمشروع سيحوي الأمثلة التي سنكتبها ضمن هذا الفصل كالتالي:

$ mkdir requests

وندخل إلى المجلد:

$ cd requests

ننشئ ملف جافاسكربت جديد ونفتحه باستخدام أي محرر نصوص حيث سنستخدم في أمثلتنا محرر نانو ‎nano‎ كالتالي:

$ nano getRequestWithGet.js

ونبدأ باستيراد الوحدة ‎https‎ كالتالي:

const https = require('https');

ملاحظة: يوجد في نود وحدتين برمجيتين هما ‎http‎ و ‎https‎ تحويان على نفس التوابع التي تعمل بنفس الطريقة، والفرق بينها أن التوابع ضمن ‎https‎ ترسل الطلبات عبر طبقة أمان النقل Transport Layer Security أو TLS/SSL، وسنرسل الطلبات في أمثلتنا عبر HTTPS لذا سنستخدم تلك التوابع من الوحدة ‎https‎، بينما لو كنا سنرسل الطلبات عبر HTTP فيجب استخدام توابع الوحدة ‎http‎ بدلًا منها.

نبدأ بكتابة شيفرة إرسال طلب ‎GET‎ إلى الواجهة البرمجية API لجلب بيانات المستخدمين، حيث سنرسل طلبًا إلى واجهة JSON Placeholder وهي واجهة برمجية متاحة للاستخدام العام لأغراض الاختبار، ولا تتأثر البيانات على ذلك الخادم بالطلبات المرسلة فمهمته فقط محاكاة عمل خادم حقيقي، حيث سيرجع لنا دومًا بيانات وهمية طالما أن الطلب المرسل إليه سليم، لنبدأ بكتابة الشيفرة التالية:

const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => { });

كما ذكرنا سابقًا يقبل التابع ‎get()‎ معاملين وهما المسار الوجهة للطلب URL كسلسلة نصية للواجهة البرمجية، ودالة رد نداء لمعالجة نتيجة طلب HTTP الواردة، حيث يمكن استخراج البيانات من الرد ضمن دالة رد النداء.

يحمل طلب HTTP على رمز الحالة status code وهو عدد يشير إلى نجاح الطلب من عدمه، فمثلًا إذا كانت قيمة الرمز بين 200 و 299 فالطلب ناجح، أما إذا كان بين 400 و 599 فهناك خطأ ما، وفي مثالنا الرد من الواجهة البرمجية يجب أن يحتوي على رمز الحالة 200 إن نجح وهو أول ما سنتحقق منه ضمن تابع رد النداء لمعالجة الطلب كالتالي:

const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }
});

يحوي كائن الرد res المُمرر لدالة رد النداء على الخاصية ‎statusCode‎ والتي تمثِّل قيمة رمز الحالة، وإذا لم تكن قيمته تساوي 200 سنطبع رسالة خطأ إلى الطرفية ونخرج مباشرةً.

نلاحظ استدعاء التابع ‎res.resume()‎ من كائن الرد وهي طريقة لتحسين أداء البرنامج فعند إرسال طلبات HTTP في نود يتم عادة معالجة البيانات المرسلة ضمن الطلب كاملةً، أما عند استدعائنا للتابع ‎res.resume()‎ فإننا نخبر نود بتجاهل البيانات ضمن مجرى كائن الرد، وهي طريقة أسرع من لو تُركت تلك البيانات لالتقاطها في مرحلة كنس المهملات garbage collection التي تتم دوريًا لتفريغ الذاكرة المستخدمة من قبل التطبيق.

والآن بعد أن تحققنا من رمز الحالة للرد سنبدأ بقراءة البيانات الواردة حيث تتوفر البيانات ضمن كائن مجرى الرد على دفعات، ويمكننا قراءتها بالاستماع إلى الحدث ‎data‎ من كائن الرد ثم تجميعها معًا ثم تحليلها بصيغة JSON لنتمكن من استخدامها ضمن التطبيق، لذلك سنضيف الشيفرة التالية ضمن تابع رد النداء:

const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });
});

عرفنا متغيرًا جديدًا بالاسم ‎data‎ والذي يحتوي على سلسلة نصية فارغة، حيث يمكننا تجميع البيانات الواردة إما على شكل مصفوفة من الأعداد تمثل البيانات للبايتات المكونة لها، أو على شكل سلسلة نصية وهو ما سنستخدمه في مثالنا لسهولة تحويل السلسلة النصية الناتجة عن عملية التجميع إلى كائن جافاسكربت.

نضيف بعد ذلك تابع الاستماع للبيانات الواردة على دفعات من الحدث ‎data‎ ونجمع البيانات كلها ضمن المتغير السابق ‎data‎، ويمكننا التأكد من انتهاء دفعات البيانات الواردة عند إطلاق حدث الإغلاق ‎close‎ من كائن الرد، وبعدها يمكننا تحويل السلسلة النصية بصيغة JSON ضمن المتغير ‎data‎ وطباعة القيمة النهائية إلى الطرفية، وبذلك نكون قد أكملنا كتابة عملية إرسال طلب إلى واجهة برمجية ستُرسل بدورها مصفوفة من بيانات حسابات شخصية لثلاثة مستخدمين بصيغة JSON ونقرأ الرد الوارد.

بقي لدينا إضافة معالجة لحالة رمي خطأ في حال لم نتمكن من إرسال الطلب لسبب ما، كحالة عدم وجود اتصال بالإنترنت كالتالي:

...
  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });

});

request.on('error', (err) => {
  console.error(`‎Encountered an error trying to make a request: ${err.message}‎`);
});

عند حدوث خطأ في عملية الإرسال سنتلقى الحدث ‎error‎ من كائن الطلب، وإذا لم نستمع لهذا الحدث فسيرمى الخطأ الناتج ما يؤدي لإيقاف عمل البرنامج، لذلك نضيف دالة استماع للحدث ‎error‎ على كائن الطلب باستخدام التابع ‎on()‎ والذي سيطبع رسالة الخطأ الوارد إلى الطرفية، وبذلك نكون قد انتهينا من كتابة البرنامج.

والآن نحفظ الملف ونخرج منه وننفذه باستخدام الأمر ‎node‎ كالتالي:

$ node getRequestWithGet.js

نحصل على الخرج التالي الذي يمثل الرد الوارد على الطلب المُرسل:

Retrieved all data
[
  {
    id: 1,
    name: 'Leanne Graham',
    username: 'Bret',
    email: 'Sincere@april.biz',
    address: {
      street: 'Kulas Light',
      suite: 'Apt. 556',
      city: 'Gwenborough',
      zipcode: '92998-3874',
      geo: [Object]
    },
    phone: '1-770-736-8031 x56442',
    website: 'hildegard.org',
    company: {
      name: 'Romaguera-Crona',
      catchPhrase: 'Multi-layered client-server neural-net',
      bs: 'harness real-time e-markets'
    }
  },
  {
    id: 2,
    name: 'Ervin Howell',
    username: 'Antonette',
    email: 'Shanna@melissa.tv',
    address: {
      street: 'Victor Plains',
      suite: 'Suite 879',
      city: 'Wisokyburgh',
      zipcode: '90566-7771',
      geo: [Object]
    },
    phone: '010-692-6593 x09125',
    website: 'anastasia.net',
    company: {
      name: 'Deckow-Crist',
      catchPhrase: 'Proactive didactic contingency',
      bs: 'synergize scalable supply-chains'
    }
  }
]

بذلك نكون قد أرسلنا طلبًا من نوع ‎GET‎ بنجاح باستخدام مكتبات نود فقط، حيث أن التابع الذي استخدمناه ‎get()‎ يوجد في نود بسبب كثرة الحاجة لإرسال الطلبات من نوع ‎GET‎، بينما الطريقة الأساسية لإرسال الطلبات هي باستخدام التابع ‎request()‎ والذي يمكنه إرسال أي نوع من الطلبات، وهو ما سنتعرف عليه في القسم التالي حيث سنستخدمه لإرسال طلب من نوع ‎GET‎.

إرسال الطلبات باستخدام التابع ‎request()‎

يمكن استخدام التابع ‎request()‎ بعدة صيغ والصيغة التي سنستخدمها في أمثلتنا هي كالتالي:

https.request(URL_String, Options_Object, Callback_Function) {
    Action
}

حيث نمرر له سلسلة نصية كمعامل أول تحتوي على مسار الواجهة البرمجية API الذي سنرسل الطلب إليه، والمعامل الثاني هو كائن جافاسكربت يحتوي على عدة خيارات للطلب المرسل، والمعامل الأخير المُمرر هو دالة رد النداء callback لمعالجة نتيجة الطلب.

نبدأ بإنشاء ملف جافاسكربت جديد بالاسم ‎getRequestWithRequest.js‎:

$ nano getRequestWithRequest.js

سنكتب برنامجًا مشابهًا لما كتبناه في القسم السابق ضمن الملف ‎getRequestWithGet.js‎، حيث نبدأ باستيراد الوحدة ‎https‎ كالتالي:

const https = require('https');

ثم نعرف كائن جافاسكربت يحتوي على الخاصية ‎method‎ كالتالي:

const https = require('https');

const options = {
  method: 'GET'
};

تعبر الخاصية ‎method‎ ضمن كائن خيارات التابع ‎request()‎ عن نوع الطلب الذي نريد إرساله، والآن نُرسل الطلب كما فعلنا سابقًا لكن مع بعض الاختلافات كالتالي:

...

let request = https.request('https://jsonplaceholder.typicode.com/users?_limit=2', options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });
});

request.end();

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

مررنا مسار الوجهة للطلب كمعامل أول للتابع ‎request()‎ ثم كائن خيارات HTTP كمعامل ثاني، وبعدها دالة رد النداء لمعالجة الرد، حيث حددنا نوع الطلب المرسل كطلب ‎GET‎ ضمن كائن الخيارات ‎options‎ الذي عرفناه سابقًا، وبقي دالة رد النداء لمعالجة الطلب كما هو في المثال السابق، وأضفنا استدعاءً للتابع ‎end()‎ من كائن الطلب ‎request‎، حيث يجب استدعاء هذا التابع عند إرسال الطلبات باستخدام ‎request()‎ لإتمام الطلب وإرساله، وفي حال لم نستدعيه فلن يُرسل الطلب ويبقى نود ينتظر منا إضافة بيانات جديدة إلى الطلب.

والآن نحفظ الملف ونخرج منه ثم ننفذ البرنامج:

$ node getRequestWithRequest.js

ليظهر الخرج التالي كما المثال السابق تمامًا:

Retrieved all data
[
  {
    id: 1,
    name: 'Leanne Graham',
    username: 'Bret',
    email: 'Sincere@april.biz',
    address: {
      street: 'Kulas Light',
      suite: 'Apt. 556',
      city: 'Gwenborough',
      zipcode: '92998-3874',
      geo: [Object]
    },
    phone: '1-770-736-8031 x56442',
    website: 'hildegard.org',
    company: {
      name: 'Romaguera-Crona',
      catchPhrase: 'Multi-layered client-server neural-net',
      bs: 'harness real-time e-markets'
    }
  },
  {
    id: 2,
    name: 'Ervin Howell',
    username: 'Antonette',
    email: 'Shanna@melissa.tv',
    address: {
      street: 'Victor Plains',
      suite: 'Suite 879',
      city: 'Wisokyburgh',
      zipcode: '90566-7771',
      geo: [Object]
    },
    phone: '010-692-6593 x09125',
    website: 'anastasia.net',
    company: {
      name: 'Deckow-Crist',
      catchPhrase: 'Proactive didactic contingency',
      bs: 'synergize scalable supply-chains'
    }
  }
]

وبذلك نكون قد تعرفنا على طريقة استخدام التابع ‎request()‎ لإرسال الطلبات من نوع ‎GET‎ وهو تابع أقوى من التابع السابق ‎get()‎ حيث يسمح بتخصيصات عدة على الطلب المرسل كتحديد نوعه وخيارات أخرى سنتعرف عليها في الفقرة التالية.

تخصيص خيارات HTTP للتابع ‎request()‎

يمكن استخدام التابع ‎request()‎ لإرسال طلبات HTTP دون تمرير عنوان مسار الوجهة للطلب كمعامل أول بل بتمريره ضمن كائن الخيارات ‎options‎ لتصبح صيغة استدعاء التابع كالتالي:

https.request(Options_Object, Callback_Function) {
    Action
}

في هذه الفقرة سنستخدم هذه الصيغة للتركيز على إعداد وتخصيص خيارات التابع ‎request()‎، لذا نعود إلى ملف المثال السابق ‎getRequestWithRequest.js‎ ونعدله بأن نزيل المسار URL المُمرر للتابع ‎request()‎ لتصبح المعاملات المُمررة له هي كائن الخيارات ‎options‎ ودالة رد النداء فقط كالتالي:

const https = require('https');

const options = {
  method: 'GET',
};

let request = https.request(options, (res) => {
...

لنضيف الخيارات الجديدة إلى الكائن ‎options‎ كالتالي:

const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users?_limit=2',
  method: 'GET'
};

let request = https.request(options, (res) => {
...

نلاحظ أنه وبدلًا من تمرير المسار كاملًا فإننا نمرره على قسمين ضمن الخاصيتين ‎host‎ و ‎path‎ حيث تُعبّر الخاصية ‎host‎ عن عنوان النطاق أو عنوان IP للخادم الوجهة، أما الخاصية ‎path‎ فهي كل ما يلي بعد ذلك ضمن المسار بما فيها معاملات الاستعلام query parameters التي تأتي بعد إشارة الاستفهام.

ويمكن أن تحتوي الخيارات على بيانات مفيدة أخرى للطلب المرسل مثل الترويسات المرسلة وهي بيانات وصفية عن الطلب نفسه، فمثلًا عادة تتطلب الواجهة البرمجية API تحديد صيغة البيانات المرسلة من عدة صيغ مدعومة مثل JSON أو CSV أو XML، ولتحديد الصيغة التي يطلبها المستخدم يمكن للواجهة البرمجية معاينة قيمة الترويسة ‎Accept‎ ضمن الطلب الوارد إليها وتحدد على أساسه الصيغة المناسبة لإرسالها.

تُعبّر الترويسة ‎Accept‎ عن نوع البيانات التي يمكن للمستخدم التعامل معها، وبما أننا نتعامل مع واجهة برمجية تدعم صيغة JSON فقط، فيمكننا إضافة الترويسة ‎Accept‎ وإضافة قيمة لها توضح أننا نريد البيانات بصيغة JSON كالتالي:

const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users?_limit=2',
  method: 'GET',
  headers: {
    'Accept': 'application/json'
  }
};

وبذلك نكون قد تعرفنا على أكثر أربعة خيارات استخدامًا ضمن طلبات HTTP وهي عنوان المضيف ‎host‎ و المسار ‎path‎ ونوع الطلب ‎method‎ والترويسات ‎headers‎، ويوجد العديد من الخيارات الأخرى المدعومة يمكنك الرجوع إلى التوثيق الرسمي لها ضمن نود للتعرف عليها.

والآن نحفظ الملف ونخرج منه ثم ننفذ البرنامج لنختبر طريقة إرسال الطلبات بتمرير كائن الخيارات فقط:

$ node getRequestWithRequest.js

ليظهر لنا بيانات الرد مطابقة للأمثلة السابقة:

Retrieved all data
[
  {
    id: 1,
    name: 'Leanne Graham',
    username: 'Bret',
    email: 'Sincere@april.biz',
    address: {
      street: 'Kulas Light',
      suite: 'Apt. 556',
      city: 'Gwenborough',
      zipcode: '92998-3874',
      geo: [Object]
    },
    phone: '1-770-736-8031 x56442',
    website: 'hildegard.org',
    company: {
      name: 'Romaguera-Crona',
      catchPhrase: 'Multi-layered client-server neural-net',
      bs: 'harness real-time e-markets'
    }
  },
  {
    id: 2,
    name: 'Ervin Howell',
    username: 'Antonette',
    email: 'Shanna@melissa.tv',
    address: {
      street: 'Victor Plains',
      suite: 'Suite 879',
      city: 'Wisokyburgh',
      zipcode: '90566-7771',
      geo: [Object]
    },
    phone: '010-692-6593 x09125',
    website: 'anastasia.net',
    company: {
      name: 'Deckow-Crist',
      catchPhrase: 'Proactive didactic contingency',
      bs: 'synergize scalable supply-chains'
    }
  }
]

تختلف متطلبات الواجهات البرمجية API بحسب الجهة المطورة لها، لذا من الضروري التعامل مع كائن الخيارات ‎options‎ لتخصيص الطلب بحسب حاجة التطبيق والخادم، من تحديد نوع البيانات المطلوبة وإضافة الترويسات المناسبة وبعض التخصيصات الأخرى.

أرسلنا ضمن كل الأمثلة السابقة طلبات فقط من نوع ‎GET‎ لجلب البيانات، وفي الفقرة التالية سنتعلم طريقة إرسال الطلبات من نوع ‎POST‎ والتي تستخدم لرفع البيانات إلى الخادم.

إرسال طلب من نوع ‎POST‎

نستخدم الطلبات من نوع ‎POST‎ لرفع البيانات إلى الخادم أو لطلب إنشاء بيانات جديدة من قبل الخادم، وفي هذه الفقرة سنتعرف على طريقة إرسال مثل هذه الطلبات في نود عبر إرسال طلب إنشاء مستخدم جديد إلى المسار ‎users‎ على الواجهة البرمجية API.

يمكننا إعادة استخدام بعض الشيفرات من مثال إرسال طلب من نوع ‎GET‎ السابق لإرسال طلبات من نوع ‎POST‎ مع إجراء بعض التعديلات عليها:

  • تعديل نوع الطلب ضمن كائن الخيارات ‎options‎ ليصبح ‎POST‎.
  • تعيين ترويسة نوع المحتوى المُرسل وهو في حالتنا بصيغة JSON.
  • التأكد من رمز الحالة للرد لتأكيد نجاح إنشاء مستخدم جديد.
  • رفع بيانات المستخدم الجديد.

نبدأ بإنشاء ملف جافاسكربت جديد بالاسم ‎postRequest.js‎ ونفتحه ضمن محرر النصوص:

$ nano postRequest.js

ونبدأ كما سابقًا باستيراد الوحدة ‎https‎ وتعريف كائن الخيارات ‎options‎ كالتالي:

const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users',
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json; charset=UTF-8'
  }
};

ونعدل خيار مسار الطلب ‎path‎ ليتوافق مع مسار إرسال الطلبات من نوع ‎POST‎ على الخادم، ونعدل خيار نوع الطلب المرسل ‎method‎ إلى القيمة ‎POST‎، وأخيرًا نضيف الترويسة ‎Content-Type‎ ضمن الخيارات والتي تدل الخادم على نوع البيانات التي أرسلناها مع الطلب وهي في حالتنا بصيغة JSON وبترميز من نوع UTF-8، ثم نُرسل الطلب باستدعاء التابع ‎request()‎ كما فعلنا تمامًا عند إرسال طلب من نوع ‎GET‎ سابقًا ولكن هذه المرة سنتحقق من رمز الحالة للرد بقيمة تختلف عن 200 كالتالي:

...
const request = https.request(options, (res) => {
  if (res.statusCode !== 201) {
    console.error(`‎Did not get a Created from the server. Code: ${res.statusCode}‎`);
    res.resume();
    return;
  }

  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Added new user');
    console.log(JSON.parse(data));
  });
});

تحققنا من صحة العملية بالتحقق من قيمة رمز الحالة بأن يساوي 201، وهو الرمز الذي يدل على إنشاء مورد جديد على الخادم بنجاح، ويُعبّر الطلب المرسل عن إنشاء مستخدم جديد لهذا سنحتاج لرفع بيانات هذا المستخدم وإرفاقها ضمن الطلب، لذا سننشئ تلك البيانات كالتالي:

...

const requestData = {
  name: 'New User',
  username: 'hsoub',
  email: 'user@hsoub.com',
  address: {
    street: 'North Pole',
    city: 'Murmansk',
    zipcode: '12345-6789',
  },
  phone: '555-1212',
  website: 'hsoub.com',
  company: {
    name: 'Hsoub',
    catchPhrase: 'Welcome to hsoub academy',
    bs: 'cloud scale security'
  }
};

request.write(JSON.stringify(requestData));

عرفنا بيانات المستخدم الجديد ضمن المتغير ‎requestData‎ على شكل كائن جافاسكربت يحتوي على بيانات المستخدم، ونلاحظ أننا لم نرفق قيمة المعرف ‎id‎ للمستخدم حيث أن هذه القيمة يولدها الخادم تلقائيًا للبيانات الجديدة، ثم استدعينا التابع ‎request.write()‎ والذي يقبل سلسلة نصية أو كائن مخزن مؤقت buffer ليتم إرسالها ضمن الطلب، وبما أن البيانات لدينا ضمن المتغير ‎requestData‎ هي كائن جافاسكربت فيجب تحويله إلى سلسلة نصية باستخدام ‎JSON.stringify‎.

ولإنهاء عملية الإرسال ننهي الطلب عبر استدعاء request.end()‎ ونتحقق من حدوث أي أخطاء في عملية الإرسال كالتالي:

...

request.end();

request.on('error', (err) => {
  console.error(`‎Encountered an error trying to make a request: ${err.message}‎`);
});

من الضروري استدعاء التابع ‎end()‎ لإنهاء الطلب وللإشارة إلى نود بأن كل البيانات التي نريد إرسالها ضمن الطلب قد أرفقت وأصبح بالإمكان إرساله.

والآن نحفظ الملف ونخرج منه ثم ننفذ البرنامج ونتأكد من عملية إنشاء المستخدم الجديد:

$ node postRequest.js

سنحصل على الخرج التالي:

Added new user
{
  name: 'New User',
  username: 'hsoub',
  email: 'user@hsoub.com',
  address: { street: 'North Pole', city: 'Murmansk', zipcode: '12345-6789' },
  phone: '555-1212',
  website: 'hsoub.com',
  company: {
    name: 'Hsoub',
    catchPhrase: 'Welcome to the hsoub academy',
    bs: 'cloud scale security'
  },
  id: 11
}

ما يعني أن الطلب تم بنجاح، حيث أعاد الخادم بيانات المستخدم التي أرسلناها مضافًا إليها قيمة معرّف المستخدم ID التي تم توليدها له، وبذلك نكون قد تعلمنا طريقة إرسال الطلبات من نوع ‎POST‎ لرفع البيانات إلى الخادم باستخدام نود، وفي الفقرة التالية سنتعلم طريقة إرسال الطلبات من نوع ‎PUT‎ للتعديل على بيانات موجودة مسبقًا.

إرسال طلب من نوع ‎PUT‎

تُستخدم الطلبات من نوع ‎PUT‎ لرفع البيانات إلى الخادم بشكل مشابه للطلبات من نوع ‎POST‎، ولكن الفرق أنه عند تنفيذ طلب من نوع ‎PUT‎ عدة مرات سنحصل على نفس النتيجة، بينما عند تكرار نفس طلب ‎POST‎ عدة مرات سنضيف بذلك البيانات المرسلة أكثر من مرة إلى الخادم، وطريقة إرسال هذا الطلب مشابهة للطلب من نوع ‎POST‎ حيث نعرف الخيارات ونُنشئ الطلب ونكتب البيانات التي نريد رفعها إلى الطلب ثم نتحقق من الرد الوارد في نتيجة الطلب.

نختبر ذلك بإنشاء طلب من نوع ‎PUT‎ لتعديل اسم المستخدم لأول مستخدم، وبما أن طريقة إرسال الطلب مشابهة لطريقة إرسال الطلب من نوع ‎POST‎ يمكننا الاستفادة من المثال السابق ونسخ الملف ‎postRequest.js‎ إلى ملف جديد بالاسم ‎putRequest.js‎ كالتالي:

$ cp postRequest.js putRequest.js

نفتح الملف ‎putRequest.js‎ ضمن محرر النصوص:

$ nano putRequest.js

ونعدل نوع الطلب إلى ‎PUT‎ ومساره إلى ‎https://jsonplaceholder.typicode.com/users/1‎ والبيانات المرسلة كالتالي:

const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users/1',
  method: 'PUT',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json; charset=UTF-8'
  }
};

const request = https.request(options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`‎Did not get an OK from the server. Code: ${res.statusCode}‎`);
    res.resume();
    return;
  }

  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Updated data');
    console.log(JSON.parse(data));
  });
});

const requestData = {
  username: 'hsoub'
};

request.write(JSON.stringify(requestData));

request.end();

request.on('error', (err) => {
  console.error(`‎Encountered an error trying to make a request: ${err.message}‎`);
});

نلاحظ تعديل قيم المسار ‎path‎ ونوع الطلب ‎method‎ ضمن كائن الخصائص ‎options‎ حيث يحوي المسار على معرّف المستخدم الذي نود تعديل بياناته، ثم نتحقق من من رمز الحالة للطلب بأن يكون بالقيمة 200 ما يدل على نجاح الطلب، ونلاحظ أن البيانات التي أرسلناها تحوي فقط على الخصائص التي نريد تحديثها من بيانات المستخدم.

والآن نحفظ الملف ونخرج منه ثم ننفذ البرنامج:

$ node putRequest.js

ليظهر الخرج التالي:

Updated data
{ username: 'hsoub', id: 1 }

أرسلنا بنجاح طلب من نوع ‎PUT‎ لتعديل بيانات مستخدم موجودة مسبقًا على الخادم، وبذلك نكون قد تعلمنا طرق طلب البيانات ورفعها وتحديثها، وسنتعلم في الفقرة التالية كيف يمكن حذف البيانات من الخادم بإرسال طلب من النوع ‎DELETE‎.

إرسال طلب من نوع ‎DELETE‎

تستخدم الطلبات من نوع ‎DELETE‎ لحذف البيانات من الخادم، ويمكن أن يحتوي الطلب على بيانات مرفقة ضمنه ولكن معظم الواجهات البرمجية API لا تتطلب ذلك، حيث يستخدم هذا النوع من الطلبات لحذف بيانات كائن ما كليًا من الخادم.

سنرسل في هذه الفقرة طلب من هذا النوع لحذف بيانات أحد المستخدمين، وطريقة إرسال هذا الطلب مشابهة لطريقة إرسال طلب من نوع ‎GET‎، لذا يمكننا نسخ ملف المثال السابق ‎getRequestWithRequest.js‎ إلى ملف جديد بالاسم ‎deleteRequest.js‎ كالتالي:

$ cp getRequestWithRequest.js deleteRequest.js

ونفتح الملف الجديد ضمن محرر النصوص:

$ nano deleteRequest.js

ونعدل الشيفرة لإرسال طلب حذف لأول مستخدم كالتالي:

const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users/1',
  method: 'DELETE',
  headers: {
    'Accept': 'application/json',
  }
};

const request = https.request(options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`‎Did not get an OK from the server. Code: ${res.statusCode}‎`);
    res.resume();
    return;
  }

  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Deleted user');
    console.log(JSON.parse(data));
  });
});

request.end();

request.on('error', (err) => {
  console.error(`‎Encountered an error trying to make a request: ${err.message}‎`);
});

عدلنا قيمة المسار ‎path‎ ضمن كائن خيارات الطلب ليحوي معرّف المستخدم الذي نريد حذفه، وعدلنا نوع الطلب إلى ‎DELETE‎، والآن نحفظ الملف ونخرج منه ثم ننفذ البرنامج كالتالي:

$ node deleteRequest.js

لنحصل على الخرج:

Deleted user
{}

لا تعيد الواجهة البرمجية أي بيانات ضمن جسم الرد الوارد، ولكن رمز الحالة لهذا الرد يكون 200 أي تم حذف بيانات المستخدم بنجاح، وبذلك نكون قد تعرفنا على طريقة إرسال طلبات من نوع ‎DELETE‎ أيضًا في نود.

خاتمة

تعرفنا في هذا الفصل على طريقة إرسال الطلبات في نود بأنواعها مختلفة مثل ‎GET‎ و ‎POST‎ و ‎PUT‎ و ‎DELETE‎ دون استخدام أي مكتبات خارجية وفقط باستخدام الوحدة البرمجية ‎https‎ التي يوفرها نود، وتعرفنا على طريقة خاصة لإرسال الطلبات من نوع ‎GET‎ باستخدام التابع ‎get()‎ وكيف أن باقي الطلبات يمكن إرسالها باستخدام التابع ‎request()‎، وتعاملنا ضمن الأمثلة مع واجهة برمجية API عامة ويمكن بنفس الطريقة إرسال الطلبات إلى مختلف أنواع الواجهات البرمجية.

ترجمة -وبتصرف- للمقال How To Create an HTTP Client with Core HTTP in Node.js.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...