Przypuśćmy, że chcę mieć odpoczynek punktów końcowych, które wyglądają mniej więcej tak:

/user/
/user/user_id 

/user/user_id/items/
/user/user_id/items/item_id

Crud na każdy, jeśli ma sens. Na przykład / User Post tworzy nowego użytkownika, pobieraj pobieranie wszystkich użytkowników. / Użytkownik / User_id Get Fetches tylko tego użytkownika.

Przedmioty są specyficzne dla użytkownika, więc umieściłem je pod user_id , który jest konkretnym użytkownikiem.

Teraz, aby wykonać ekspresowe routing modułowy, wykonałem kilka instancji routera. Jest router dla użytkownika i router dla przedmiotu.

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);

URL do item jest potomkami hierarchii adresów URL user. Teraz jak uzyskać adres URL z /users cokolwiek do Użytkownika, ale bardziej konkretna trasa /user/*user_id*/items/ do ItemOutera? A także, chciałbym, aby user_id był dostępny do ItemRoutera, jeśli to możliwe.

150
huggie 12 sierpień 2014, 13:30

5 odpowiedzi

Najlepsza odpowiedź

Możesz gniazdować routery, dołączając je jako Middleware na innym routerze, z lub bez params .

Musisz przejść {mergeParams: true} do routera dla dzieci, jeśli chcesz uzyskać dostęp do params z routera macierzystego.

mergeParams został wprowadzony w Express 4.5.0 (lipca 5 2014)

W tym przykładzie itemRouter jest przymocowany do userRouter na trasie /:userId/items

Spowoduje to następujące możliwe trasy:

GET /user - & gt; hello user
GET /user/5 - & gt; hello user 5
GET /user/5/items - & gt; hello items from user 5
GET /user/5/items/6 - & gt; 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);
306
Willem D'Haeseleer 26 sierpień 2015, 20:57

Zarządzanie zagnieżdżonymi trasami ...

Chciałem konkretny przykład wykonania zagnieżdżonych tras w bardzo łatwy sposób w ekspresji 4, a to był górny wynik wyszukiwania dla "zagnieżdżonych tras w ekspresji". Oto interfejs API, który miałby wiele tras, które musiałyby zostać rozbite na przykład.

./ index.js:

var app = require('express')();

// anything beginning with "/api" will go into this
app.use('/api', require('./routes/api'));

app.listen(3000);

./ trasy / 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;

./ trasy / 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;

Przykład gniazdowy w strukturze folderu

Zauważyłem kilka komentarzy na temat "zagnieżdżania struktury folderów". Obsługuje się, jednak nie jest oczywiste, więc dodałem poniższy sekcję. Oto określony przykład struktury folderu dla tras .

index.js
/api
  index.js
  /admin
    index.js
    /users
      index.js
      list.js
    /permissions
      index.js
      list.js

Jest to bardziej ogólny przykład, jak działa węzeł. Jeśli używasz "index.js" w folderach, podobnie jak "index.html" działa na stronach internetowych dla domyślnych katalogów, będzie to łatwe w skalowaniu organizacji opartej na rekurencji bez zmiany punktów wpisowych do kodu. "index.js" jest domyślnym dokumentem dostępnym podczas korzystania z wymagać w katalogu.

Spis treści index.js

const express = require('express');
const router = express.Router();
router.use('/api', require('./api'));
module.exports = router;

Spis treści /Pi/index.js

const express = require('express');
const router = express.Router();
router.use('/admin', require('./admin'));
module.exports = router;

Zawartość / hapi/admin/index.js

const express = require('express');
const router = express.Router();
router.use('/users', require('./users'));
router.use('/permissions', require('./permissions'));
module.exports = router;

Spis treści /api/admin/users/index.js

const express = require('express');
const router = express.Router();
router.get('/', require('./list'));
module.exports = router;

Prawdopodobnie istnieje kilka suchych problemów, ale nadaje się dobrze do kapsułki obaw.

FYI, ostatnio dostałem się do Actionhero i stwierdziłem, że jest to pełne funkcjonalne w / gniazda i zadania, bardziej jak prawdziwa ramy all-in-one odwracając paradygmat resztę na głowie. Prawdopodobnie powinieneś to sprawdzić nad nim w / Express.

139
Jason Sebring 23 grudzień 2017, 21:25
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);

Kluczem do drugiej części twojego pytania jest użycie opcji MergeParams

var itemRouter = require('express').Router({ mergeParams: true }); 

Z /user/jordan/item/cat otrzymuję odpowiedź:

{"user_id":"jordan","item_id":"cat"}
8
Jordonias 14 sierpień 2014, 16:51

Korzystanie z rozwiązania @jason Sebring i dostosowanie do maszynopisu.

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;
2
Pierre R-A 8 luty 2018, 11:08

Potrzebujesz tylko jednego routera i użyć go tak:

router.get('/users');
router.get('/users/:user_id');

router.get('/users/:user_id/items');
router.get('/users/:user_id/items/:item_id');

app.use('api/v1', router);
-7
eguneys 14 sierpień 2014, 09:41