Node.js:Jak vytvořit REST API část 2

ahoj komunito,

v této části dokončíme naše REST API, pokud jste neviděli první část, můžete ji zkontrolovat zde.

Začněme

celou tuto část pokryjeme :

  • vytvořit nový film
  • získat film podle ID
  • získejte všechny filmy
  • aktualizovat film
  • smazat film
  • nakonec si promluvíme o konceptu middlewaru a o tom, jak jej postavit a implementovat do našeho API

nejprve musíme vytvořit model filmu, takže ve složce models vytvoříme soubor s názvem movie-model.js :

//movie-model.js
const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const userSchema = new Schema({
  title: { type: String, required: true },
  description: { type: String, required: true},
  creator: { type: String, required: true }
});

module.exports = mongoose.model('Movie', userSchema);

nyní je čas vytvořit ovladač filmu ve složce controllers vytvoříme soubor movie-controller.js :

//movie-controller.js
const { validationResult } = require('express-validator');
const ObjectId = require('mongoose').Types.ObjectId;
const User = require('../models/user-model');
const Movie = require('../models/movie-model');

// CREATE MOVIE 
const createMovie = async (req, res) => {};

// GET MOVIE BY ID 
const getMovieById = async (req, res) => {};

// GET ALL MOVIES 
const getAllMovies = async (req, res) => {};

// UPDATE MOVIE 
const updateMovie = async (req, res) => {};

// DELETE MOVIE 
const deleteMovie = async (req, res) => {};

module.exports = {
    createMovie,
    getMovieById,
    getAllMovies,
    updateMovie,
    deleteMovie
};

nebojte se, tyto funkce vezmeme jednu po druhé později, teď potřebujeme nastavit filmové trasy, které vytváříme movie-routes.js ve složce tras:

//movie-routes.js
const { check } = require('express-validator');
const movieController = require('../controllers/movie-controller');
const express = require('express');
const router = express.Router();

const {
    createMovie,
    getMovieById,
    getAllMovies,
    updateMovie,
    deleteMovie } = movieController;

const validation = [ 
    check('title').not().isEmpty(),
     check('description').not().isEmpty(),
     check('creator').not().isEmpty()]

// CREATE MOVIE 
router.post('/',validation,createMovie);

// GET MOVIE BY ID 
router.get('/:id',getMovieById);

// GET ALL MOVIES
router.get('/',getAllMovies);

// UPDATE MOVIE 
router.patch('/:id',validation,updateMovie);

// DELETE MOVIE 
router.delete('/:id',deleteMovie);

module.exports = router;

poslední věc, kterou musíme udělat, než se ponoříme do movie-controller.js funkcí je přidat movie-routes v index.js soubor:

//index.js
const movieRoutes = require('./routes/movie-routes'); 

app.use('/api/movie', movieRoutes);

nyní začněme s první funkcí createMovie :

// CREATE MOVIE 
const createMovie = async (req, res) => {

      const errors = validationResult(req);
      if (!errors.isEmpty()) 
         return res.status(400).json({ errors: errors.array() });

      const { title, description, creator } = req.body;
      let  existingUser = await User.findOne({ _id: creator });
      if (!existingUser)
         return res.status(400).json({error : 'invalid user'});

      const movie = new Movie({
          title,
          description,
          creator
      });

      try {
          await movie.save();
          res.status(200).json({
          message: "movie created successfully",
          movie: movie
        })
      } catch (error) {
           res.status(500).json(error.message);
      }
};

dovolte mi vysvětlit logiku nejprve zkontrolujeme výsledek ověření dat, pokud se některé ověření nezdařilo vrátíme chybu, jinak vezmeme název všech dat, popis a tvůrce =ID uživatele, pokud neexistuje žádný uživatel s tímto ID, vrátíme také chybu nakonec vytvoříme objekt movie a uložte jej do databáze, poté vrátíte objekt json, který obsahuje úspěšně zprávu a film byl vytvořen.

  • getMovieById :
// GET MOVIE BY ID 
const getMovieById = async (req, res) => {

      const movieId = req.params.id;
      if(!ObjectId.isValid(movieId))
           return res.status(400).json({error : 'Invalid id'});

        try {
            const movie = await Movie.findById(movieId);
            if(!movie) 
               return res.status(404).json('there is no movie with this id.');
             res.status(200).json(movie)
        } catch (err) {
             res.status(500).json({error:err.message});
        } 
};

logika je jednoduchá tato funkce získá id filmu jako parametr a zkontroluje, zda je to platné id, pak hledáme v databázi, jinak vrátíme zprávu, že žádný film s tímto id neexistuje.

  • getAllMovies :
// GET ALL MOVIES 
const getAllMovies = async (req, res) => {

    try {
        const movies = await Movie.find();
        return res.status(200).json(movies)
    } catch (err) {
        return res.status(500).json({message :'server error'})
    }

};
  • updateMovie :
// UPDATE MOVIE 
const updateMovie = async (req, res) => {

    const errors = validationResult(req);
     if(!errors.isEmpty()) 
        return res.status(400).json({ errors: errors.array() });

    const { title, description, creator } = req.body;
    const movieId = req.params.id;
    if(!ObjectId.isValid(movieId))
           return res.status(400).json({error : 'Invalid id'});

     try {
         const movie = await Movie.findById(movieId);
         if(!movie)
            return res.status(404).json({message: 'movie not found.'});
         await movie.updateOne({
             title,
             description,
             creator
         })
         return res.status(200).json(movie)
     } catch (err) {
         console.log(err.message);
         res.status(500).json({error : 'server error'});

     }
};
  • deleteMovie :
//DELETE MOVIE 
const deleteMovie = async (req, res) => {

    const movieId = req.params.id ; 
    if(!ObjectId.isValid(movieId))
           return res.status(400).json({error : 'Invalid id'});

    try {
        const movie = await Movie.findById(movieId);
        if(!movie) 
           return res.status(404).json({message : 'there is no movie with this id.'});

        await movie.remove();
        res.status(200).json({message : 'movie removed'});
    } catch (err) {
        console.log(err.message);
        res.status(500).json({error : 'server error'});
    }

};

nyní potřebujeme vytvořit ověřovací middleware, který ochrání některé z našich tras API, protože v našem API může kdokoli přidávat, aktualizovat a mazat filmy bez ověření, a to je špatné.

Funkce middlewaru jsou funkce, které mají přístup k objektu požadavku (req), objektu odezvy (res) a další funkci middlewaru v cyklu žádost-odpověď aplikace. Další middlewarová funkce je běžně označována proměnnou s názvem next.

ve složce middlewaru vytvořte soubor s názvem auth.js :

const jwt = require('jsonwebtoken');

module.exports = function(req, res, next){

    const token = req.header('x-auth-token');
    if(!token) 
       return res.status(401).json({ message: 'No token, authorization dnied.'});
    try{
        const decoded = jwt.verify(token,'supersecretkey');
        req.user = decoded.user;
        next();
    }catch(err){
        res.status(401).json({ message: 'Token is not valid' });
    }
}

nech mě to vysvětlit :
když se uživatel přihlásí nebo zaregistruje API vrací token, tento token značí, že uživatel je ověřen, ale abychom ho mohli použít, musíme ho přidat do hlavičky jako 'x-auth-token' s tím, že když chce uživatel přidat film auth meddleware získá tento token z hlavičky a otestuje, zda je to platný token, pak může přidat film, jinak middleware vrátí chybu, že token není platný.

abychom ochránili naše API, stačí importovat auth middleware do movie-routes.js a přidejte jej jako druhý argument do všech tras, které chceme chránit.

//movie-routes.js
// CREATE MOVIE 
router.post('/',[auth, validation],createMovie);

// UPDATE MOVIE 
router.patch('/:id',[auth, validation],updateMovie);

// DELETE MOVIE 
router.delete('/:id',auth, deleteMovie);

nezapomeňte importovat 'auth.js'.

pojďme otestovat naše REST API s pošťákem:

  • nejprve se musíme ověřit

  • přidat nový film bez přidání tokenu do záhlaví

  • přidat nový film s tokenem v záhlaví (stačí zkopírovat token a přejít do záhlaví přidat nový klíč 'x-auth-token' a dát token jako hodnotu)

  • získat film podle ID

  • získat všechny filmy

  • aktualizovat film

  • smazat film

nyní můžeme říci, že naše API je hotové, pokrýváme všechny základy a pravidla, která budete potřebovat při vytváření vlastního REST API.

Děkuji.