본문 바로가기
프로그래밍 개발/Express

Express - 미들웨어

by Jinseok Kim 2021. 1. 14.
반응형

 

 

미들웨어

 

 

  • 미들웨어는 누군가 미리 만들어 놓은 코드를 부품을 쓰듯이 생산성을 높이기 위하여 쓸 수 있는 기능이라고 말할 수 있다.
  • express 자체가 미들웨어로 구성되어있다고 해도 무방하다.

 

 

 

 

 

 

 

미들웨어 사용하기

 

body-praser라는 node.js 코드를 더 간결하고 간단하게 해주는 미들웨이로 예를 들어 보겠다.

 

expressjs.com/en/resources/middleware/body-parser.html

 

Express body-parser middleware

body-parser Node.js body parsing middleware. Parse incoming request bodies in a middleware before your handlers, available under the req.body property. Note As req.body’s shape is based on user-controlled input, all properties and values in this object a

expressjs.com

 

 

npm install body-parser

위의 코드를 터미널에서 명령하면 body-parser라는 미들웨어가 깔린다.

 

 

 

 

var bodyParser = require('body-parser')

app.use(bodyParser.urlencoded({ extended: false }))

위 두 코드를 추가시켜줘야 main.js안에서 body-parser 미들웨이가 작동한다.

 

 

 

 

 

body-parser 적용 예시

const express = require('express')
const app = express()
const port = 3000
var fs = require('fs');
var qs = require('querystring');
var template = require('./lib/template.js');
var path = require('path');
var sanitizeHtml = require('sanitize-html');
var bodyParser = require('body-parser') //추가


app.use(bodyParser.urlencoded({ extended: false })) //추가

app.get('/', (request, response) => {
  fs.readdir('./data', function(error, filelist){
          var title = 'Welcome';
          var description = 'Hello, Node.js';
          var list = template.list(filelist);
          var html = template.HTML(title, list,
            `<h2>${title}</h2>${description}`,
            `<a href="/create">create</a>`
          );
         
          response.send(html);
        });
});

app.get('/page/:pageId',(request, response)=>{
    fs.readdir('./data', function(error, filelist){
          var filteredId = path.parse(request.params.pageId).base;
          fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
            var title = request.params.pageId;
            var sanitizedTitle = sanitizeHtml(title);
            var sanitizedDescription = sanitizeHtml(description, {
              allowedTags:['h1']
            });
            var list = template.list(filelist);
            var html = template.HTML(sanitizedTitle, list,
              `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
              ` <a href="/create">create</a>
                <a href="/update/${sanitizedTitle}">update</a>
                <form action="/delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>`
            );
            response.send(html);
          });
        });
})

app.get('/create', (request, response)=>{
    fs.readdir('./data', function(error, filelist){
        var title = 'WEB - create';
        var list = template.list(filelist);
        var html = template.HTML(title, list, `
          <form action="/create_process" method="post">
            <p><input type="text" name="title" placeholder="title"></p>
            <p>
              <textarea name="description" placeholder="description"></textarea>
            </p>
            <p>
              <input type="submit">
            </p>
          </form>
        `, '');
        response.send(html);
      });
});
       //body-parser 때문에 post의 두번째 인자인 콜백함수의 첫번째 인자에는 body라는 프로퍼티가
       //자동으로 추가되었다고 생각하면 된다.
app.post('/create_process', (request, response)=>{
//body 프로퍼티를 적용하면 이제 따로 받은 데이터를 받는 코드를 작성하지 않아도 된다.
       var post = request.body; 
       var title = post.title;
       var description = post.description;
    fs.writeFile(`data/${title}`, description, 'utf8', function(err){
     response.writeHead(302, {Location: `/? id=${title}`});
     response.end();
  });
});
    
   /*var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var title = post.title;
          var description = post.description;
          fs.writeFile(`data/${title}`, description, 'utf8', function(err){
            response.writeHead(302, {Location: `/?id=${title}`});
            response.end();
          })
      });*/  

app.get('/update/:pageId', (request, response)=>{
  fs.readdir('./data', function(error, filelist){
        var filteredId = path.parse(request.params.pageId).base;
        fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
          var title = request.params.pageId;
          var list = template.list(filelist);
          var html = template.HTML(title, list,
            `
            <form action="/update_process" method="post">
              <input type="hidden" name="id" value="${title}">
              <p><input type="text" name="title" placeholder="title" value="${title}"></p>
              <p>
                <textarea name="description" placeholder="description">${description}</textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
            `,
            `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`
          );
          response.send(html);
        });
      });  
});

app.post('/update_process', (request, response)=>{
/body 프로퍼티를 적용하면 이제 따로 받은 데이터를 받는 코드를 작성하지 않아도 된다.
     var post = request.body;
     var id = post.id;
     var title = post.title;
     var description = post.description;
     fs.rename(`data/${id}`, `data/${title}`,  function(error){
     fs.writeFile(`data/${title}`, description, 'utf8', function(err){
      response.redirect(`/?id=${title}`);
    })
  });
});
  /* var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var id = post.id;
          var title = post.title;
          var description = post.description;
          fs.rename(`data/${id}`, `data/${title}`, function(error){
              fs.writeFile(`data/${title}`, description, 'utf8', function(err){
          response.redirect(`/?id=${title}`);
          */
         
app.post('/delete_process', (request, response)=>{
/body 프로퍼티를 적용하면 이제 따로 받은 데이터를 받는 코드를 작성하지 않아도 된다.
    var post = request.body;
    var id = post.id;
    var filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, function(error){
    response.redirect('/');
  });
});
   /* var body = '';
      request.on('data', function(data){
          body = body + data;
      });
      request.on('end', function(){
          var post = qs.parse(body);
          var id = post.id;
          var filteredId = path.parse(id).base;
          fs.unlink(`data/${filteredId}`, function(error){
          response.redirect('/');
         */
         

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

 

 

 

 

 

 

미들웨어 만들기

 

main.js

const express = require('express')
const app = express()
const port = 3000
var fs = require('fs');
var qs = require('querystring');
var template = require('./lib/template.js');
var path = require('path');
var sanitizeHtml = require('sanitize-html');
var bodyParser = require('body-parser')


app.use(bodyParser.urlencoded({ extended: false }))

//아래와 같이 미들웨어를 만들 수 있다. 지금까지 반복되었던  
//"fs.readdir('./data', function(error, filelist){"을 미들웨어로 만들어 코드를 축약시켰다.
//'*'는 이 파일 안에 있는 코드 전체에 적용시킨다는 의미이다.
app.get('*', function(request, response, next){
  fs.readdir('./data', function(error, filelist){
  
  //읽어온 데이터를 받은 콜백함수 두번째 인자의 filelis을 request.list로 변수화
  //여기서 request.list의 request는 app.get 미들웨이의 함수인 request 객체를 인자로 
  //받은 파라미터라고 보면된다.
    request.list = filelist; 
    next(); //next 파라미터에는 그 다음에 호출될 미들웨어를 담고있으므로 꼭 실행시켜줘야한다.
  });
});

app.get('/', (request, response) => {
  
          var title = 'Welcome';
          var description = 'Hello, Node.js';
          var list = template.list(request.list); //request.list로 변환
          var html = template.HTML(title, list,
            `<h2>${title}</h2>${description}`,
            `<a href="/create">create</a>`
          );
         
          response.send(html);
        
});

app.get('/page/:pageId',(request, response)=>{
    
          var filteredId = path.parse(request.params.pageId).base;
          fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
            var title = request.params.pageId;
            var sanitizedTitle = sanitizeHtml(title);
            var sanitizedDescription = sanitizeHtml(description, {
              allowedTags:['h1']
            });
            var list = template.list(request.list); //request.list로 변환
            var html = template.HTML(sanitizedTitle, list,
              `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
              ` <a href="/create">create</a>
                <a href="/update/${sanitizedTitle}">update</a>
                <form action="/delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>`
            );
            response.send(html);
          });
        
});

app.get('/create', (request, response)=>{
    
        var title = 'WEB - create';
        var list = template.list(request.list); //request.list로 변환
        var html = template.HTML(title, list, `
          <form action="/create_process" method="post">
            <p><input type="text" name="title" placeholder="title"></p>
            <p>
              <textarea name="description" placeholder="description"></textarea>
            </p>
            <p>
              <input type="submit">
            </p>
          </form>
        `, '');
        response.send(html);
      
});

app.post('/create_process', (request, response)=>{
       var post = request.body;
       var title = post.title;
       var description = post.description;
    fs.writeFile(`data/${title}`, description, 'utf8', function(err){
     response.writeHead(302, {Location: `/? id=${title}`});
     response.end();
  });
});
    


app.get('/update/:pageId', (request, response)=>{
  
        var filteredId = path.parse(request.params.pageId).base;
        fs.readFile(`data/${filteredId}`, 'utf8', function(err, description){
          var title = request.params.pageId;
          var list = template.list(request.list); //request.list로 변환
          var html = template.HTML(title, list,
            `
            <form action="/update_process" method="post">
              <input type="hidden" name="id" value="${title}">
              <p><input type="text" name="title" placeholder="title" value="${title}"></p>
              <p>
                <textarea name="description" placeholder="description">${description}</textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
            `,
            `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`
          );
          response.send(html);
        });
        
});

app.post('/update_process', (request, response)=>{
     var post = request.body;
     var id = post.id;
     var title = post.title;
     var description = post.description;
     fs.rename(`data/${id}`, `data/${title}`,  function(error){
     fs.writeFile(`data/${title}`, description, 'utf8', function(err){
      response.redirect(`/?id=${title}`);
    })
  });
});
  
         
app.post('/delete_process', (request, response)=>{
    var post = request.body;
    var id = post.id;
    var filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, function(error){
    response.redirect('/');
  });
});
   

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

 

 

 

 

 

 

 

 

미들웨어의 실행순서

 

 

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()
})

위와 같이 미들웨어를 여러개를 붙일 수 있다.

 

 

 

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()을 호출하게 되면 계속 미들웨어를 붙일 수 있지만 호출하지 않는다면 거기서 미들웨이는 끝나게 된다고 볼 수 있따.

 

 

 

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')
})

위와 같은 조건문 if을 주어 다음 미들웨어를 이어나갈지 안나갈지 정해줄 수도 있다.

 

 

 

 

반응형

댓글