const fs = require('fs');
const path = require('path');
//리스너
const mimeType = {
'.html' : 'text/html',
'.css' : 'text/css',
'.js' : 'text/javascript',
'':'text/html'
}
let output = {
results: []
};
fs.readFile('./text.json', 'utf8', function(err, data){
if (err) {
return;
} else if (data.length > 0 && typeof(JSON.parse(data)) === 'object'){
console.log(data);
output = JSON.parse(data);
}
});
const requestHandler =function(request, response){
console.log(
'Serving request type ' + request.method + ' for url ' + request.url
);
const statusCode = 200;
const headers = defaultCorsHeaders;
headers['Content-Type'] = 'text/plain';
if(request.url === '/classes/messages'){
if(request.method === 'OPTIONS'){
response.writeHead(statusCode, headers);
response.end();
}
else if(request.method === 'POST'){
let message ='';
request.on('data', chunk =>{
message += chunk;
}).on('end', () => {
message = JSON.parse(message);
output.results.push(message);
fs.writeFile('./text.json', JSON.stringify(output),'utf8', function(err){
console.log('비동기적 파일 쓰기 완료');
response.writeHead(201, headers);
response.end();
});
})
}
else if(request.method === 'GET'){
response.writeHead(statusCode, headers);
response.end(JSON.stringify(output));
}else{
console.log('ERROR');
response.writeHead(404, headers);
response.end();
}
}
else if(request.url === '/'){
const filePath = path.join(__dirname, '../public/index.html')
fs.readFile(filePath, (err, data) => {
if (err) throw err;
response.end(data)
})
}else if(request.url === '/codestates'){
response.writeHead(404, headers);
response.end();
}
else{
const ext = path.parse(request.url).ext;
const publicPath = path.join(__dirname, '../public');
if(Object.keys(mimeType).includes(ext)){
fs.readFile(`${publicPath}${request.url}`, (err, data) => {
if(err){
response.end('Not Found');
}
else{
headers['Content-Type'] = mimeType[ext];
response.writeHead(200, headers);
response.end(data);
}
})
}
}
};
const defaultCorsHeaders = {
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',
'access-control-allow-headers': 'content-type, accept',
'access-control-max-age': 10 // Seconds.
};
module.exports = requestHandler;
const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();
const cors = require('cors');
const PORT = 3000;
// request 의 body를 읽어오기 위한 패키지
var bodyParser = require('body-parser');
const corsOptions = {
'optionSuccessStatus' : 200,
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',
'access-control-allow-headers': 'content-type, accept',
'access-control-max-age': 10 // Seconds.
}
// 데이터 보관 => 계속 초기화 돼서 메시지를 출력할 수 없다.
let output = {
results: []
};
//text.json 파일이 비어있을 때와, 데이터를 가지고 있을 때를 구분한다.
fs.readFile('./text.json', 'utf8', function(err, data){
if (err) {
return;
} else if (data.length > 0 && typeof(JSON.parse(data)) === 'object'){
// 이미 데이터를 가지고 있으면 output에 덮어씌운다
output = JSON.parse(data);
}
});
// cors 대응
app.use(cors(corsOptions));
// static 파일폴더를 지정해준다
app.use(express.static('public'))
//request의 body에 접근할 수 있다.
app.use(bodyParser.json());
// options 메서드가 왔을 때에 대한 응답
app.options((request, response) => {
console.log(request.method);
response.send(cors(defaultCorsHeaders));
});
// 모든 요청에 대해서 콘솔 띄우기
app.use((request, response, next) => {
console.log('Serving request type ' + request.method + ' for url ' + request.url);
next();
});
app.get('/', (request, response) => {
const publicPath = path.join(__dirname, '../public/index.html');
response.sendFile(publicPath);
});
app.get('/css/style.css', (request, response) => {
const publicPath = path.join(__dirname, '../public/css/style.css');
response.sendFile(publicPath);
});
app.get('/js/script.js', (request, response) => {
const publicPath = path.join(__dirname, '../public/js/script.js');
response.sendFile(publicPath);
});
// '/classes/messages' 로 get 요청이 들어오면 outout보내기
app.get('/classes/messages', (request, response, next) => {
fs.readFile('./text.json', 'utf8', function(err, data){
if (err){
return;
} else if (data.length > 0 && typeof(JSON.parse(data)) === 'object'){
output = JSON.parse(data);
}
response.send(output);
});
});
// '/classes/messages' 로 post 요청이 들어오면 fs에 write
app.post('/classes/messages', (request, response) => {
output.results.push(request.body);
fs.writeFile('./text.json', JSON.stringify(output),'utf8', function(err){
if(err) throw err;
console.log('비동기적 파일 쓰기 완료');
response.send();
});
});
app.listen(PORT, function(){
console.log(`server listen on ${PORT}`);
})
const defaultCorsHeaders = {
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',
'access-control-allow-headers': 'content-type, accept',
'access-control-max-age': 10 // Seconds.
};
TypeError: Converting circular structure to JSON
발생app.post('/classes/messages', (request, response) => {
output.results.push(request);
fs.writeFile('./text.json', JSON.stringify(output),'utf8', function(err){
if(err) throw err;
response.send();
});
});
위 코드 세번째 줄의 JSON.stringify(output)
에서 TypeError: Converting circular structure to JSON
에러가 발생했다. 이 타입에러가 뜨는 이유는 자신을 참조하는 객체를 JSON화 하려고 할 때 발생한다고 한다. 파일시스템 메서드가 비동기로 실행되기 때문에 발생하는 문제라고 생각해서 output.result.push(request)
를 fs.writeFile안으로 옮겼고, 에러는 해결되었다.
output.results.push(request)
를 fs.writeFile안으로 옮김 => 타입에러는 사라졌으나, 파일시스템에 데이터를 저장하지 못했다.app.post('/classes/messages', (request, response) => {
fs.writeFile('./text.json', JSON.stringify(output),'utf8', function(err){
if(err) throw err;
output.results.push(request);
response.send();
});
});
타입에러는 해결됐지만, 파일시스템에 어떠한 것도 저장되지 않았다. 따라서 클라이언트에서 메시지를 전송해도 그에 대한 응답으로 어떤 메시지도 받을 수 없었다.
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/classes/messages', (request, response) => {
output.results.push(request.body);
fs.writeFile('./text.json', JSON.stringify(output),'utf8', function(err){
if(err) throw err;
response.send();
});
});
output에 요청메시지(request)를 통째로 넣었기 때문에 위 두가지 문제에 부딪혔던 것 같다. output에 넣어야할 것은 요청메시지 자체가 아니라 요청메시지의 body 프로퍼티(request.body)이다. request.body
를 사용해야한다는 것은 알고 있었지만, console.log(request.body)
는 undefined
가 나오고 console.log(request)
를 해봐도, request
에는 body
라는 프로퍼티가 없었기 때문에 request
자체를 이용했다. request.body
를 사용하려면 body-parser
를 이용해야한다.const bodyParser = require('body-parser');
app.use(bodyParser.json());
두줄의 코드를 추가했고, request.body를 사용해서 문제를 해결했다.