express.js – שימוש ב-middleware בראוטינג

איך מייצרים שכבה שרצה תמיד בראוטינג מסוים
express.js

במאמר הקודם עברנו על ראוטינג, ראינו שאנחנו לא חייבים לכתוב את כל הקוד בתוך הקובץ המרכזי של app.js אלא ליצור מודול של ראוטר שבו כותבים את כל הנתיבים הרלוונטיים. בתור דוגמה, הראיתי איך אני יוצר מודול ראוטינג שיטפל בכל הדפים שיש בנתיב help.

קובץ ה-help.js נראה כך:


var express = require('express');
var router = express.Router();

router.get('/about-me', function(req, res) {
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  res.send('How to use');
});

module.exports = router;

קובץ ה-app.js


var express = require('express');
var app = express();
var help = require('./help');

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

app.use('/help', help);

בואו ונדמיין שאני רוצה סוג של לוגר שבכל פעם שאני נכנס ל-help סלאש משהו, אני רוצה שהוא יכתוב לי ללוג. משהו בסגנון הזה:


var express = require('express');
var router = express.Router();

router.get('/about-me', function(req, res) {
  console.log('Someone entered to help in time: ', Date.now());
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  console.log('Someone entered to help in time: ', Date.now());
  res.send('How to use');
});

module.exports = router;

לכאורה בכיף, אני פשוט אוסיף את ה-console.log בכל נתיב באפליקציה שלי. אבל זה פתרון גרוע מאוד. אם אני אשכח להוסיף console.log לאחד מהנתיבים, אני לא אקבל חיווי אם מישהו נכנס לדפי העזרה. כמו כן – עודף קוד מסורבל. למרבה השמחה, express מאפשרת לנו בקלות ליצור middleware, מיני תוכנה שרצה בנקודה מסוימת על כל הראוטר.

express route scheme with middleware

איך עושים את זה? מאוד מאוד פשוט :



var express = require('express');
var router = express.Router();

// middleware that is specific to this router
router.use(function (req, res, next) {
  console.log('Someone entered to help in time: ', Date.now());
  next();
});

router.get('/about-me', function(req, res) {
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  res.send('How to use');
});

module.exports = router;

שימו לב שה-middleare מקבל שלושה ארגומנטים, את ה-request וה-response אנחנו מכירים, אבל מה זה next? זו הפונקציה שמפעילים אם רוצים שהבקשה תמשיך הלאה בצינורות. אם לא, אז משתמשים ב-end. אנחנו נדבר על כך כאשר נמשיך לחקור את ה-API. אבל עכשיו אנחנו עדיין לומדים את תפקיד ה-middleware שהוא בעצם שרשרת של פונקציות שבהן הבקשה עוברת עד שמישהו יעשה send. למשל, כאן הוספתי middleware ל help.js:


var express = require('express');
var router = express.Router();

// middleware that is specific to this router
router.use(function (req, res, next) {
  console.log('Someone entered to help in time: ', Date.now());
  next();
});

// another middleware that is specific to this router
router.use(function (req, res, next) {
  console.log('This is another middleware');
  next();
});


router.get('/about-me', function(req, res) {
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  res.send('How to use');
});

module.exports = router;

מה יקרה כשאני אכנס ל: http://localhost:3000/help/about-me ? מאוד פשוט, אני אראה את התוצאה הזו בלוגר:

barzik@BARZIK2 MINGW64 ~/express_sample $ node app.js Example app listening on port 3000! Someone entered to help in time:  1462024700720 This is another middleware

שימו לב שכמו ב-routing, גם ב-middleware ראשון זוכה שני בוכה – כלומר ה-middleware רצות לפי סדר הכתיבה.

אני לא חייב להשתמש בפונקציות אנונימיות כמובן, אני יכול להשתמש בפונקציות עם שם. למשל:


var express = require('express');
var router = express.Router();

// middleware that is specific to this router
var myLogger = function (req, res, next) {
  console.log('Someone entered to help in time: ', Date.now());
  next();
};

// using the middleware
router.use(myLogger);

router.get('/about-me', function(req, res) {
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  res.send('How to use');
});

module.exports = router;

או אפילו במודול חיצוני פשוט, כמו למשל ליצור קובץ בשם myLogger.js שיכלול את הקוד הזה:


// middleware that is specific to this router
var myLogger = function (req, res, next) {
  console.log('Someone entered to help in time: ', Date.now());
  next();
};

module.exports = myLogger;

וה-help.js (שהוא הראוטר שלנו) יקרא לו כך:


var express = require('express');
var myLogger = require('./myLogger');
var router = express.Router();


// using the middleware
router.use(myLogger);

router.get('/about-me', function(req, res) {
  res.send('About me page');
});

router.get('/how-to-use', function (req, res) {
  res.send('How to use');
});

module.exports = router;

מי שלא זוכר מה זה export, מדובר בחלק מרכזי מתוך ה-node.js, אם הקוד שלעיל לא מובן (במיוחד איך יצרתי מודול חדש של node.js מפונקצית ה-myLogger) מומלץ לעבור שוב על המאמר שלי על מודולים ב-node.js.

אפשר לראות שהשימוש ב-middleware ברמת הראוטר ובמיוחד הסינטקס:

router.use(myLogger);

כשה-myLogger הוא מודול.

חשוד ומזכיר את הקריאה ל-router מה-app.js (זוכרים אותו? הוא מופיע למעלה) :

app.use('/help', help);

כשה-help הוא מודול.

זה בגלל שגם הראוטר הוא middleware, אבל ברמת האפליקציה. למדנו עכשיו על middlewareברמת הראוטר, במאמר הבא נלמד על middleware ברמת האפליקציה.

פוסטים נוספים שכדאי לקרוא

צילום מסך של סוואגר
יסודות בתכנות

openAPI

שימוש בתשתית הפופולרית למיפוי ותיעוד של API וגם הסבר בסיסי על מה זה API

גלילה לראש העמוד