Description
Cet article décrit comment mettre en place un serveur avec Node.js et Express, se connecter à une base de données MongoDB et créer des interfaces back-end simples. Le projet front-end utilise Vue 2 pour un système de gestion hôtelière. En lisant cet article, vous apprendrez à vous connecter à MongoDB, à exécuter des commandes de manipulation de la base de données, à gérer les requêtes cross-origin depuis le front-end et à respecter les bonnes pratiques lors de l'appel des endpoints back-end.
Présentation du projet back-end

Nous nous concentrons ici sur la connexoin à MongoDB et les cmomandes associées. Les autres fichiers ne sont pas détaillés.
- Ouvrez un terminal et exécutez
mongodpour démarrer la base de données (ne fermez pas la fenêtre). - Ouvrez un nouveau terminal et exécutez
mongo(ne fermez pas la fenêtre).
bin/www.js
Ce fichier met en place le serveur HTTP. Il écoute sur le port 4000.
const app = require('../app');
const debug = require('debug')('mgserver:server');
const http = require('http');
function normalizePort(val) {
const port = parseInt(val, 10);
if (isNaN(port)) return val;
if (port >= 0) return port;
return false;
}
const port = normalizePort(process.env.PORT || '4000');
app.set('port', port);
const server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function onError(error) {
if (error.syscall !== 'listen') throw error;
const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' nécessite des privilèges élevés');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' est déjà utilisé');
process.exit(1);
break;
default:
throw error;
}
}
function onListening() {
const addr = server.address();
const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
debug('En écoute sur ' + bind);
}
db/index.js
const mongoose = require('mongoose');
mongoose.connect("mongodb://127.0.0.1:27017/Mango");
const connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'Erreur de connexion :'));
connection.once('open', () => {
console.log('Connexion à la base de données réussie');
});
const userSchema = new mongoose.Schema({
username: { type: String },
password: { type: String }
});
const UserModel = mongoose.model("users", userSchema);
module.exports = {
UserModel
};
L'URI mongodb://127.0.0.1:27017/Mango utilise le protocole MongoDB, l'adresse locale (127.0.0.1), le port par défaut 27017, et la base de données nommée Mango (créée automatiquement si elle n'existe pas).
router/user/User.js
Ce fichier expose un endpoint d'inscription.
const express = require('express');
const { UserModel } = require('../../db');
const router = express.Router();
router.post('/register', async (req, res, next) => {
try {
const form = req.body;
const existingUser = await UserModel.find(form);
if (existingUser.length > 0) {
return res.json({
code: 0,
message: 'Nom d\'utilisateur déjà existant'
});
}
const newUser = await UserModel.create(form);
if (newUser) {
return res.json({
code: 0,
message: 'Inscription réussie'
});
} else {
return res.json({
code: 1,
message: 'Échec de l\'inscription'
});
}
} catch (err) {
console.error(err);
return res.json({
code: 0,
message: 'Erreur lors de l\'inscription'
});
}
});
module.exports = router;
app.js
const createError = require('http-errors');
const express = require('express');
const app = express();
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
require("./db/index.js");
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
const userRouter = require('./router/user/User.js');
// La route de base définie ici + celle du sous-router constitue le chemin complet.
// Exemple : si l'on utilise "/api/user", l'URL complète sera "/api/user/register".
app.use( "/user", userRouter);
// Gestion 404
app.use((req, res, next) => {
next(createError(404));
});
// Gestionnaire d'erreurs
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Projet front-end
Configuration du proxy CORS
Dans vue.config.js, nous utilisons un proxy pour éviter les problèmes de cross-origin.
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
pathRewrite: { '^/api': '' },
logLevel: 'debug'
}
}
}
Fichier request.js
Nous configurons Axios avec des intercepteurs pour la gestion des chargements et des erreurs.
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import axios from 'axios';
import BASE_URL from '../../config/index';
const instance = axios.create({
baseURL: BASE_URL,
timeout: 5000,
headers: {}
});
instance.interceptors.request.use(config => {
NProgress.start();
return config;
}, error => {
NProgress.done();
return Promise.reject(error);
});
instance.interceptors.response.use(response => {
NProgress.done();
return response;
}, error => {
NProgress.done();
return Promise.reject(error);
});
const get = async (url, params) => {
const { data } = await instance.get(url, params);
return data;
};
const post = async (url, params) => {
const { data } = await instance.post(url, params);
return data;
};
const setToken = () => {
instance.defaults.headers.common['token'] = '123';
};
export { get, post, setToken };
Plugin myPlugin.js
Ce plugin mixe dans Vue les méthodes $get, $post, etc., via un mixin global.
import { get, post, setToken } from '../utils/request';
export default {
install(Vue) {
Vue.mixin({
methods: {
$get(url, params) { return get(url, params); },
$post(url, params) { return post(url, params); },
$setToken() { setToken(); },
$msg_s(message, duration = 3000) {
this.$message({ showClose: true, message, type: 'success', duration });
},
$msg_w(message, duration = 3000) {
this.$message({ showClose: true, message, type: 'warning', duration });
},
$msg_e(message, duration = 3000) {
this.$message({ showClose: true, message, type: 'error', duration });
},
$con_f(message) {
return this.$confirm(message)
.then(() => true)
.catch(() => {});
}
}
});
}
};
Composant registerView.vue
Dans la page d'inscritpion, lors de la soumission du formulaire, on appelle l'endpoint /user/register via le proxy (attention : le préfixe /api est utilisé pour le proxy, pas pour la route réelle).
submitForm(formName) {
this.$refs[formName].validate(async (valid) => {
if (valid) {
const res = await this.$post('/api/user/register', this.loginForm);
// this.$router.push('/login');
} else {
return false;
}
});
}
Visualisation des utilisateurs enregistrés dans MongoDB

