كيفية إنشاء واجهة برمجة تطبيقات GraphQL لـ Node.js آمنة
نشرت: 2022-03-11في هذه المقالة ، نهدف إلى تقديم دليل سريع حول كيفية إنشاء واجهة برمجة تطبيقات GraphQL آمنة لـ Node.js.
بعض الأسئلة التي قد تتبادر إلى الذهن قد تكون:
- ما الغرض من استخدام واجهة برمجة تطبيقات GraphQL؟
- ما هي واجهة برمجة تطبيقات GraphQL؟
- ما هو استعلام GraphQL؟
- ما فائدة GraphQL؟
- هل GraphQL أفضل من REST؟
- لماذا نستخدم Node.js؟
كل هذه أسئلة صحيحة ، ولكن قبل الإجابة عليها ، يجب أن نتعمق في لمحة موجزة عن الوضع الحالي لتطوير الويب:
- يستخدم كل حل ستجده اليوم تقريبًا نوعًا من واجهة برمجة التطبيقات (API).
- حتى إذا كنت تستخدم شبكة اجتماعية فقط ، مثل Facebook أو Instagram ، فأنت لا تزال متصلاً بواجهة أمامية تستهلك واجهة برمجة تطبيقات.
- إذا كنت مهتمًا بالفضول ، فستجد أن جميع خدمات الترفيه عبر الإنترنت تقريبًا تستخدم نوعًا مختلفًا من واجهة برمجة التطبيقات ، بما في ذلك خدمات مثل Netflix و Spotify و YouTube.
في كل سيناريو تقريبًا ، ستجد واجهة برمجة تطبيقات لا تحتاج إلى معرفتها بالتفصيل ، على سبيل المثال ، لست بحاجة إلى معرفة كيف تم إنشاؤها ، ولا تحتاج إلى استخدام نفس التكنولوجيا التي اعتادت أن تكون قادر على دمجه في نظامك الخاص. تتيح لك واجهة برمجة التطبيقات التي يتم توفيرها تقديم طريقة للتواصل بين الخدمات وفقًا لمعيار مشترك يمكن لكل من الخدمة والعميل الاتصال به دون الحاجة إلى الاعتماد على مجموعة تقنية معينة.
من خلال واجهة برمجة تطبيقات جيدة التنظيم ، من الممكن أن يكون لديك واجهة برمجة تطبيقات قوية وقابلة للصيانة وقابلة للتطوير يمكنها أن تخدم أنواعًا متعددة من العملاء وتطبيقات الواجهة الأمامية.
ومع ذلك ، ما هي واجهة برمجة تطبيقات GraphQL؟
GraphQL هي لغة استعلام لواجهات برمجة التطبيقات ، تم تطويرها للاستخدام الداخلي في Facebook وتم نشرها للاستخدام العام في عام 2015. وهي تدعم القراءة والكتابة والتحديثات في الوقت الفعلي. إنه أيضًا مفتوح المصدر ، ويتم مقارنته عادةً بـ REST والبنى الأخرى. إنه باختصار يعتمد على:
- استعلامات GraphQL - يسمح هذا للعميل بقراءة كيفية تلقي البيانات ومعالجتها.
- طفرات GraphQL - هذه هي كيفية كتابة البيانات على الخادم. إنها اتفاقية GraphQL حول كيفية كتابة البيانات في النظام.
على الرغم من أنه من المفترض أن توضح هذه المقالة سيناريو بسيطًا ولكنه واقعي حول كيفية إنشاء واستخدام واجهات برمجة تطبيقات GraphQL ، إلا أننا لن نقدم مقدمة تفصيلية إلى GraphQL. السبب بسيط ، حيث يوفر فريق GraphQL توثيقًا شاملاً ويسرد العديد من أفضل الممارسات في مقدمتهم إلى GraphQL.
ما هو استعلام GraphQL؟
كما تم وصفه من قبل ، الاستعلام هو الطريقة التي يمكن للعميل من خلالها قراءة البيانات من واجهة برمجة التطبيقات ومعالجتها. يمكنك تمرير نوع الكائن وتحديد نوع الحقول التي تريد استلامها مرة أخرى. قد يكون الاستعلام البسيط كما يلي:
query{ users{ firstName, lastName } }
في هذا الاستعلام ، نحاول الوصول إلى جميع المستخدمين من مخطط مستخدمينا ولكننا نتلقى فقط firstName
واسم lastName
. قد تكون نتيجة هذا الاستعلام مثل:
{ "data": { "users": [ { "firstName": "Marcos", "lastName": "Silva" }, { "firstName": "Paulo", "lastName": "Silva" } ] } }
إنه سهل للغاية لاستخدام العميل.
ما هو الغرض من استخدام واجهة برمجة تطبيقات GraphQL؟
الغرض من إنشاء API هو القدرة على الحصول على برنامج كخدمة يمكن دمجها بواسطة خدمات خارجية أخرى. حتى إذا تم استهلاك تطبيقك بواسطة واجهة أمامية واحدة ، يمكنك اعتبار هذه الواجهة الأمامية خدمة خارجية ، ولهذا ، ستتمكن من العمل في مشاريع مختلفة عندما يتم توفير الاتصال بين الاثنين عبر واجهة برمجة التطبيقات.
إذا كنت تعمل في فريق كبير ، فيمكن تقسيمه لإنشاء فريق الواجهة الأمامية والخلفية ، مما يسمح لكليهما باستخدام نفس التكنولوجيا وتسهيل عملهما. عند تصميم واجهة برمجة تطبيقات ، من المهم اختيار الأنسب للمشروع وما يقربك من الحل الذي تريده.
في هذه المقالة ، سنركز على هيكل لبناء واجهة برمجة تطبيقات تستخدم GraphQL.
هل GraphQL أفضل من REST؟
قد يكون الأمر نوعًا من التهرب ، لكن لا يمكنني مساعدته: هذا يعتمد .
GraphQL هي نهج يناسب العديد من السيناريوهات جيدًا. REST هو نهج معماري تم إثباته في العديد من السيناريوهات أيضًا. في الوقت الحاضر ، هناك الكثير من المقالات التي تشرح سبب كون أحدهما أفضل من الآخر أو لماذا يجب عليك استخدام REST فقط بدلاً من GraphQL. وأيضًا ، هناك الكثير من الطرق التي يمكنك من خلالها استخدام GraphQL داخليًا مع الحفاظ على نقاط نهاية API كبنية قائمة على REST.
سيكون أفضل توجيه هو معرفة فوائد كل نهج ، وتحليل الحل الذي تقوم بإنشائه ، وتقييم مدى راحة فريقك في العمل مع الحل ، وتقييم ما إذا كنت ستتمكن من توجيه فريقك للتعلم والاستعداد. السرعة قبل الاختيار بين الطرق.
هذه المقالة عبارة عن دليل عملي أكثر من كونها مقارنة ذاتية بين GraphQL و REST. إذا كنت ترغب في قراءة مقارنة مفصلة بين الاثنين ، أقترح عليك مراجعة مقال آخر من مقالاتنا ، GraphQL مقابل REST - برنامج تعليمي لـ GraphQL.
في مقال اليوم ، سنركز على إنشاء واجهة برمجة تطبيقات GraphQL باستخدام Node.js.
لماذا نستخدم Node.js؟
تمتلك GraphQL العديد من المكتبات المختلفة التي يمكنك استخدامها. لغرض هذه المقالة ، قررنا المضي قدمًا في فكرة استخدام JavaScript مع Node.js نظرًا لاستخدامها على نطاق واسع وحقيقة أن Node.js يسمح للمطورين باستخدام بناء جملة مألوف للواجهة الأمامية لتطوير جانب الخادم.
من المفيد أيضًا المقارنة مع نهجنا مع واجهة برمجة التطبيقات المستندة إلى REST ، على غرار تلك التي تم توضيحها في مقال آخر في مدونة Toptal Engineering: إنشاء واجهة برمجة تطبيقات آمنة في Node.js. تعرض هذه المقالة أيضًا استخدام Node.js مع Express لتطوير هيكل REST API والذي سيسمح لك بمقارنة بعض الاختلافات بين هذين النهجين. تم تصميم Node.js أيضًا باستخدام تطبيقات شبكة قابلة للتطوير ، ومجتمع عالمي ، والعديد من المكتبات مفتوحة المصدر التي يمكنك العثور عليها على موقع ويب npm.
هذه المرة ، سنعرض كيفية إنشاء واجهة برمجة تطبيقات هيكلية باستخدام GraphQL و Node.js و Express!
التدريب العملي على دروس GraphQL
كما أوضحنا سابقًا ، سنبني فكرة هيكلية لواجهة GraphQL API ، وستحتاج إلى معرفة أساسيات Node.js و Express قبل المتابعة. يتوفر هنا كود المصدر الخاص بالمشروع المصنوع لمثال GraphQL هذا.
سوف نتعامل مع نوعين من الموارد:
- المستخدمون ، الذين سنتعامل معهم مع CRUD الأساسي.
- المنتجات ، التي سيكون لدينا القليل من التفاصيل الخاصة بها لإظهار المزيد من قوة GraphQL.
سيحتوي المستخدمون على الهيكل التالي:
- هوية شخصية
- الاسم الأول
- الكنية
- البريد الإلكتروني
- كلمه السر
- مستوى الإذن
ستحتوي المنتجات على الهيكل التالي:
- هوية شخصية
- اسم
- وصف
- السعر
بالنسبة لمعيار الترميز ، سنستخدم TypeScript لهذا المشروع. في الملف المصدر ، ستتمكن من تكوين كل شيء لبدء الترميز باستخدام TypeScript.
دعونا نبرمج!
بادئ ذي بدء ، تأكد من تثبيت أحدث إصدار من Node.js. في وقت النشر ، الإصدار الحالي هو 10.15.3 ، وفقًا لـ Nodejs.org.
بدء المشروع
لنبدأ في مجلد جديد يمكننا تسميته node-graphql
. هناك ، يمكننا فتح Terminal أو وحدة تحكم Git CLI وبدء السحر باستخدام الأمر التالي: npm init
.
تكوين تبعياتنا و TypeScript
لتسريع العملية ، يجب أن يحتوي استبدال package.json
بما يلي في مستودع Git على جميع التبعيات الضرورية:
{ "name": "node-graphql", "version": "1.0.0", "description": "", "main": "dist/index.js", "scripts": { "tsc": "tsc", "start": "npm run tsc && node ./build/app.js" }, "author": "", "license": "ISC", "dependencies": { "@types/express": "^4.16.1", "@types/express-graphql": "^0.6.2", "@types/graphql": "^14.0.7", "express": "^4.16.4", "express-graphql": "^0.7.1", "graphql": "^14.1.1", "graphql-tools": "^4.0.4" }, "devDependencies": { "tslint": "^5.14.0", "typescript": "^3.3.4000" } }
باستخدام package.json
المحدث ، فقط اضغط على Terminal مرة أخرى واستخدم: npm install
. سيقوم بتثبيت جميع التبعيات اللازمة لتشغيل واجهة برمجة تطبيقات GraphQL هذه داخل Node.js و Express.
الجزء التالي هو تكوين وضع TypeScript الخاص بنا. نحتاج إلى ملف يسمى tsconfig.json
في المجلد الجذر لدينا مع ما يلي:
{ "compilerOptions": { "target": "ES2016", "module": "commonjs", "outDir": "./build", "strict": true, "esModuleInterop": true } }
سيكون منطق رمز هذا التكوين موجودًا في مجلد التطبيق. هناك يمكننا إنشاء ملف app.ts
الأساسي ، أضف الكود التالي هناك:
console.log('Hello Graphql Node API tutorial');
من خلال التكوين الخاص بنا ، يمكننا الآن تشغيل npm start
والقدرة على اختبار أن كل شيء يعمل بشكل صحيح. في وحدة التحكم الطرفية ، يجب أن ترى "البرنامج التعليمي Hello GraphQL Node API الخاص بنا." في المشهد الخلفي ، يقوم التكوين بشكل أساسي بتجميع كود TypeScript إلى JavaScript خالص ثم يقوم بتنفيذ بنائنا في مجلد build
.
لنقم الآن بتهيئة هيكل أساسي لواجهة برمجة تطبيقات GraphQL الخاصة بنا. لبدء مشروعنا ، سنضيف ثلاث واردات أساسية:

- يعبر
- Express-Graphql
- أدوات Graphql
لنبدأ في تجميعها جميعًا:
import express from 'express'; import graphqlHTTP from 'express-graphql'; import {makeExecutableSchema} from 'graphql-tools';
الآن يجب أن نكون قادرين على البدء في البرمجة قليلاً. الخطوة التالية هي التعامل مع تطبيقنا في Express وتكوين GraphQL الأساسي مثل:
import express from 'express'; import graphqlHTTP from 'express-graphql'; import {makeExecutableSchema} from 'graphql-tools'; const app: express.Application = express(); const port = 3000; let typeDefs: any = [` type Query { hello: String } type Mutation { hello(message: String) : String } `]; let helloMessage: String = 'World!'; let resolvers = { Query: { hello: () => helloMessage }, Mutation: { hello: (_: any, helloData: any) => { helloMessage = helloData.message; return helloMessage; } } }; app.use( '/graphql', graphqlHTTP({ schema: makeExecutableSchema({typeDefs, resolvers}), graphiql: true }) ); app.listen(port, () => console.log(`Node Graphql API listening on port ${port}!`));
ما نقوم به هو:
- تفعيل المنفذ 3000 لتطبيقنا للخادم السريع.
- تحديد الاستعلامات والطفرات التي نريد استخدامها كمثال سريع.
- تحديد كيفية عمل الاستعلامات والطفرات.
حسنًا ، ولكن ما الذي يحدث لأدوات التحليل والمحللات ، بالإضافة إلى علاقتها بالاستعلامات والطفرات؟
- typeDefs - تعريف مخططنا لما يمكن أن نتوقعه من الاستعلامات والطفرات.
- المحللون - بدلاً من توقع الحقول أو المعلمات المطلوبة ، نحدد هنا الوظائف والسلوكيات الخاصة بكيفية عمل الاستعلامات والطفرات.
- الاستعلامات - "يحصل" الذي نريد قراءته من الخادم.
- الطفرات - طلباتنا التي ستؤثر على أي بيانات لدينا على خادمنا الخاص.
الآن ، لنبدأ تشغيل npm مرة أخرى لنرى ما لدينا هناك. نتوقع أن يتم تشغيل التطبيق بالرسالة التالية: تستمع Node Graphql API على المنفذ 3000!
يمكننا الآن محاولة الاستعلام عن واجهة برمجة تطبيقات GraphQL واختبارها على خادمنا الخاص عبر: http: // localhost: 3000 / graphql
رائع ، يمكننا الآن كتابة أول طلب بحث خاص بنا والذي تم تعريفه على أنه "مرحبًا".
لاحظ أن الطريقة التي حددناها بها في typeDefs
، يمكن أن تساعدنا الصفحة في بناء الاستعلام.
هذا رائع ، لكن كيف يمكننا تغيير القيمة؟ الطفرات!
الآن ، دعنا نرى ما يحدث عندما نغير القيمة في الذاكرة بطفرة:
يمكننا الآن إجراء عمليات CRUD الأساسية باستخدام واجهة برمجة تطبيقات GraphQL Node.js. دعنا نتقدم مع الكود الخاص بنا الآن.
منتجات
بالنسبة للمنتجات ، سوف نستخدم وحدة تسمى المنتجات. في محاولة لتبسيط هذه المقالة ، سنستخدم قاعدة بيانات في الذاكرة للتوضيح فقط. سنحدد نموذجًا وخدمة لإدارة المنتجات.
سيعتمد نموذجنا على النحو التالي:
export class Product { private id: Number = 0; private name: String = ''; private description: String = ''; private price: Number = 0; constructor(productId: Number, productName: String, productDescription: String, price: Number) { this.id = productId; this.name = productName; this.description = productDescription; this.price = price; } }
سيتم تعريف الخدمة التي ستتواصل مع GraphQL على النحو التالي:
export class ProductsService { public products: any = []; configTypeDefs() { let typeDefs = ` type Product { name: String, description: String, id: Int, price: Int } `; typeDefs += ` extend type Query { products: [Product] } `; typeDefs += ` extend type Mutation { product(name:String, id:Int, description: String, price: Int): Product! }`; return typeDefs; } configResolvers(resolvers: any) { resolvers.Query.products = () => { return this.products; }; resolvers.Mutation.product = (_: any, product: any) => { this.products.push(product); return product; }; } }
المستخدمون
بالنسبة للمستخدمين ، سوف نتبع نفس هيكل وحدة المنتجات. سيكون لدينا نموذج وخدمة للمستخدمين. سيتم تعريف النموذج على النحو التالي:
export class User { private id: Number = 0; private firstName: String = ''; private lastName: String = ''; private email: String = ''; private password: String = ''; private permissionLevel: Number = 1; constructor(id: Number, firstName: String, lastName: String, email: String, password: String, permissionLevel: Number) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.email = email; this.password = password; this.permissionLevel = permissionLevel; } }
وفي الوقت نفسه ، ستكون خدمتنا مثل:
const crypto = require('crypto'); export class UsersService { public users: any = []; configTypeDefs() { let typeDefs = ` type User { firstName: String, lastName: String, id: Int, password: String, permissionLevel: Int, email: String } `; typeDefs += ` extend type Query { users: [User] } `; typeDefs += ` extend type Mutation { user(firstName:String, lastName: String, password: String, permissionLevel: Int, email: String, id:Int): User! }`; return typeDefs; } configResolvers(resolvers: any) { resolvers.Query.users = () => { return this.users; }; resolvers.Mutation.user = (_: any, user: any) => { let salt = crypto.randomBytes(16).toString('base64'); let hash = crypto.createHmac('sha512', salt).update(user.password).digest("base64"); user.password = hash; this.users.push(user); return user; }; } }
للتذكير ، الكود المصدري متاح للاستخدام من هذا الرابط.
الآن يمكننا اللعب واختبار الكود الخاص بنا. لنبدأ تشغيل npm start
. سيكون لدينا الخادم قيد التشغيل في المنفذ 3000. يمكننا الآن الوصول إلى GraphQL للاختبار على http: // localhost: 3000 / graphql.
دعنا نجرب طفرة لإضافة عنصر إلى قائمة منتجاتنا:
لاختبار ما إذا كان قد نجح ، سنستخدم الآن استعلامًا عن المنتجات ، لكننا نتلقى فقط id
name
price
:
query{ products{ id, name, price } } The response will be: { "data": { "products": [ { "id": 100, "name": "My amazing product", "price": 400 } ] } }
وهذا كل شيء؛ المنتج يعمل كما هو متوقع. الآن يمكننا اللعب وتبديل الحقول إذا أردنا ذلك. يمكنك محاولة إضافة وصف:
query{ products{ id, name, description, price } }
الآن يمكننا الحصول على أوصاف منتجاتنا. لنجرب المستخدمين الآن.
mutation{ user(id:200, firstName:"Marcos", lastName:"Silva", password:"amaz1ingP4ss", permissionLevel:9, email:"[email protected]") { id } }
والاستعلام سيكون مثل:
query{ users{ id, firstName, lastName, password, email } }
برد مثل:
{ "data": { "users": [ { "id": 200, "firstName": "Marcos", "lastName": "Silva", "password": "kpj6Mq0tGChGbZ+BT9Nw6RMCLReZEPPyBCaUS3X23lZwCCp1Ogb94/oqJlya0xOBdgEbUwqRSuZRjZGhCzLdeQ==", "email": "[email protected]" } ] } }
والآن أصبح الهيكل العظمي لـ GraphQL جاهزًا! هناك الكثير من الخطوات من هنا نحو واجهة برمجة تطبيقات مفيدة تعمل بكامل طاقتها ، ولكن تم تعيين النواة الأساسية الآن.
الخلاصة والأفكار النهائية
حتى قطع الحواف لاختصارها ، فإن المقالة كبيرة جدًا وتحتوي على الكثير من المعلومات الأساسية المتعلقة بتطوير واجهة برمجة تطبيقات GraphQL Node.js.
دعنا نراجع ما غطيناه حتى الآن:
- استخدام Node.js مع Express و GraphQL لإنشاء واجهة برمجة تطبيقات GraphQL ؛
- استخدام GraphQL الأساسي ؛
- الاستخدام الأساسي للاستعلامات والطفرات ؛
- النهج الأساسي لإنشاء وحدات لمشروعك ؛
- اختبار واجهة برمجة تطبيقات GraphQL الخاصة بنا ؛
للتركيز أكثر على الجانب التنموي للأشياء ، تجنبنا عدة بنود مهمة يمكن تلخيصها بإيجاز على النحو التالي:
- عمليات التحقق من صحة العناصر الجديدة ؛
- معالجة الأخطاء بشكل صحيح من خلال خدمة الأخطاء العامة ؛
- التحقق من صحة الحقول التي يمكن للمستخدم استخدامها عند كل طلب مع خدمة عامة ؛
- إضافة JWT اعتراض لتأمين API ؛
- التعامل مع تجزئة كلمة المرور بنهج أكثر فاعلية ؛
- إضافة اختبارات الوحدة والتكامل ؛
تذكر أن لدينا كود المصدر الكامل على رابط Git هذا. لا تتردد في الاستخدام والشوكة وفتح المشكلات وتقديم طلبات السحب واللعب بها! يرجى ملاحظة أن جميع المعايير والاقتراحات الواردة في هذه المقالة ليست منحوتة في الحجر.
هذه مجرد واحدة من العديد من الأساليب التي يمكن استخدامها لبدء تصميم واجهة برمجة تطبيقات GraphQL الخاصة بك. تأكد أيضًا من قراءة GraphQL واستكشافها بمزيد من التفاصيل ، وتعلم ما تقدمه وكيف يمكنها تحسين واجهات برمجة التطبيقات الخاصة بك.