Учебники

ExpressJS — RESTFul API

API всегда необходим для создания мобильных приложений, одностраничных приложений, использования вызовов AJAX и предоставления данных клиентам. Популярный архитектурный стиль структурирования и именования этих API-интерфейсов и конечных точек называется REST (репрезентативное состояние передачи) . HTTP 1.1 был разработан с учетом принципов REST. REST был представлен Роем ​​Филдингом в 2000 году в его «Бумажной диссертации».

RESTful URI и методы предоставляют нам практически всю информацию, необходимую для обработки запроса. Таблица, приведенная ниже, суммирует, как должны использоваться различные глаголы и как должны называться URI. Мы будем создавать API фильмов к концу; давайте теперь обсудим, как это будет структурировано.

метод URI подробности функция
ПОЛУЧИТЬ /фильмы Безопасный, кэшируемый Получает список всех фильмов и их детали
ПОЛУЧИТЬ / Фильмы / 1234 Безопасный, кэшируемый Получает подробную информацию о фильме id 1234
СООБЩЕНИЕ /фильмы N / A Создает новый фильм с предоставленной информацией. Ответ содержит URI для этого вновь созданного ресурса.
ПОЛОЖИЛ / Фильмы / 1234 идемпотент Изменяет идентификатор фильма 1234 (создает его, если он еще не существует). Ответ содержит URI для этого вновь созданного ресурса.
УДАЛЯТЬ / Фильмы / 1234 идемпотент Идентификатор фильма 1234 следует удалить, если он существует. Ответ должен содержать статус запроса.
УДАЛИТЬ или ПОСТАВИТЬ /фильмы Недействительным Должен быть недействительным. DELETE и PUT должны указывать, над каким ресурсом они работают.

Давайте теперь создадим этот API в Express. Мы будем использовать JSON в качестве нашего транспортного формата данных, так как с ним легко работать в JavaScript и есть другие преимущества. Замените файл index.js на файл movies.js, как показано в следующей программе.

index.js

var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();

var app = express();

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());

//Require the Router we defined in movies.js
var movies = require('./movies.js');

//Use the Router on the sub route /movies
app.use('/movies', movies);

app.listen(3000);

Теперь, когда мы настроили наше приложение, давайте сосредоточимся на создании API.

Начните с настройки файла movies.js. Мы не используем базу данных для хранения фильмов, а храним их в памяти; поэтому каждый раз, когда сервер перезагружается, добавленные нами фильмы исчезают. Это можно легко имитировать с помощью базы данных или файла (с помощью модуля node fs).

После того, как вы импортируете Express, создайте маршрутизатор и экспортируйте его, используя module.exports

var express = require('express');
var router = express.Router();
var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];

//Routes will go here
module.exports = router;

ПОЛУЧИТЬ маршруты

Давайте определим маршрут GET для получения всех фильмов —

router.get('/', function(req, res){
   res.json(movies);
});

Чтобы проверить, работает ли это нормально, запустите ваше приложение, затем откройте терминал и введите —

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET 
localhost:3000/movies

Следующий ответ будет отображаться —

[{"id":101,"name":"Fight Club","year":1999,"rating":8.1},
{"id":102,"name":"Inception","year":2010,"rating":8.7},
{"id":103,"name":"The Dark Knight","year":2008,"rating":9},
{"id":104,"name":"12 Angry Men","year":1957,"rating":8.9}]

У нас есть маршрут, чтобы получить все фильмы. Теперь давайте создадим маршрут для получения конкретного фильма по его идентификатору.

router.get('/:id([0-9]{3,})', function(req, res){
   var currMovie = movies.filter(function(movie){
      if(movie.id == req.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      res.json(currMovie[0])
   } else {
      res.status(404);//Set status to 404 as movie was not found
      res.json({message: "Not Found"});
   }
});

Это даст нам фильмы в соответствии с идентификатором, который мы предоставили. Чтобы проверить вывод, используйте следующую команду в вашем терминале —

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET 
localhost:3000/movies/101

Вы получите следующий ответ —

{"id":101,"name":"Fight Club","year":1999,"rating":8.1}

Если вы посещаете неверный маршрут, он выдаст ошибку not GET, а если вы посетите действующий маршрут с идентификатором, который не существует, он выдаст ошибку 404.

Мы закончили с маршрутами GET, теперь давайте перейдем к маршруту POST .

POST маршрут

Используйте следующий маршрут для обработки POST- данных —

router.post('/', function(req, res){
   //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      var newId = movies[movies.length-1].id+1;
      movies.push({
         id: newId,
         name: req.body.name,
         year: req.body.year,
         rating: req.body.rating
      });
      res.json({message: "New movie created.", location: "/movies/" + newId});
   }
});

Это создаст новый фильм и сохранит его в переменной movies. Чтобы проверить этот маршрут, введите следующий код в своем терминале —

curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" http://localhost:3000/movies

Следующий ответ будет отображаться —

{"message":"New movie created.","location":"/movies/105"}

Чтобы проверить, было ли это добавлено к объекту movies, снова запустите запрос get для / movies / 105 . Следующий ответ будет отображаться —

{"id":105,"name":"Toy story","year":"1995","rating":"8.5"}

Давайте перейдем к созданию маршрутов PUT и DELETE.

PUT маршрут

Маршрут PUT почти совпадает с маршрутом POST. Мы будем указывать идентификатор для объекта, который будет обновлен / создан. Создайте маршрут следующим образом.

router.put('/:id', function(req, res){
   //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !req.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(req.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new
         movies.push({
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         });
         res.json({message: "New movie created.", location: "/movies/" + req.params.id});
      } else {
         //Update existing movie
         movies[updateIndex] = {
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         };
         res.json({message: "Movie id " + req.params.id + " updated.", 
            location: "/movies/" + req.params.id});
      }
   }
});

Этот маршрут будет выполнять функцию, указанную в таблице выше. Он обновит объект новыми деталями, если он существует. Если он не существует, он создаст новый объект. Чтобы проверить маршрут, используйте следующую команду curl. Это обновит существующий фильм. Чтобы создать новый фильм, просто измените идентификатор на несуществующий идентификатор.

curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5" 
http://localhost:3000/movies/101

отклик

{"message":"Movie id 101 updated.","location":"/movies/101"}

УДАЛИТЬ маршрут

Используйте следующий код для создания маршрута удаления.

router.delete('/:id', function(req, res){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(req.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      res.json({message: "Not found"});
   } else {
      movies.splice(removeIndex, 1);
      res.send({message: "Movie id " + req.params.id + " removed."});
   }
});

Проверьте маршрут так же, как мы проверяли другие маршруты. При успешном удалении (например, с идентификатором 105) вы получите следующий вывод:

{message: "Movie id 105 removed."}

Наконец, наш файл movies.js будет выглядеть следующим образом.

var express = require('express');
var router = express.Router();
var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];
router.get('/:id([0-9]{3,})', function(req, res){
   var currMovie = movies.filter(function(movie){
      if(movie.id == req.params.id){
         return true;
      }
   });
   
   if(currMovie.length == 1){
      res.json(currMovie[0])
   } else {
      res.status(404);  //Set status to 404 as movie was not found
      res.json({message: "Not Found"});
   }
});
router.post('/', function(req, res){
   //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      var newId = movies[movies.length-1].id+1;
      movies.push({
         id: newId,
         name: req.body.name,
         year: req.body.year,
         rating: req.body.rating
      });
      res.json({message: "New movie created.", location: "/movies/" + newId});
   }
});

router.put('/:id', function(req, res) {
   //Check if all fields are provided and are valid:
   if(!req.body.name ||
      !req.body.year.toString().match(/^[0-9]{4}$/g) ||
      !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !req.params.id.toString().match(/^[0-9]{3,}$/g)){
      res.status(400);
      res.json({message: "Bad Request"});
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(req.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new
         movies.push({
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         });
         res.json({
            message: "New movie created.", location: "/movies/" + req.params.id});
      } else {
         //Update existing movie
         movies[updateIndex] = {
            id: req.params.id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
         };
         res.json({message: "Movie id " + req.params.id + " updated.",
            location: "/movies/" + req.params.id});
      }
   }
});

router.delete('/:id', function(req, res){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(req.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      res.json({message: "Not found"});
   } else {
      movies.splice(removeIndex, 1);
      res.send({message: "Movie id " + req.params.id + " removed."});
   }
});
module.exports = router;

Это завершает наш REST API. Теперь вы можете создавать гораздо более сложные приложения, используя этот простой архитектурный стиль и Express.