Supposons que je veuille avoir REST points finaux qui ressemblent à peu près à ceci:
/user/
/user/user_id
/user/user_id/items/
/user/user_id/items/item_id
CRUD sur chaque si a du sens. Par exemple,/user POST crée un nouvel utilisateur, GET extrait tous les utilisateurs./user/ser_id GET ne récupère que cet utilisateur.
Les éléments sont spécifiques à l'utilisateur, donc je les mets sous ser_id, qui est un utilisateur particulier.
Maintenant, pour rendre le routage Express modulaire, j'ai créé quelques instances de routeur. Il existe un routeur pour l'utilisateur et un routeur pour l'élément.
var userRouter = require('express').Router();
userRouter.route('/')
.get(function() {})
.post(function() {})
userRouter.route('/:user_id')
.get(function() {})
var itemRouter = require('express').Router();
itemRouter.route('/')
.get(function() {})
.post(function() {})
itemRouter.route('/:item_id')
.get(function() {})
app.use('/users', userRouter);
// Now how to add the next router?
// app.use('/users/', itemRouter);
L'URL de item
est issue de la hiérarchie des URL de user
. Maintenant, comment obtenir l'URL avec /users
quel que soit l'utilisateur, mais la route plus spécifique de /user/*user_id*/items/
vers itemRouter? Et aussi, j'aimerais que user_id soit aussi accessible à itemRouter, si possible.
Vous pouvez imbriquer des routeurs en les connectant comme middleware sur un autre routeur, avec ou sans params
.
Vous devez transmettre {mergeParams: true}
au routeur enfant si vous souhaitez accéder au params
à partir du routeur parent.
mergeParams
a été introduit dans Express 4.5.0
(5 juillet 2014)
Dans cet exemple, la itemRouter
est attachée à la userRouter
de la route /:userId/items
.
Cela se traduira par les itinéraires possibles suivants:
GET /user
-> hello user
GET /user/5
-> hello user 5
GET /user/5/items
-> hello items from user 5
GET /user/5/items/6
-> hello item 6 from user 5
var express = require('express');
var app = express();
var userRouter = express.Router();
// you need to set mergeParams: true on the router,
// if you want to access params from the parent router
var itemRouter = express.Router({mergeParams: true});
// you can nest routers by attaching them as middleware:
userRouter.use('/:userId/items', itemRouter);
userRouter.route('/')
.get(function (req, res) {
res.status(200)
.send('hello users');
});
userRouter.route('/:userId')
.get(function (req, res) {
res.status(200)
.send('hello user ' + req.params.userId);
});
itemRouter.route('/')
.get(function (req, res) {
res.status(200)
.send('hello items from user ' + req.params.userId);
});
itemRouter.route('/:itemId')
.get(function (req, res) {
res.status(200)
.send('hello item ' + req.params.itemId + ' from user ' + req.params.userId);
});
app.use('/user', userRouter);
app.listen(3003);
Je voulais un exemple spécifique de création de routes imbriquées de manière très gérable dans Express 4. Il s’agissait du premier résultat de la recherche pour "routes imbriquées dans express". Voici une API qui aurait plusieurs routes à scinder, par exemple.
./ index.js:
var app = require('express')();
// anything beginning with "/api" will go into this
app.use('/api', require('./routes/api'));
app.listen(3000);
./ routes/api/index.js:
var router = require('express').Router();
// split up route handling
router.use('/products', require('./products'));
router.use('/categories', require('./categories'));
// etc.
module.exports = router;
./ routes/api/products.js:
var router = require('express').Router();
// api/products
router.get('/', function(req, res) {
res.json({ products: [] });
});
// api/products/:id
router.get('/:id', function(req, res) {
res.json({ id: req.params.id });
});
module.exports = router;
J'ai remarqué des commentaires sur la "structure de dossiers". C'est implicite dans ceci cependant pas évident ainsi j'ai ajouté la section ci-dessous. Voici un exemple spécifique de structure de dossiers imbriqués pour les itinéraires.
index.js
/api
index.js
/admin
index.js
/users
index.js
list.js
/permissions
index.js
list.js
Ceci est plus un exemple général du fonctionnement du noeud. Si vous utilisez "index.js" dans les dossiers de la même manière que "index.html" dans les pages Web pour un répertoire par défaut, il sera facile de faire évoluer votre organisation en fonction de la récursivité sans modifier vos points d'entrée en code. "index.js" est le document utilisé par défaut lors de l'utilisation de requis dans un répertoire.
contenu de index.js
const express = require('express');
const router = express.Router();
router.use('/api', require('./api'));
module.exports = router;
contenu de /api/index.js
const express = require('express');
const router = express.Router();
router.use('/admin', require('./admin'));
module.exports = router;
contenu de /api/admin/index.js
const express = require('express');
const router = express.Router();
router.use('/users', require('./users'));
router.use('/permissions', require('./permissions'));
module.exports = router;
contenu de /api/admin/users/index.js
const express = require('express');
const router = express.Router();
router.get('/', require('./list'));
module.exports = router;
Il existe peut-être quelques problèmes DRY ici, mais cela se prête bien à l'encapsulation des préoccupations.
Pour votre information, je me suis récemment lancé dans l'actionhero et je l'ai trouvé complet en fonctions de sockets et de tâches, plus comme un véritable framework tout en renversant le paradigme REST. Vous devriez probablement y jeter un coup d'œil en allant nu avec w/express.
var userRouter = require('express').Router();
var itemRouter = require('express').Router({ mergeParams: true });
userRouter.route('/')
.get(function(req, res) {})
.post(function(req, res) {})
userRouter.route('/:user_id')
.get(function() {})
itemRouter.route('/')
.get(function(req, res) {})
.post(function(req, res) {})
itemRouter.route('/:item_id')
.get(function(req, res) {
return res.send(req.params);
});
app.use('/user/', userRouter);
app.use('/user/:user_id/item', itemRouter);
La clé de la deuxième partie de votre question concerne l'utilisation de l'option mergeParams.
var itemRouter = require('express').Router({ mergeParams: true });
De /user/jordan/item/cat
je reçois une réponse:
{"user_id":"jordan","item_id":"cat"}
Utilisation de la solution @Jason Sebring et adaptation à TypeScript.
server.ts
import Routes from './api/routes';
app.use('/api/', Routes);
/ api/routes/index.ts
import { Router } from 'express';
import HomeRoutes from './home';
const router = Router();
router.use('/', HomeRoutes);
// add other routes...
export default router;
/ api/routes/home.ts
import { Request, Response, Router } from 'express';
const router = Router();
router.get('/', (req: Request, res: Response) => {
res.json({
message: 'Welcome to API',
});
});
export default router;