Yunseok's Dev Blog

배운 것을 적는 블로그입니다.

Express Using Middleware

  • Express는 최소한의 기능을 가지고 있는 라우팅과 미들웨어 웹 프레임워크입니다. Express는 일련의 미들웨어 함수를 실행하는 어플리케션입니다.
  • 미들웨어함수들은 request object(req)와 response object(res)에 접근할 수 있고 다음 미들웨어 함수를 실행도록 next를 실행할 수 있습니다.
  • 미들웨어는
    • 어떤 코드든 실행할 수 있습니다.
    • request와 reponse객체를 변경할 수 있습니다.
    • request-response사이클을 끝낼 수 있습니다.
    • 다음 미들웨어함수를 실행할 수 있습니다.
  • 만약 현재 미들웨어 함수가 request-response사이클을 끝내지 않는다면 반드시 next()를 호출해야합니다. 응답을 끝내지 않은채로 남아있을 수 있습니다.
  • Express어플리케이션은 다양한 종류들의 미들웨어를 사용할 수 있습니다.

Application-level middleware

  • 어플리케이션 레벨 미들웨어를 app objectapp.use()함수와 app.METHOD함수를 이용하여 할당할 수 있습니다.
  • 다음 예는 mount path없이 미들웨어 함수를 사용합니다. 이 함수는 앱에서 모든 요청마다 실행됩니다.
var app = express()

app.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})
  • 다음 예에서 함수는 모든 /user/:id에 요청할 때 마다 실행되는 미들웨어 함수입니다.
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})
  • 다음 예는 GET요청으로 /user/:id로로 요청했을 때 실행되는 핸들러 함수입니다.
app.get('/user/:id', function (req, res, next) {
  res.send('USER')
})
  • 다음 예는 여러개의 함수를 등록하고 있습니다. /user/:id로 요청할 떄 마다 실행되는 미들웨어함수들입니다.
app.use('/user/:id', function (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})
  • 라우트 핸들러들은 path에 대하여 여러개의 라우트를 정의할 수 있습니다.
  • 다음예에서 두번 쟤 라우트에서 어떤 에러도 발생하지 않지만 절대 실행되지 않습니다. 왜냐하면 첫 번째 라우트가 request-response사이클을 끝내기 때문입니다.
app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id)
  next()
}, function (req, res, next) {
  res.send('User Info')
})

// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id)
})
  • 라우터 미들웨어 스택에서 나머지 미들웨어함수들을 스킵하려면 next('route')함수를 호출하면됩니다.
  • next('route')app.METHOD()router.METHOD()를 통해 로드된 미들웨어에서만 동작합니다.
app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // send a regular response
  res.send('regular')
})

// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
  res.send('special')
})

Router-level middleware

  • express.Router()를 사용한다는것을 제외하면 라우터레벨 미들웨어는 어플리케이션 레벨 미들웨어와 똑같이 동작합니다.
  • router.user()router.METHOD()를 사용하여 미들웨어를 로드할 수 있습니다.
  • 다음 예는 위의 어플리케이션 레벨 미들웨어 사용 예제를 라우터 레벨 미들웨어를 사용해서 로드한 예제입니다.
var app = express()
var router = express.Router()

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next router
  if (req.params.id === '0') next('route')
  // otherwise pass control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id)
  res.render('special')
})

// mount the router on the app
app.use('/', router)
  • 나머지 미들웨어들은 스킵하기위해서는 next('router')를 호출하면 됩니다.
var app = express()
var router = express.Router()

// predicate the router with a check and bail out when needed
router.use(function (req, res, next) {
  if (!req.headers['x-auth']) return next('router')
  next()
})

router.get('/', function (req, res) {
  res.send('hello, user!')
})

// use the router and 401 anything falling through
app.use('/admin', router, function (req, res) {
  res.sendStatus(401)
})

Error-handling middleware

  • 에러 핸들링은 미들웨어는 항상 4개의 인수를 받는 함수여야 합니다.
  • 미들웨어함수를 등록하는 방법이랑 비슷하지만 미들웨어가 4개의 인수를 받아야 합니다.
  • 자세한 내용은 Error handling을 참고해주세요.
app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

Built-in middleware

Third-party middleware

  • Express앱에서 다양한 기능들을 추가하기위해 써드파티 미들웨어를 사용할 수 있습니다.
  • 미들웨어 목록
$ npm install cookie-parser
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')

// load the cookie-parsing middleware
app.use(cookieParser())

Sources

  • https://expressjs.com/en/guide/using-middleware.html