// server.js 파일=================================================
const express=require('express');
const cookieParser=require('cookie-parser');
const ctoken = require('./jwt');
const chash = require('./chash')
const app=express();
const nunjucks = require('nunjucks')
const bodyParser = require('body-parser')
const auth = require('./middleware/auth')
const {sequelize, User} = require('./models')
const socket = require('socket.io');
const http = require('http');
const server = http.createServer(app);
const io = socket(server);
const port = process.env.PORT||3000
const Router = require('./js/router.js')
// router.js는 public 폴더 안의 js폴더 안에 위치
app.set('view engine', 'html')
app.use(express.static('public'));
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:false}))
nunjucks.configure('views',{
express: app,
})
app.use(cookieParser());
sequelize.sync({force:false})
.then(()=>{ // resolve
console.log('DB접속이 완료되었습니다.')
})
.catch((err)=>{ // reject
console.log(err)
})
app.get('/', (req,res)=>{
let {msg} = req.query;
res.render('index')
})
app.use('/router',Router)
// '/router'경로로 들어오면 콜백함수로 Router를 실행. 즉 router.js파일 실행
app.get('/user/info',auth, (req,res)=>{
res.send(`Hello ${req.userid}`)
})
app.get('/user/join',(req,res)=>{
res.render('join')
})
app.get('/user/userid_check',async (req,res)=>{
userid = req.query.userid
result = await User.findOne({
where:{userid}
})
if (result == undefined){
check = true;
} else{
check = false;
}
res.json({check})
})
app.post('/user/join_success',async (req,res)=>{
let{userid, userpw, username, gender, userimage, useremail} = req.body
let token = chash(userpw)
let result = await User.create({
userid, token, username, gender, useremail, userimage
})
res.json({result})
})
app.post('/auth/local/login',async (req,res)=>{
let {userid, userpw} = req.body
console.log('body req :',userid, userpw)
let result = {}
let token = chash(userpw)
let check = await User.findOne({
where : {userid, token}
})
let token2 = ctoken(userid)
if(check== null){
result = {
result:false,
msg:'아이디와 패스워드를 확인해주세요'
}
}else{
result = {
result:true,
msg:'로그인에 성공하셨습니다.'
}
res.cookie('AccessToken',token2,{httpOnly:true,secure:true,})
}
res.json(result)
})
app.get('/chat',auth,(req,res)=>{
res.render('chat')
})
let id;
io.sockets.on('connection',socket=>{
let cookieString = socket.handshake.headers.cookie;
if(cookieString != undefined){
let cookieArr = cookieString.split(';');
cookieArr.forEach(v=>{
let [name,value] = v.split('=');
if(name.trim() == 'AccessToken'){
let jwt = value.split('.');
let payload = Buffer.from(jwt[1],'base64').toString();
let {userid} = JSON.parse(payload);
id = userid;
}
})
}
console.log(id)
socket.on('send',data=>{
console.log(data);
socket.broadcast.emit('msg',data)
})
})
app.use((req,res,next)=>{
const error = new Error(`${req.method} ${req.url} 을 찾을 수 없습니다.`);
error.status = 404;
next(error)
})
app.use((err,req,res,next)=>{
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !=='production'?err:{};
res.status(err.status||500);
res.render('error');
});
server.listen(3000,()=>{
console.log('server start port: 3000');
})
// router.js파일===================================================
const express = require('express')
const router = express.Router()
router.get('/',(req,res)=>{res.send('router')})
// router로 연결된 상태이므로 위 코드의 경로는 '/router'
// '/router'로 들어오면 server.js에서 콜백함수로 연결되어 router를 화면에 출력
router.get('/plus',(req,res)=>{res.send('plus')})
// 위의 코드는 '/router/plus' 경로로 들어왔을 때 화면에 plus를 출력
module.exports = router
// 반드시 module.exports로 내보내 주어야 한다.
//서버를 만들기 위해 가장 기본적으로 사용하는 프레임워크
--npm install express
const express = require('express')
const app = express()
// express를 사용하기 위한 기본세팅
app.set('view engine','html')
// 페이지를 볼 때 html을 이용하겠다는 것
// html이외에 nunjucks 등을 줄 수 도 있다.
app.use(express.static(('public'))
// 이미지나 css, js같은 정적 파일 등을 사용시 public폴더에 있는 것을 이용
// 여러개의 폴더를 지정하는 것도 가능
app.get('/',(req,res)=>{res.render('index')})
// /경로 즉 주소창에 localhost:3000으로 들어오면 index.html파일을 가져오겠다.
// * 화살표 함수 ()=>{}
app.use((req,res,next)=>{
res.status(404).send("can't find file")
/*
const error = new Error
error.status = 404
next(error)
// 즉 새로운 error를 만들어내서 error에 담고 해당 error의 상태코드는 404
// 그런후 next(error)안에 error를 담아 전달하면 오류핸들러로 처리하게 됨
*/
})
// 상태코드가 404일때 페이지에 can't find file을 출력
// 상태코드가 404라는 것 -> 오류x 단지 파일을 찾지 못하는 것
// 즉 404는 오류핸들러로 처리하지 못함
// 오류핸들러로 처리하려면 주석부분과 같은 코드를 추가하면 가능
app.use((err,req,res,next)=>{
res.status(500).render('error')
})
// 오류가 발생시 위의 코드에 의해 오류핸들러에 걸리면 error.html파일을 보여줌
/*
상태코드
200번대 -> 일반적으로 성공을 의미
300번대 -> 리다이렉션을 알리는 상태코드
400번대
- 400 -> 잘못된 요청
- 401 -> 권한없음
- 404 -> 찾을 수 없음
500번대 -> 서버오류
*/
// ** res.render()대신에 res.sendFile()함수를 이용해도 된다.
app.listen(3000,()=>{console.log(`server start 3000`)})
// app.listen()의 첫번째 인자는 서버가 실행될 포트값, 두번째 인자에는 실행될 콜백함수.
// 즉 위 코드는 3000번 port에서 실행하고, 실행을 확인하기 위해 콜백함수로 console.log() 실행
app.all()
//모든 요청메서드에 대하여 해당 경로로 들어올때 특정한 미들웨어 함수를 적용하도록
all.all('/secret',()=>{console.log('secret section')})
//어떤 메소드(get,post 등)로 들어오든지 '/secret'경로에 들어오면 콘솔에 secret setion이라고 찍히도록 함.
app.use()
app.use(cookieParser())
해당 서버에서 cookieParser를 사용하겠다.
// app.use는 해당 서버에서 인자값으로 준 것을 사용한다는 의미
// 미들웨어를 장착시에 app.use 사용
// 라우트로도 사용
라우트
// 두개 이상의 콜백함수를 주는 경우 해당 콜백함수를 우회하여 갈 수 있다.
단 앞에서 준 콜백함수에서 next()를 통해 다음 콜백함수로 이동할 수 있도록
되어 있어야 함
app.get('/',auth,()=>{console.log('auth를 한 번 거쳐옴')})
// auth함수
function auth(){console.log('here is auth') next()}
// 위의 auth함수의 코드와 같이 next()로 다음 콜백함수에 이동, 인자에 이동할 콜백함수 명을 입력하여 해당 콜백함수로 이동하는 것도 가능.
// 각각의 라우트 종류와 경로가 일치하는 경우에만
1) get
app.get('/',(req,res)=>{res.send('hi')})
// 경로'/'로 들어왔을 때 화면에 hi출력
`
2) post
3) put
4) delete
app.route()
//app.route()를 사용하여 하나의 경로에 대하여 get,post등 다른 method를 한번에 실행가능
app.route('/index').get((req,res)=>{res.send('get method')}) .post((req,res)=>{res.send('post')})
// 위의 코드의 경우 '/index'라는 경로에 대하여 get과 post로 들어왔을 때를 나눈 것
응답메소드 -> 아래에 응답객체와 요청객체로 추가설명
1) res.download() -> 파일이 다운로드되도록 프롬프트
2) res.end() -> 응답프로세스 종류
3) res.json() -> 응답을 json형식으로 변환하여 전달
app.get('/json',()=>{res.json({name:"algml",age:26}) })
res.json()에서 인자값을 줄 때도 객체 형식으로 주어야 한다.
res.send({name:"algml",age:26})로 이와 같이 보낼 때는 객체형식이 아니라 string형식으로 보내진다.
4) res.jsonp() -> jsonp 지원을 통해 json응답을 전달
5) res.redirect() -> 경로 재지정
app.get('/redirect',()=>{res.redirect('/redirectedRoute')})
'/redirect'경로도 들어왔을 때 다시 '/redirectedRoute'로 경로로 다시 이동됨
6) res.render() -> 해당 템플럿을 보여줌
app.get('/',()=>{res.render('index.html')})
'/'에 들어오면 index.html파일을 보여줌
7) res.send() -> 인자값으로 준 것을 그대로 화면에 출력
app.get('/send',()=>{res.send('<p style="color:yellow">yellow</p>')})
// 위와 같이 코드를 짜면 노란색으로 된 yellow라는 글자를 출력하여 줌
8) res.sendFile() -> 해당 인자값으로 준 파일을 화면에 출력
9) res.sendStatue() -> 해당 상태코드를 반환.
express.Router()
//sub.js파일
const express = require('express')
const router = express.Router()
router.get('/',(req,res)=>{res.send('router')})
module.exports = router
// server.js 파일에 추가할 내용
const Router = require('./sub.js')
app.get('/',router)
//터미널에서 node server.js를 키고 서버를 실행하고 경로'/' 에 들어가면 라우터와 연결되어 화면에 router를 출력하여 준다.
미들웨어(middle ware)함수
--req(요청)객체
--res(응답)객체
오류처리 미들웨어 함수
app.use((err,req,res,next)=>{console.error('error') res.status(500).send('error')})
써드파티 미들웨어 함수
// express 내부에 자체적으로 존재하지 않고 개별적으로 설치하여 사용하는 미들웨어 함수를 의미
템플릿 엔진 설정
app.set('view engine','html')
템플릿 엔진을 설정해둔 경우 보여지는 파일의 확장자를 설정하지 않아도 설정해둔 템플릿 엔진으로 지정된다.
req객체
-- req.body
// POST method에 의한 요청값을 넘겨 받는다.
// key-value 형식 -> json객체에 접근 가능
// body-parser를 통해 가공된 값을 받는다.
-- req.params
// GET method를 통해 요청값을 받는다.
-- req.query
// GET method를 통해 쿼리스트링 파라미터를 넘겨받음
//?뒤에 키=값 형식으로 주는 것
//받을 때는 req.query.키로 받음
//GET/user?name=algml&age=26
console.log(req.query.name) // algml
console.log(req.query.age) //26
-- req.cookies /req.signedCookies
// 클라이언트가 전달한 쿠키값을 받는다.
-- req.fresh
-- req.originalUrl
-- req.headers
// HTTP의 header정보를 가지고 있다.
res.render('index',{name:'algml'})
//index파일을 렌더링하면서 두번째 인자를 통해 data를 함께 전달할 수 있다.
res.append('Set-cookie','name=algml')
res.cookie('name','algml')
app.get('/',(req,res)=>{res.json({name:'algml',age:26})})
let user = {name:'algml',age:26}
let stringify = JSON.stringify(user)
console.log(stringify) //{"name":"algml","age":26}
console.log(stringify.name) //undefined
let user = '{"name":"algml","age":26}'
// user는 string형식
let parse = JSON.parse(user)
console.log(parse) // [object object]
console.log(parse.name) //algml
app.set('port',3000)
app.get('port')
//app.get을 통해 app.set으로 설정해둔 값을 가져올 수 있다.
-- npm install body-parser
// req.body를 통해 가공된 요청값을 받는다.
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))
//// parse application/x-www-form-urlencoded
app.use(bodyParser.json())
// parse applicaion/json
app.post('/',(req,res)=>{res.render('index',{id:req.body.id})})
// index파일을 렌더링하면서 req.body.id의 값을 id로 전달함
-- npm install cookie-parser
// 쿠키값을 쉽게 이용할 수 있도록 가공된 값을 출력
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')
app.use(cookieParser())
app.get('/',(req,res)=>{console.log(req.cookies,req.signedCookies);
res.cookie('mycookie','algml')})