bestsource

Express.js 중첩 라우터와 함께 휴식

bestsource 2023. 10. 11. 20:50
반응형

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 밑에 넣었습니다.

Express routing modular를 만들기 위해 몇 가지 라우터 인스턴스를 만들었습니다.사용자를 위한 라우터와 아이템을 위한 라우터가 있습니다.

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. 이제 URL을 어떻게 얻습니까?/usersuserRouter에게 무엇이든 간에 보다 구체적인 경로는/user/*user_id*/items/라우터 항목으로 이동하시겠습니까?그리고 가능하다면 user_id도 itemRouter에 접근할 수 있기를 바랍니다.

유무와 상관없이 라우터를 다른 라우터에 미들웨어로 연결하여 네스트할 수 있습니다.params.

통과해야 합니다.{mergeParams: true}액세스를 원하는 경우 하위 라우터로 연결합니다.params상위 라우터에서 전송할 수 있습니다.

mergeParams익스프레스(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에서 매우 관리하기 쉬운 방법으로 중첩 경로를 수행하는 구체적인 예를 원했고 이것이 "express에서 중첩 경로"에 대한 상위 검색 결과였습니다.여기에는 예를 들어 분해해야 할 많은 경로가 있을 것으로 예상되는 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;

폴더 구조에 내포 예제

나는 "네스팅 폴더 구조"에 대한 몇 가지 의견을 알아챘습니다.여기에 암시되어 있지만 명확하지 않아 아래 부분을 추가했습니다.다음은 경로에 대한 중첩 폴더 구조의 구체적인 예입니다.

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 문제가 있을 가능성이 있지만 우려 사항을 요약하는 데 도움이 됩니다.

참고로 저는 최근에 액션 히어로를 맡게 되었고, 그것이 REST 패러다임을 뒤집는 진정한 프레임워크 올인원(All-in-One)에 더 가깝다는 것을 알게 되었습니다.속달로 벌거벗고 가는 것을 확인해 보셔야 할 것 같습니다.

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/cat답변이 왔습니다.

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

@Jason Sebring 솔루션을 사용하고 Typecript에 적응합니다.

server.

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;

Express 모듈러 라우터의 정신에 따라 사용자와 아이템을 위한 별도의 라우터를 보유해야 합니다.그 라우터는 우리의 최상위 애플리케이션 로직의 일부가 아닙니다.대신 사용자의 라우터에 둥지를 틀 수 있습니다.

Users 라우터

const users = require('express').Router();
const items = require('./items');

//...

// Our root route to /users
albums.get('/', function(req, res, next) {
  // res.send() our response here
});

// A route to handle requests to any individual user, identified by an user id
users.get('/:userId', function(req, res, next) {
  let userId = req.params.userId;
  // retrieve user from database using userId
  // res.send() response with user data
});

// Note, this route represents /users/:userId/items because our top-level router is already forwarding /users to our Users router!
users.use('/:userId/items', items);

//...

module.exports = users;

아이템 공유기

// We need to merge params to make userId available in our Items router
const items = require('express').Router({ mergeParams: true });

//...

// The root router for requests to our items path
items.get('/', function(req, res, next) {
  let userId = req.params.userId; // Here is where mergeParams makes its magic

  // retrieve user's track data and render items list page
});

// The route for handling a request to a specific item
items.get('/:itemId', function(req, res, next) {
  let userId = req.params.userId; // <-- mergeParams magic
  let itemId = req.params.itemId;

  // retrieve individual item data and render on single item page
});

//...

module.exports = items;

원천

덧붙이려고 애쓰다{ mergeParams: true }.getUser 동안이나 postUser

const userRouter = require("express").Router({ mergeParams: true });
export default ()=>{
  userRouter
    .route("/")
    .get(getUser)
    .post(postUser);

  userRouter.route("/:user_id").get(function () {});
}

Express 라우터(express).라우터()는 파라미터를 별도로 유지하므로 이들 파라미터를 병합하려면 express에 명시적으로 지시해야 합니다.예: express.라우터({ mergeParams: true})

//위 줄은 질문에 대한 답변입니다.

라우터가 하나만 있으면 다음과 같이 사용할 수 있습니다.

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

언급URL : https://stackoverflow.com/questions/25260818/rest-with-express-js-nested-router

반응형