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.