TIL 42 | Express Route


生活コード講座を見て書いた.
https://opentutorials.org/course/3370/21388
Expressの基本ハローワールド!コードについて詳しく説明しましょう.
https://expressjs.com/ko/starter/hello-world.html
//express도 모듈이기 때문에 모듈을 로드, 이름은 express로 붙임 
const express = require('express')
//가져온 express를 함수처럼 호출, 즉 express는 함수다! 
//app이라는 변수에 담았는데, application 객체가 담기도록 약속되어 있어 app의 메서드를 사용할 수 있음
const app = express()
const port = 3000

//route, routing
//app의 get 메서드를 사용하고 첫번째 인자로 path를 전달해 routing
app.get('/', (req, res) => {
  res.send('Hello World!')
})

/*
  listen메서드 첫번째 인자로 port번호를 주고 
  메서드 실행될 때 비로소 웹서버가 실행되며 그 포트를 listening하게 되고
  콜백함수가 실행된다
*/
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

ホームページ実装

const express = require('express')
const app = express()
// FileSystem의 약자로 파일 처리와 관련된 모듈
const fs = require('fs');
//템플릿 엔진(Templete Engine)은 동적인 결과를 정적인 파일(HTML)에 담기 위해 사용
//서버파일 내에 HTML 코드를 쓰지 않아도 되므로 뷰와 서버 코드를 따로따로 관리할 수 있도록 해줌
const template = require('./lib/template.js');

const port = 3000


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

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

実装詳細ページ


[Route Parameter] https://expressjs.com/en/guide/routing.html
app.get('/page/:pageId', (req, res) => {
  res.send(req.params)
})
//path 모듈은 파일, 폴더, 디렉터리 등의 경로를 편리하게 설정할 수 있는 기능 제공
//내장 모듈이므로 별도 설치 없이 사용 가능
const path = require('path');
//악성스크립트로 변질되는 것을 막아주는 보안 라이브러리
const sanitizeHtml = require('sanitize-html');

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

ページ生成の実装

//querystring은 legacy로 여겨지기 때문에 이제는 URLSearchParams를 사용하는 것이 좋다
const qs = require('querystring');

app.get('/create/', (req, res) => {
  fs.readdir('./data', (error, filelist) => {
    let title = 'WEB - create';
    let list = template.list(filelist);
    let html = template.HTML(title, list, `
      <form action="/create" 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>
    `, '');
    res.send(html)
  });
})

app.post('/create', (req, res) => {
  let body = '';
  req.on('data', data => {
    body = body + data;
  });
  req.on('end', () => {
    let post = qs.parse(body);
    let title = post.title;
    let description = post.description;
    fs.writeFile(`data/${title}`, description, 'utf8', err => {
      res.writeHead(302, {Location: encodeURI(`/page/${title}`)});
      res.end();
    });
  });
});

pathがtitleに設定され、titleが韓国語の場合符号化エラーが発生したため、encodeURIを適用して解決した.
[注]https://hayjo.tistory.com/37