[javascript] Express.js 중첩 라우터로 휴식

대략 다음과 같은 REST 엔드 포인트를 원한다고 가정하십시오.

/user/
/user/user_id

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

각각의 CRUD는 의미가 있습니다. 예를 들어, / user POST는 새 사용자를 작성하고 GET은 모든 사용자를 가져옵니다. / user / user_id GET은 한 명의 사용자 만 가져옵니다.

항목은 사용자마다 다르므로 user_id ( 특정 사용자) 아래에 놓습니다 .

이제 익스프레스 라우팅을 모듈화하기 위해 몇 가지 라우터 인스턴스를 만들었습니다. 사용자를위한 라우터와 아이템을위한 라우터가 있습니다.

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 item은의 URL 계층 구조의 하위 항목입니다 user. 이제 /usersuserRouter에 대한 것이지만 itemRouter에 대한보다 구체적인 경로는 /user/*user_id*/items/무엇입니까? 또한 가능한 경우 item_uter에서도 user_id에 액세스 할 수 있기를 바랍니다.



답변

라우터를 사용하거나 사용하지 않고 다른 라우터에 미들웨어 로 연결하여 라우터를 중첩 할 수 있습니다 params.

상위 라우터에서 {mergeParams: true}액세스하려면 하위 라우터로 전달해야 params합니다.

mergeParamsExpress4.5.0 에 도입되었습니다 (2014 년 7 월 5 일)

이 예에서는 경로 에 itemRouter연결됩니다.userRouter/:userId/items

가능한 경로는 다음과 같습니다.

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


답변

관리 가능한 중첩 경로 …

Express 4에서 매우 관리 가능한 방식으로 중첩 된 경로를 수행하는 특정 예를 원했고 이것이 “표현 된 경로 중 가장 빠른”검색 결과입니다. 예를 들어 분해해야 할 경로가 많은 API가 있습니다.

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

폴더 구조의 중첩 예

“중첩 폴더 구조”에 대한 의견을 발견했습니다. 그러나 이것이 명확하지는 않기 때문에 아래 섹션을 추가했습니다. 다음 은 route 에 대한 중첩 폴더 구조 의 특정 예입니다 .

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

이것은 노드의 작동 방식에 대한 일반적인 예입니다. 디렉토리 기본값으로 웹 페이지에서 “index.html”이 작동하는 방식과 유사하게 폴더에서 “index.js”를 사용하는 경우 진입 점을 코드로 변경하지 않고 재귀에 따라 조직을 쉽게 확장 할 수 있습니다. “index.js”는 디렉토리에서 require 를 사용할 때 액세스되는 기본 문서 입니다.

index.js의 내용

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

/api/index.js의 내용

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

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

/api/admin/users/index.js의 내용

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

여기에 일부 DRY 문제가있을 수 있지만 문제를 캡슐화하는 데 적합합니다.

참고로, 최근에 나는 actionhero에 들어가서 REST 패러다임을 뒤집는 진정한 프레임 워크 올인원과 같은 완전한 기능의 w / 소켓 및 작업 인 것을 발견했습니다. 당신은 아마 명시 적 / 알몸으로 그것을 확인해야합니다.


답변

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

질문의 두 번째 부분의 핵심은 mergeParams 옵션을 사용하는 것입니다

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

에서 /user/jordan/item/catI reponse를 얻을 :

{"user_id":"jordan","item_id":"cat"}


답변

@Jason Sebring 솔루션을 사용하고 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;


답변

try to add  { mergeParams: true } look to simple example  which it middlware use it in controller file getUser at the same for  postUser
    const userRouter = require("express").Router({ mergeParams: true });
    export default ()=>{
    userRouter
      .route("/")
      .get(getUser)
      .post(postUser);
    userRouter.route("/:user_id").get(function () {});


    }


답변

라우터는 하나만 필요하며 다음과 같이 사용하십시오.

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


답변