Node JS Web 1
Node JS Web Application
기본 웹 서버를 만들기 위한 node 모듈
//서버를 만들기 위한 node 내장 모듈
var http = require("http");
//파일을 쓰고/읽기 위한 내장 모듈
var fs = require("fs");
//url을 얻기위한 내장 모듈
var url = require('url');
//url의 쿼리를 얻기위한 내장 모듈
var qs = require('querystring');
//탬플릿의 객체화 하여 불러오기
var template = require('./lib/template.js');
//보안을 위해 접근 방법
var path = require('path');
//npm을 이용하여 출력시 태그를 걸러주는 라이브러리
var sanitizeHtml = require('sanitize-html');
서버를 생성하기 위한 http.createServer에 메인 홈 생성
var app = http.createServer(function (request, response) {
var _url = request.url; //서버의 url을 가져옴
var queryData = url.parse(_url,true).query;//가져온 url을 파라미터로 넣고 쿼리문을 가져옴
var pathname = url.parse(_url,true).pathname;//path(쿼리 제외)
if(pathname === '/'){ //제대로된 url로 들어왔을경우
if(queryData.id === undefined){ // url에서 뒤에 쿼리가 없는경우(메인 홈 화면)
fs.readdir('./data',function(error,filelist){ // data디렉토리에서 파일들을 읽어옴 (list)
var title = 'Welcome';
var description = 'Hello Node.js';
var list = template.list(filelist); // 객체의 list를 가져옴
var html = template.html(title,list,`<h2>${title}</h2>${description}`,`<a href="/create">create</a>`); // html 폼에 파라미터를 넣고 변수에 담아줌
response.writeHead(200);
response.end(html);// 완성된 html을 웹 브라우저에 뿌려줌
})
}
홈 화면이 아닐 경우 뿌려주는 화면
else{
fs.readdir('./data',function(error,filelist) {
var filteredId = path.parse(queryData.id).base;//보안을 위해 경로를 읽어서 넣어주는 방법
fs.readFile(`data/${filteredId}`,'utf-8',function(err,description){
var title = queryData.id;
var sanitizedTitle = sanitizeHtml(title);//title을 url로 읽지 못하게 해줌
var sanitizedDescription = sanitizeHtml(description,{allowedTags:['h1']});//h1은 허용한다는 기능
var list = template.list(filelist);
var 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>`);//hidden을 넣어주는 이유는 삭제할때 삭제할 파일 이름을 전달 하기 위해
response.writeHead(200);
response.end(html);
});
});
}
파일 생성시 화면
create , update , delete 버튼이 사라지고 입력 창만 출력
else if(pathname === '/create'){
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>
`,'');
response.writeHead(200);
response.end(html);
})
}
입력한 내용을 생성하는 로직
else if(pathname === '/create_process'){
var body = '';
request.on('data',function(data){//post로 전달한 데이터를 callback을 통해 return한다
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}`});//302은 변경된 페이지를 의미이며 {Location}은redirect해준다
response.end();
})
});
}
업데이트를 하기위한 페이지 화면
이전 모듈들 사용과 비슷하다.
else if(pathname ==='/update'){
fs.readdir('./data',function(error,filelist) {
var filteredId = path.parse(queryData.id).base;
fs.readFile(`data/${filteredId}`,'utf-8',function(err,description){
var title = queryData.id;
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>`,`<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);
response.writeHead(200);
response.end(html);
});
});
}
업데이트를 진행 한후 데이터 처리
else if(pathname ==='/update_process'){
var body = '';
request.on('data',function(data){
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(err){
fs.writeFile(`data/${title}`,description,'utf8',function(err){
response.writeHead(302,{Location: `/?id=${title}`});//302은 변경된 페이지고 redirect
response.end();
})
});
});
}
파일을 삭제한 후 처리
else if(pathname ==='/delete_process'){
var body = '';
request.on('data',function(data){
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(){
response.writeHead(302,{Location: `/`});//302은 변경된 페이지고 redirect
response.end();
})
});
}
제대로 되지 않은 url로 접근 하였을때 오류 페이지
else{
response.writeHead(404);//웹서버가 응답할때 200은 브라우저는 성공 이라는 의미, 404 는 에러
response.end('Not found');
}
});
app.listen(3000);
마지막 app.listen(3000)은 포트 3000으로 서버를 지켜보고 있다라는 의미이며 3000포트를 사용한다는 의미 이다.
Template.js (객체)
var template = require('./lib/template.js');
맨 위에 선언한 모듈 불러오기에 사용되었다.
module.exports = {
html: function (title, list, body, control) {
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
},
list: function (filelist) {
var list = "<ul>";
var i = 0;
while (i < filelist.length) {
list += `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i++;
}
list = list + "</ul>";
return list;
},
};