Pull to refresh

Разработка REST API на Express, Restify, hapi и LoopBack

Reading time 5 min
Views 44K
Original author: Alex Gorbatchev
Если вы работаете над Node.js приложением, то есть все шансы, что у него появится некое API, которое будет использовано вами или кем-то другим. Наверняка это будет REST API и перед вами возникнет дилемма — какие инструменты и подходы использовать. Ведь выбор так широк…

image

Благодаря невероятно активному сообществу Node.js, количество результатов на NPM по запросу «rest» зашкаливает. У каждого есть свои реализации и подходы, но у некоторых есть что-то общее в создании REST API на Node.js.



Express


Наиболее распространённый подход — дать доступ к ресурсам с помощью Express. Это даст лёгкий старт, но в последствии будет становиться всё более тяжелым.

Пример
Используя Router последней версии Express 4.x, ресурс будет выглядеть примерно так:

var express = require('express');
var Item = require('models').Item;
var app = express();
var itemRoute = express.Router();
 
itemRoute.param('itemId', function(req, res, next, id) {
  Item.findById(req.params.itemId, function(err, item) {
    req.item = item;
    next();
  });
});
 
itemRoute.route('/:itemId')
  .get(function(req, res, next) {
    res.json(req.item);
  })
  .put(function(req, res, next) {
    req.item.set(req.body);
    req.item.save(function(err, item) {
      res.json(item);
    });
  })
  .post(function(req, res, next) {
    var item = new Item(req.body);
    item.save(function(err, item) {
      res.json(item);
    });
  })
  .delete(function(req, res, next) {
    req.item.remove(function(err) {
      res.json({});
    });
  })
  ;
 
app.use('/api/items', itemRoute);
app.listen(8080);


Плюсы Минусы
  1. Низкий порог вхождения, Express — это практически стандарт Node.js-приложения.
  2. Полная кастомизация.

  1. Все ресурсы необходимо создавать вручную и, в результате, появится много повторного кода или хуже — собственная библиотека.
  2. Каждый ресурс требует тестирования или простой проверки на 500-ую ошибку.
  3. Рефакторинг станет болезненным, так как будет необходимо править всё и везде.
  4. Нету стандартного подхода, нужно искать свой.

Express — это отличный старт, но в итоге вы почувствуете боль от «своего собственного» подхода.


Restify


Restify — относительно старый игрок на поле Node.js API, но очень стабильный и активно разрабатываемый. Он создан для построения правильных REST-сервисов и намеренно похож на Express.

Пример
Так как он похож на Express, то и синтаксис практически такой же:

var restify = require('restify');
var Item = require('models').Item;
var app = restify.createServer()
 
app.use(function(req, res, next) {
  if (req.params.itemId) {
    Item.findById(req.params.itemId, function(err, item) {
      req.item = item;
      next();
    });
  }
  else {
    next();
  }
});
 
app.get('/api/items/:itemId', function(req, res, next) {
  res.send(200, req.item);
});
 
app.put('/api/items/:itemId', function(req, res, next) {
  req.item.set(req.body);
  req.item.save(function(err, item) {
    res.send(204, item);
  });
});
 
app.post('/api/items/:itemId', function(req, res, next) {
  var item = new Item(req.body);
  item.save(function(err, item) {
    res.send(201, item);
  });
});
 
app.delete('/api/items/:itemId', function(req, res, next) {
  req.item.remove(function(err) {
    res.send(204, {});
  });
});
 
app.listen(8080);


Плюсы Минусы
  1. Поддержка DTrace, если API работает на платформе, которая его поддерживает.
  2. Нет такого лишнего функционала, как шаблоны и рендеринг.
  3. Ограничение частоты запросов (throttling).
  4. Поддержка SPDY

Минусы такие же как и у Express — много лишней работы.



hapi


hapi — менее известный фреймворк, который разрабатывается командой Walmart Labs. В отличие от Express и Restify у него несколько другой подход, предоставляющий больший функционал сразу из коробки.

Пример
var Hapi = require('hapi');
var Item = require('models').Item;
var server = Hapi.createServer('0.0.0.0', 8080);
 
server.ext('onPreHandler', function(req, next) {
  if (req.params.itemId) {
    Item.findById(req.params.itemId, function(err, item) {
      req.item = item;
      next();
    });
  }
  else {
    next();
  }
});
 
server.route([
  {
    path: '/api/items/{itemId}',
    method: 'GET',
    config: {
      handler: function(req, reply) {
        reply(req.item);
      }
    }
  },
  {
    path: '/api/items',
    method: 'PUT',
    config: {
      handler: function(req, reply) {
        req.item.set(req.body);
        req.item.save(function(err, item) {
          res.send(204, item);
        });
      }
    }
  },
  {
    path: '/api/items',
    method: 'POST',
    config: {
      handler: function(req, reply) {
        var item = new Item(req.body);
        item.save(function(err, item) {
          res.send(201, item);
        });
      }
    }
  },
  {
    path: '/api/items/{itemId}',
    method: 'DELETE',
    config: {
      handler: function(req, reply) {
        req.item.remove(function(err) {
          res.send(204, {});
        });
      }
    }
  }
]);
 
server.start();


Плюсы Минусы
  1. Полный контроль над приёмом запросов.
  2. Детальная справка с генерацией документации.

hapi, также как Express и Restify, даёт отличные возможности, но как их использовать, вы должны понять сами.

Express, Restify и hapi отличные решения для старта, но, если вы планируете развивать API, то они могут стать плохим выбором.


LoopBack


LoopBack от StrongLoop — это полноценный Node.js-фреймворк для соединения приложений с данными через REST API. Он перенимает мантру "договорённость в конфигурации", ставшей популярной в Ruby on Rails.

Пример

var loopback = require('loopback');
var Item = require('./models').Item;
var app = module.exports = loopback();
 
app.model(Item);
app.use('/api', loopback.rest());
app.listen(8080);

Много волшебства происходит за кулисами, но всего шесть строчек кода создадут для вас эти ресурсы:
GET /items
GET /items/count
GET /items/findOne
GET /items/{id}
GET /items/{id}/exists
POST /items
PUT /items
PUT /items/{id}
DELETE /items/{id}

image

Чтобы легко изучить свой API, достаточно подключить встроенный модуль explorer:
var explorer = require('loopback-explorer');
app.use('/explorer', explorer(app, {basePath: '/api'}));


Теперь откройте localhost:8080/explorer и получите эту крутую документацию:
image

Пример на LoopBack достаточно простой, но что на счёт RPC-ресурса?
var loopback = require('loopback');
var explorer = require('loopback-explorer');
var remoting = require('strong-remoting');
var Item = require('./models').Item;
var app = module.exports = loopback();
var rpc = remoting.create();
 
function echo(ping, callback) {
  callback(null, ping);
}
 
echo.shared = true;
echo.accepts = {arg: 'ping'};
echo.returns = {arg: 'echo'};
 
rpc.exports.system = {
  echo: echo
};
 
app.model(Item);
app.use('/api', loopback.rest());
app.use('/explorer', explorer(app, {basePath: '/api'}));
app.use('/rpc', rpc.handler('rest'));
app.listen(8080);


Теперь можно делать так:
$ curl "http://localhost:8080/rpc/system/echo?ping=hello"
{
  "echo": "hello"
}


image

Плюсы Минусы
  1. Очень быстрая разработка REST API.
  2. Договорённость в конфигурации.
  3. Встроенные готовые модели.
  4. Поддержка RPC.
  5. Полностью настраиваемый.
  6. Обширная документация.
  7. Команда, работающая над проектом на постоянной основе и являющаяся основной компанией-контрибутором в Node.js.
  8. Коммерческая поддержка.

Порог вхождения немного высок, так как фреймворк состоит из множества деталей.



Что дальше


Only registered users can participate in poll. Log in, please.
Слышали ли вы раньше о LoopBack?
21.73% Да 148
78.27% Не слышал 533
681 users voted. 113 users abstained.
Only registered users can participate in poll. Log in, please.
Пробовали ли вы работать с LoopBack?
12.14% Да и понравилось 72
3.04% Да и не понравилось 18
84.82% Нет 503
593 users voted. 173 users abstained.
Tags:
Hubs:
+15
Comments 25
Comments Comments 25

Articles