1. 라우터 연결 오류 2. req.response가 undefined
1090
작성한 질문수 4
수정 전 코드에서는 다음과 같은 오류가 뜨면서 라우터 연결이 안됩니다.
GET /v1/posts/my 라우터가 없습니다.
(1-1) 수정 전 nodebird-api의 app.js
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const passport = require("passport");
const morgan = require("morgan");
const session = require("express-session");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");
dotenv.config();
const v1 = require("./routes/v1");
const authRouter = require("./routes/auth");
const indexRouter = require("./routes");
const { sequelize } = require("./models");
const passportConfig = require("./passport");
const app = express();
passportConfig();
app.set("port", process.env.PORT || 8002);
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
watch: true,
});
sequelize
.sync({ force: false })
.then(() => {
console.log("데이터베이스 연결 성공");
})
.catch((err) => {
console.error(err);
});
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use("/v1", v1);
app.use("/auth", authRouter);
app.use("/", indexRouter);
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");
});
app.listen(app.get("port"), () => {
console.log(app.get("port"), "번 포트에서 대기중");
});
(2-2) 수정 후 nodebird-api의 app.js
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const morgan = require('morgan');
const session = require('express-session');
const nunjucks = require('nunjucks');
const dotenv = require('dotenv');
dotenv.config();
const v1 = require('./routes/v1');
const v2 = require('./routes/v2');
const authRouter = require('./routes/auth');
const indexRouter = require('./routes');
const { sequelize } = require('./models');
const passportConfig = require('./passport');
const app = express();
passportConfig();
app.set('port', process.env.PORT || 8002);
app.set('view engine', 'html');
nunjucks.configure('views', {
express: app,
watch: true,
});
sequelize.sync({ force: false })
.then(() => {
console.log('데이터베이스 연결 성공');
})
.catch((err) => {
console.error(err);
});
app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/v1', v1);
app.use('/v2', v2);
app.use('/auth', authRouter);
app.use('/', indexRouter);
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');
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기중');
});
수정 후에는 에러 메시지가 Cannot read properties of undefined (reading 'status')로 바뀌었습니다.
nodecat의 index.js
const express = require("express");
const axios = require("axios");
const router = express.Router();
const URL = "http://localhost:8002/v1";
axios.defaults.headers.origin = "http://localhost:4000";
const request = async (req, api) => {
try {
if (!req.session.jwt) {
const tokenResult = await axios.post(`${URL}/token`, {
clientSecret: process.env.CLIENT_SECRET,
});
req.session.jwt = tokenResult.data.token;
return await axios.get(`${URL}${api}`, {
headers: { authorization: req.session.jwt },
});
}
} catch (error) {
console.error(error);
if (error.response.status === 419) {
delete req.session.jwt;
return request(req, api);
}
return error.response;
}
};
router.get("/mypost", async (req, res, next) => {
try {
const result = await request(req, "/posts/my");
res.json(result.data);
} catch (error) {
console.error(error);
next(error);
}
});
router.get("/search/:hashtag", async (req, res, next) => {
try {
const result = await request(
req,
`/posts/hashtag/${encodeURIComponent(req.params.hashtag)}`
);
res.json(result.data);
} catch (error) {
console.error(error);
next(error);
}
});
module.exports = router;
nodebird-api의 middleware.js
const jwt = require("jsonwebtoken");
exports.isLoggedIn = (req, res, next) => {
if (req.isAuthenticated()) {
next();
} else {
res.status(403).send("로그인 필요");
}
};
exports.isNotLoggedIn = (req, res, next) => {
if (!req.isAuthenticated()) {
next();
} else {
res.redirect("/");
}
};
exports.verifyToken = (req, res, next) => {
try {
req.decoded = jwt.verify(req.headers.authorization, process.env.JWT_SECRET);
// req.headers.authorization 유효한지 검사.
// jwt토큰을 검증해서 req.decoded에 payload(데이터)부분이 담긴다.
return next();
} catch (error) {
if (error.name === "TokenExpiredError") {
// 유효기간 초과.
return res.status(419).json({
code: 419,
// 2xx 3xx 4xx 5xx같이 앞자리만 용도에 맞으면 이후 값은 마음대로 정해도 된다.
// 문서화만 제대로 하면 됨.
message: "토큰이 만료되었습니다",
});
}
return res.status(401).json({
// 위조한 토큰인 경우.
code: 401,
message: "유효하지 않은 토큰입니다",
});
}
};
nodebird-api의 v1.js
const express = require("express");
const jwt = require("jsonwebtoken");
// api서버이기 때문에 nodebird에서 요청자에게로 정보를 제공할 라우터를 뚫어줘야 한다.
// 요청을 처리할 수 있는 라우터.
const { verifyToken } = require("./middlewares");
const { Domain, User, Post, Hashtag } = require("../models");
const router = express.Router();
router.post("/token", async (req, res) => {
// 토큰을 발급해주는 라우터.
const { clientSecret } = req.body;
try {
const domain = await Domain.findOne({
// 도메인 등록했는지 검사.
where: { clientSecret },
// nodecat의 .env에 있는 CLIENT_SECRET값이
// 도메인 clientSecret 등록되어있는지 검사.
include: {
model: User,
attribute: ["nick", "id"],
},
});
if (!domain) {
// 도메인 등록 안되어있으면 에러.
return res.status(401).json({
code: 401,
message: "등록되지 않은 도메인입니다. 먼저 도메인을 등록하세요",
});
}
const token = jwt.sign(
// 토큰 발급해주기 .sign()
// 도메인 등록 되어 있으면 토큰 발급 해주기.
{
id: domain.User.id,
nick: domain.User.nick,
// - 부가적 데이터 넣어줌.
},
process.env.JWT_SECRET,
// - signiture 만들어줌 위조 검사.
{
expiresIn: "1m", // 유효기간 1분.
issuer: "nodebird", // 누가 발급해줬는가.
// - 토큰 옵션
}
);
return res.json({
// 토큰 발급되면 nodecat에 돌려줌.
// nodecat의 index.js의 tokenResult.data.token에 저장됨.
code: 200,
message: "토큰이 발급되었습니다",
token,
});
} catch (error) {
console.error(error);
return res.status(500).json({
code: 500,
message: "서버 에러",
});
}
});
router.get("/test", verifyToken, (req, res) => {
// 토큰이 제대로 발급되었는지 테스트 하는 라우터.
res.json(req.decoded);
// req.decoded는 verifyToken에서 나옴.
// 이후 req.decoded는 nodecat의 index.js의 result.data안에 들어간다.
});
// nodebird의 data들을 보내주는 라우터 코딩.
router.get("./posts/my", verifyToken, (req, res) => {
// 자기 자신의 정보를 가져올 수 있게 해주는것.
Post.findAll({ where: { userId: req.decoded.id } })
.then((posts) => {
console.log(posts);
// async await 방식이 아니라 post방식으로 작성됨.
res.json({
code: 200,
payload: posts,
// 코드와 데이터를 규격에 맞춰 보내줌.
});
})
.catch((error) => {
// 비동기 처리를 할때는 에러가 뭔지 기록해주어야 한다.
console.error(error);
return res.status(500).json({
code: 500,
message: "서버 에러",
});
});
});
// 해시태그로 검색하는 라우터
router.get(`/posts/hashtag/:title`, verifyToken, async (req, res) => {
try {
const hashtag = await Hashtag.findOne({
where: { title: req.params.title },
});
if (!hashtag) {
return res.status(404).json({
code: 404,
message: "검색 결과가 없습니다.",
});
}
const posts = await hashtag.getPosts();
return res.json({
code: 200,
payload: posts,
});
} catch (error) {
console.error(error);
return res.status(500).json({
code: 500,
message: "서버 에러",
});
}
});
module.exports = router;
질문 1.
수정 후 코드는 10.7의 코드는 붙여 넣기 한 것입니다. 수정 전에도 라우터는 연결된 것처럼 보였는데 라우터가 없다는 오류가 뜬 이유가 뭔가요?
질문 2.
수정 후에 뜨는 에러 메시지인 Cannot read properties of undefined (reading 'status')가
if (error.response.status === 419) {
// 토큰 만료 시 토큰 재발급 받기이 부분에서 발생했습니다. error.response가 undefined라는 것 까지는 알겠는데
2-1. 왜 error.response가 undefined가 된것인지.
2-2. 어느 부분에서 오류가 발생해 error로 넘어간 것인지 전혀 감이 잡히지 않습니다.
답변 1
1
router.get("./posts/my", verifyToken, (req, res) => {
주소 앞에 . 붙어 있는 오타입니다.
error.response는 응답이 아예 오지 않았으면 undefined입니다. 서버에서 에러가 나서 응답이 오지 않은 것이죠. 서버를 봐야합니다.
0
빠른 답변 감사합니다 오타가 문제였네요...
강사님께서 '서버를 봐야 한다' 라고 말씀하셔서 다시 오타가 있는 상태로 돌려놓고 f12로 네트워크를 창을 띄웠는데요, status code가 500 Internal Server Error로 나와있었습니다.
이런 경우는 status code가 500이다 -> 내부 서버 오류이다 -> 서버에서 에러가 났다
이렇게 생각하고 서버에서 오류가 발생할 수 있는 여러가지 가능성을 검토하면 된다 이런 식으로 문제 해결을 해나가는 것이라고 이해하면 되는 걸까요?
리눅스 노드 설치시 패키지
0
165
0
socket.js 에서 referer로부터 roomId를 가져올 때
0
909
3
스트리밍 방식으로 대용량 파일 업로드 & 다운로드 관련 질문
0
2287
2
a[title] 질문드립니다
0
380
1
리뉴얼 강의 및 공부 방법
0
583
1
jwt decode
0
1135
1
node.js 교과서 3판 질문드립니다
0
393
1
passport와 jwt
0
437
1
리뉴얼 강의
0
422
2
혹시 Node.js 교과서 3판 이북은 언제 나오나요?
0
356
1
몽고디비 사용자도 MYSQL부분을 들어야 하나요???
0
485
1
sql 쿼리 로그는 어떤 모듈이 작성하나요?
0
507
2
nunjucks res.render('error'); 작동을 안합니다.
0
514
1
질문있습니다.
0
348
1
multer 한글 파일 업로드시 파일명이 깨져요.
1
3538
1
수업자료는 어디있나요?
0
369
1
질문 있습니디
0
240
1
multer 사용시 file 외 name값은 못받나용?
0
421
1
코드 중복 부분 질문드립니다.
0
300
1
api 만드는 이유 질문드립니다.
0
290
1
Strategy의 done에 대해 질문드립니다.
0
368
1
안녕하세요 fs 권한 관련 질문드립니다
0
453
1
시퀄라이즈 연결질문...
0
503
2
res.setHeader vs res.cookie
0
1791
3





