From 6eb9e0e841814c95cc8f5add813ed99d3ec71734 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 19 Jul 2022 16:46:34 +0900 Subject: [PATCH 01/25] =?UTF-8?q?1=EB=8B=A8=EA=B3=84:=20BufferedReader=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=9A=94=EC=B2=AD=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=9D=BD=EC=96=B4=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BufferedReader 생성하고 readLine 메소드 사용해서 한줄씩 읽도록 했다. --- src/main/java/webserver/RequestHandler.java | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 90195ec..953fc56 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,9 +1,6 @@ package webserver; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.net.Socket; import org.slf4j.Logger; @@ -23,7 +20,20 @@ public void run() { connection.getPort()); try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. + // 3.4.3.1 1단계: 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. + BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + String line = br.readLine(); + log.debug("request line: {}", line); + + if (line == null) { + return; + } + while (!line.equals("")){ + line = br.readLine(); + log.debug("header: {}", line); + } + + DataOutputStream dos = new DataOutputStream(out); byte[] body = "Hello World".getBytes(); response200Header(dos, body.length); From 731db31ee5848da75ef8871e54ddf2cff1199060 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 19 Jul 2022 17:02:41 +0900 Subject: [PATCH 02/25] =?UTF-8?q?2=EB=8B=A8=EA=B3=84:=20LineParser=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LineParser 클래스의 parseLine 메소드를 생성해 line에서 url을 추출할 수 있도록 했다. --- src/main/java/util/LineParser.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/util/LineParser.java diff --git a/src/main/java/util/LineParser.java b/src/main/java/util/LineParser.java new file mode 100644 index 0000000..23648cc --- /dev/null +++ b/src/main/java/util/LineParser.java @@ -0,0 +1,9 @@ +package util; + +public class LineParser { + + public static String parseLine(String line){ + String[] parsedLines = line.split(" "); + return parsedLines[1]; + } +} From 8f10cdc6a022fd8d56d0ab06d91081a43bba9c1b Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 19 Jul 2022 17:18:11 +0900 Subject: [PATCH 03/25] =?UTF-8?q?3=EB=8B=A8=EA=B3=84:=20webapp=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=EC=97=90=EC=84=9C=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20URL=EC=97=90=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EC=9D=84=20=EC=9D=BD=EC=96=B4=EC=98=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - url에 해당하는 파일을 가져와 byte배열로 변환. --- src/main/java/webserver/RequestHandler.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 953fc56..c869aa4 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,10 +2,13 @@ import java.io.*; import java.net.Socket; +import java.nio.file.Files; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static util.LineParser.parseLine; + public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); @@ -24,7 +27,9 @@ public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line = br.readLine(); log.debug("request line: {}", line); + String url = parseLine(line); + //2단계 + 3단계 if (line == null) { return; } @@ -33,11 +38,11 @@ public void run() { log.debug("header: {}", line); } - DataOutputStream dos = new DataOutputStream(out); - byte[] body = "Hello World".getBytes(); + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); response200Header(dos, body.length); responseBody(dos, body); + } catch (IOException e) { log.error(e.getMessage()); } From 5bb0f5a9d33ecbaf00abc9380f29952063eba360 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Wed, 20 Jul 2022 15:54:42 +0900 Subject: [PATCH 04/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=202:?= =?UTF-8?q?=20GET=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 책에 있는 힌트를 보고 진행했다. 기존에 구현되어 있는 parseQueryString메소드를 사용하니 수월했다. --- src/main/java/webserver/RequestHandler.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index c869aa4..5b26c8b 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -3,9 +3,12 @@ import java.io.*; import java.net.Socket; import java.nio.file.Files; +import java.util.Map; +import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; import static util.LineParser.parseLine; @@ -38,11 +41,19 @@ public void run() { log.debug("header: {}", line); } - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - response200Header(dos, body.length); - responseBody(dos, body); - + if (url.startsWith("/user/create")){ + int index = url.indexOf("?"); + String queryString = url.substring(index + 1); + Map params = HttpRequestUtils.parseQueryString(queryString); + User user = new User(params.get("userId"), params.get("password"), params.get("name"), + params.get("email")); + log.debug("user: {}", user); + } else { + DataOutputStream dos = new DataOutputStream(out); + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + response200Header(dos, body.length); + responseBody(dos, body); + } } catch (IOException e) { log.error(e.getMessage()); } From fc0418e7e5156a312876ece3323b17bf4a84c438 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Wed, 20 Jul 2022 16:46:45 +0900 Subject: [PATCH 05/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=203:?= =?UTF-8?q?=20POST=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LineParser 클래스는 따로 필요가 없는 것 같아서 삭제하고 안에 있던 메소드는 RequestHandler로 이동시켰다. --- src/main/java/util/LineParser.java | 9 --------- src/main/java/webserver/RequestHandler.java | 21 +++++++++++++++++---- webapp/user/form.html | 4 ++-- 3 files changed, 19 insertions(+), 15 deletions(-) delete mode 100644 src/main/java/util/LineParser.java diff --git a/src/main/java/util/LineParser.java b/src/main/java/util/LineParser.java deleted file mode 100644 index 23648cc..0000000 --- a/src/main/java/util/LineParser.java +++ /dev/null @@ -1,9 +0,0 @@ -package util; - -public class LineParser { - - public static String parseLine(String line){ - String[] parsedLines = line.split(" "); - return parsedLines[1]; - } -} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 5b26c8b..1816a97 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -9,8 +9,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; +import util.IOUtils; -import static util.LineParser.parseLine; public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); @@ -32,19 +32,22 @@ public void run() { log.debug("request line: {}", line); String url = parseLine(line); + int contentLength = 0; //2단계 + 3단계 if (line == null) { return; } while (!line.equals("")){ line = br.readLine(); + if (line.contains("Content-Length")){ + contentLength = getContentLength(line); + } log.debug("header: {}", line); } if (url.startsWith("/user/create")){ - int index = url.indexOf("?"); - String queryString = url.substring(index + 1); - Map params = HttpRequestUtils.parseQueryString(queryString); + String body = IOUtils.readData(br, contentLength); + Map params = HttpRequestUtils.parseQueryString(body); User user = new User(params.get("userId"), params.get("password"), params.get("name"), params.get("email")); log.debug("user: {}", user); @@ -78,4 +81,14 @@ private void responseBody(DataOutputStream dos, byte[] body) { log.error(e.getMessage()); } } + + private int getContentLength(String line) { + String[] split = line.split(":"); + return Integer.parseInt(split[1].trim()); + } + + private String parseLine(String line){ + String[] parsedLines = line.split(" "); + return parsedLines[1]; + } } diff --git a/webapp/user/form.html b/webapp/user/form.html index 96fe1bd..587a9d6 100644 --- a/webapp/user/form.html +++ b/webapp/user/form.html @@ -75,7 +75,7 @@
-
+
@@ -104,4 +104,4 @@ - \ No newline at end of file + From de7a969b2684c8bec1e93000345ca4a374f6f20f Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Thu, 21 Jul 2022 10:32:44 +0900 Subject: [PATCH 06/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=204:?= =?UTF-8?q?=20302=20status=20code=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 처음에는 유저를 저장한 후에 else 부분을 복붙하니 index.html로 화면이 전환되었으나 주소부분이 바뀌지 않았다. 책의 힌트처럼 http 302 문서를 읽고 구현완료. --- src/main/java/webserver/RequestHandler.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 1816a97..921e3e6 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -51,6 +51,9 @@ public void run() { User user = new User(params.get("userId"), params.get("password"), params.get("name"), params.get("email")); log.debug("user: {}", user); + + DataOutputStream dos = new DataOutputStream(out); + response302Header(dos, "/index.html"); } else { DataOutputStream dos = new DataOutputStream(out); byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); @@ -73,6 +76,16 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { } } + private void response302Header(DataOutputStream dos, String url) { + try { + dos.writeBytes("HTTP/1.1 302 Found \r\n"); + dos.writeBytes("Location: " + url + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + private void responseBody(DataOutputStream dos, byte[] body) { try { dos.write(body, 0, body.length); From e487e549672a73b3e1cec0b46d48de5b59b79712 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Thu, 21 Jul 2022 11:55:46 +0900 Subject: [PATCH 07/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=205:?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 반복되는 부분을 response 메소드로 분리함 - 힌트 보고 진행함 --- src/main/java/webserver/RequestHandler.java | 43 +++++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 921e3e6..24f3040 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -5,6 +5,7 @@ import java.nio.file.Files; import java.util.Map; +import db.DataBase; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,15 +51,31 @@ public void run() { Map params = HttpRequestUtils.parseQueryString(body); User user = new User(params.get("userId"), params.get("password"), params.get("name"), params.get("email")); + DataBase.addUser(user); log.debug("user: {}", user); DataOutputStream dos = new DataOutputStream(out); response302Header(dos, "/index.html"); + } else if (url.equals("/user/login")){ + String body = IOUtils.readData(br, contentLength); + Map params = HttpRequestUtils.parseQueryString(body); + User user = DataBase.findUserById(params.get("userId")); + log.debug("로그인유저: {}", user ); + + if (user == null) { + response(out, "/user/login_failed.html"); + return; + } + if (user.getPassword().equals(params.get("password"))){ + DataOutputStream dos = new DataOutputStream(out); + String cookie = "logined=true"; + responseLogin302Header(dos, cookie); + } else { + response(out, "/user/login_failed.html"); + } + } else { - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - response200Header(dos, body.length); - responseBody(dos, body); + response(out, url); } } catch (IOException e) { log.error(e.getMessage()); @@ -76,6 +93,17 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { } } + private void responseLogin302Header(DataOutputStream dos, String cookie) { + try { + dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); + dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); + dos.writeBytes("Location: /index.html" + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + private void response302Header(DataOutputStream dos, String url) { try { dos.writeBytes("HTTP/1.1 302 Found \r\n"); @@ -95,6 +123,13 @@ private void responseBody(DataOutputStream dos, byte[] body) { } } + private void response(OutputStream out, String url) throws IOException { + DataOutputStream dos = new DataOutputStream(out); + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + response200Header(dos, body.length); + responseBody(dos, body); + } + private int getContentLength(String line) { String[] split = line.split(":"); return Integer.parseInt(split[1].trim()); From c4c817412acdf0f12aed05c05a7c70e2591cd023 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Fri, 22 Jul 2022 16:59:33 +0900 Subject: [PATCH 08/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=206:?= =?UTF-8?q?=20=EC=BF=A0=ED=82=A4=20=ED=99=95=EC=9D=B8=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이를 위해 로그인 실패시 'logined=false'를 쿠키값으로 갖도록 수정. - 'logined=true'일 때 /user/list.html로 이동할 수 있도록 기능 구현 --- src/main/java/webserver/RequestHandler.java | 28 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 24f3040..2f6e702 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -3,6 +3,7 @@ import java.io.*; import java.net.Socket; import java.nio.file.Files; +import java.util.HashMap; import java.util.Map; import db.DataBase; @@ -34,6 +35,7 @@ public void run() { String url = parseLine(line); int contentLength = 0; + Map cookies = new HashMap<>(); //2단계 + 3단계 if (line == null) { return; @@ -43,6 +45,10 @@ public void run() { if (line.contains("Content-Length")){ contentLength = getContentLength(line); } + if (line.contains("Cookie")){ + cookies = HttpRequestUtils.parseCookies(line); + log.debug("쿠키: {}", cookies); + } log.debug("header: {}", line); } @@ -56,6 +62,7 @@ public void run() { DataOutputStream dos = new DataOutputStream(out); response302Header(dos, "/index.html"); + } else if (url.equals("/user/login")){ String body = IOUtils.readData(br, contentLength); Map params = HttpRequestUtils.parseQueryString(body); @@ -69,9 +76,22 @@ public void run() { if (user.getPassword().equals(params.get("password"))){ DataOutputStream dos = new DataOutputStream(out); String cookie = "logined=true"; - responseLogin302Header(dos, cookie); + String redirect ="/index.html"; + responseLogin302Header(dos, cookie, redirect); } else { - response(out, "/user/login_failed.html"); + DataOutputStream dos = new DataOutputStream(out); + String cookie = "logined=false"; + String redirect = "/user/login_failed.html"; + responseLogin302Header(dos, cookie, redirect); + } + + } else if (url.equals("/user/list")){ + //TODO: 사용자 목록 출력하기 + if (cookies.get("logined").equals("true")) { + log.debug("쿠키확인: {}" , cookies.get("logined")); + response(out, "/user/list.html"); + } else { + response(out, "/user/login.html"); } } else { @@ -93,11 +113,11 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { } } - private void responseLogin302Header(DataOutputStream dos, String cookie) { + private void responseLogin302Header(DataOutputStream dos, String cookie, String url) { try { dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); - dos.writeBytes("Location: /index.html" + "\r\n"); + dos.writeBytes("Location: " + url + "\r\n"); dos.writeBytes("\r\n"); } catch (IOException e) { log.error(e.getMessage()); From d4e31a918d225aecc1073e6869693a7d0372b64f Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 23 Jul 2022 13:03:53 +0900 Subject: [PATCH 09/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=206:?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EB=AA=A9=EB=A1=9D=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - StringBuilder를 사용해서 유저 목록을 테이블로 출력함 --- src/main/java/webserver/RequestHandler.java | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 2f6e702..ac3075d 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,7 +2,9 @@ import java.io.*; import java.net.Socket; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -86,10 +88,27 @@ public void run() { } } else if (url.equals("/user/list")){ - //TODO: 사용자 목록 출력하기 + //TODO: 한글 깨짐 해결하기 if (cookies.get("logined").equals("true")) { log.debug("쿠키확인: {}" , cookies.get("logined")); - response(out, "/user/list.html"); + Collection users = DataBase.findAll(); + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(""); + sb.append(""); + for (User u : users) { + sb.append(""); + sb.append(""); + } + sb.append(""); + sb.append("
# 사용자 아이디 이름 이메일
" + u.getUserId() + ""); + sb.append("" + u.getName() + ""); + sb.append("" + u.getEmail() + ""); + sb.append("
"); + byte[] body = sb.toString().getBytes(StandardCharsets.UTF_8); + DataOutputStream dos = new DataOutputStream(out); + response200Header(dos, body.length); + responseBody(dos, body); } else { response(out, "/user/login.html"); } From 8a85e62f1243067e94178de0ba3ebf2f26e59d9d Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Mon, 25 Jul 2022 16:23:05 +0900 Subject: [PATCH 10/25] =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=207:?= =?UTF-8?q?=20CSS=20=EC=A7=80=EC=9B=90=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 헤더에 "Accept: text/css"가 포함되어 있는경우 responseCss 메소드-> responseCss200Header를 응답하게 된다. --- src/main/java/webserver/RequestHandler.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index ac3075d..90f7d10 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -51,6 +51,9 @@ public void run() { cookies = HttpRequestUtils.parseCookies(line); log.debug("쿠키: {}", cookies); } + if(line.contains("Accept: text/css")){ + responseCss(out, url); + } log.debug("header: {}", line); } @@ -130,6 +133,15 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { } catch (IOException e) { log.error(e.getMessage()); } + }private void responseCss200Header(DataOutputStream dos, int lengthOfBodyContent) { + try { + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + dos.writeBytes("Content-Type: text/css;charset=utf-8\r\n"); + dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } } private void responseLogin302Header(DataOutputStream dos, String cookie, String url) { @@ -169,6 +181,13 @@ private void response(OutputStream out, String url) throws IOException { responseBody(dos, body); } + private void responseCss(OutputStream out, String url) throws IOException { + DataOutputStream dos = new DataOutputStream(out); + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + responseCss200Header(dos, body.length); + responseBody(dos, body); + } + private int getContentLength(String line) { String[] split = line.split(":"); return Integer.parseInt(split[1].trim()); From fdb87d3f1289e7b160da025593d12b7685498f9b Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Mon, 25 Jul 2022 17:02:00 +0900 Subject: [PATCH 11/25] =?UTF-8?q?TODO:=20=ED=95=9C=EA=B8=80=20=EA=B9=A8?= =?UTF-8?q?=EC=A7=90=20=ED=95=B4=EA=B2=B0=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유저 생성시에 URLdecoder의 decode를 사용해서 한글로 변환후 저장하도록 했다. --- src/main/java/webserver/RequestHandler.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 90f7d10..fad854b 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,6 +2,7 @@ import java.io.*; import java.net.Socket; +import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Collection; @@ -58,7 +59,9 @@ public void run() { } if (url.startsWith("/user/create")){ - String body = IOUtils.readData(br, contentLength); + + String body = URLDecoder.decode(IOUtils.readData(br, contentLength), StandardCharsets.UTF_8); + log.debug("바디: {}", body); Map params = HttpRequestUtils.parseQueryString(body); User user = new User(params.get("userId"), params.get("password"), params.get("name"), params.get("email")); @@ -91,7 +94,6 @@ public void run() { } } else if (url.equals("/user/list")){ - //TODO: 한글 깨짐 해결하기 if (cookies.get("logined").equals("true")) { log.debug("쿠키확인: {}" , cookies.get("logined")); Collection users = DataBase.findAll(); @@ -101,9 +103,10 @@ public void run() { sb.append(""); for (User u : users) { sb.append(""); - sb.append("" + u.getUserId() + ""); - sb.append("" + u.getName() + ""); - sb.append("" + u.getEmail() + ""); + sb.append("#"); + sb.append("" + u.getUserId() + ""); + sb.append("" + u.getName() + ""); + sb.append("" + u.getEmail() + ""); sb.append(""); } sb.append(""); From 1290d6df5e12b28e044a3faec327fa88a3f57020 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 2 Aug 2022 21:07:18 +0900 Subject: [PATCH 12/25] =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=201?= =?UTF-8?q?=EB=8B=A8=EA=B3=84:=20=EC=9A=94=EC=B2=AD=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=20=EC=B2=98=EB=A6=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=84=EB=8F=84=EC=9D=98=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET일 때 읽어오는 로직 작성 - header 값을 제외하고 다른 값을 잘 가져오고 있음. 로그로 확인했을 때는 잘 들어오나 마지막에 NPE가 터져서 테스트 오류발생. - TODO: POST도 읽어올 수 있도록 로직 작성 및 수정 필요함 --- src/main/java/http/HttpRequest.java | 61 +++++++++++++++++++++++++ src/test/java/http/HttpRequestTest.java | 22 +++++++++ src/test/resources/Http_GET.txt | 4 ++ src/test/resources/Http_POST.txt | 8 ++++ 4 files changed, 95 insertions(+) create mode 100644 src/main/java/http/HttpRequest.java create mode 100644 src/test/java/http/HttpRequestTest.java create mode 100644 src/test/resources/Http_GET.txt create mode 100644 src/test/resources/Http_POST.txt diff --git a/src/main/java/http/HttpRequest.java b/src/main/java/http/HttpRequest.java new file mode 100644 index 0000000..106173f --- /dev/null +++ b/src/main/java/http/HttpRequest.java @@ -0,0 +1,61 @@ +package http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +public class HttpRequest { + private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); + private String method; + private String path; + private Map header = new HashMap<>(); + private Map parameter = new HashMap<>(); + + public HttpRequest(InputStream in) { + try(in){ + BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + String line = br.readLine(); + String[] s = line.split(" "); + method = s[0]; + String[] split1 = s[1].split("[?]"); + path = split1[0]; + parameter = HttpRequestUtils.parseQueryString(split1[1]); + + if (line == null) { + return; + } + line = br.readLine(); + log.debug("라인: {}", line); + while (!line.equals("")) { + String[] split = line.split(":"); + header.put(split[0].trim(), split[1].trim()); + line = br.readLine(); + } + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getHeader(String s) { + return header.get(s); + } + + public String getParameter(String s) { + return parameter.get(s); + } +} diff --git a/src/test/java/http/HttpRequestTest.java b/src/test/java/http/HttpRequestTest.java new file mode 100644 index 0000000..fec0c39 --- /dev/null +++ b/src/test/java/http/HttpRequestTest.java @@ -0,0 +1,22 @@ +package http; +import java.io.*; + +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.*; + +public class HttpRequestTest { + private String testDirectory = "./src/test/resources/"; + + @Test + public void request_GET() throws Exception{ + InputStream in = new FileInputStream(new File(testDirectory + "Http_GET.txt")); + HttpRequest request = new HttpRequest(in); + + + assertThat("GET").isEqualTo(request.getMethod()); + assertThat("/user/create").isEqualTo(request.getPath()); + assertThat("keep-alive").isEqualTo(request.getHeader("Connection")); + assertThat("javajigi").isEqualTo(request.getParameter("userId")); + + } +} diff --git a/src/test/resources/Http_GET.txt b/src/test/resources/Http_GET.txt new file mode 100644 index 0000000..437b554 --- /dev/null +++ b/src/test/resources/Http_GET.txt @@ -0,0 +1,4 @@ +GET /user/create?userId=javajigi&password=password&name=tester HTTP/1.1 +Host: localhost:8080 +Connection: keep-alive +Accept: */* diff --git a/src/test/resources/Http_POST.txt b/src/test/resources/Http_POST.txt new file mode 100644 index 0000000..be3664b --- /dev/null +++ b/src/test/resources/Http_POST.txt @@ -0,0 +1,8 @@ +POST /user/create HTTP/1.1 +Host: localhost:8080 +Connection: keep-alive +Content-Length: 46 +Content-Type: application/x-www-form-urlencoded +Accept: */* + +userId=javajigi&password=password&name=tester From 9327f7cc404bca0c11007b52a64d9fbfd74300f6 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 2 Aug 2022 21:32:30 +0900 Subject: [PATCH 13/25] =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=201?= =?UTF-8?q?=EB=8B=A8=EA=B3=84:=20method=EA=B0=80=20POST=EC=9D=BC=20?= =?UTF-8?q?=EB=95=8C=EB=8F=84=20=EC=9D=BD=EC=96=B4=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트 통과 - 아직도 HttpRequestTest.request_GET 테스트에서 NPE가 터져서 테스트 오류발생.(HttpRequest의 while문에서 발생.) --- src/main/java/http/HttpRequest.java | 29 ++++++++++++++++++++----- src/test/java/http/HttpRequestTest.java | 12 ++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/main/java/http/HttpRequest.java b/src/main/java/http/HttpRequest.java index 106173f..3a9a49a 100644 --- a/src/main/java/http/HttpRequest.java +++ b/src/main/java/http/HttpRequest.java @@ -3,11 +3,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; +import util.IOUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -22,15 +25,13 @@ public HttpRequest(InputStream in) { try(in){ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line = br.readLine(); - String[] s = line.split(" "); - method = s[0]; - String[] split1 = s[1].split("[?]"); - path = split1[0]; - parameter = HttpRequestUtils.parseQueryString(split1[1]); + parseRequestLine(line); + if (line == null) { return; } + line = br.readLine(); log.debug("라인: {}", line); while (!line.equals("")) { @@ -38,11 +39,29 @@ public HttpRequest(InputStream in) { header.put(split[0].trim(), split[1].trim()); line = br.readLine(); } + + if (method.equals("POST")){ + String body = URLDecoder.decode(IOUtils.readData(br, Integer.parseInt(header.get("Content-Length"))), StandardCharsets.UTF_8); + parameter = HttpRequestUtils.parseQueryString(body); + } } catch (IOException e) { log.error(e.getMessage()); } } + public void parseRequestLine(String line){ + String[] parsedLines = line.split(" "); + method = parsedLines[0]; + if (method.equals("POST")){ + path = parsedLines[1]; + return; + } + String[] split1 = parsedLines[1].split("[?]"); + path = split1[0]; + parameter = HttpRequestUtils.parseQueryString(split1[1]); + log.debug("유저아이디: {}, 비밀번호: {}, 유저이름: {}", parameter.get("userId"), parameter.get("password"), parameter.get("name")); + } + public String getMethod() { return method; } diff --git a/src/test/java/http/HttpRequestTest.java b/src/test/java/http/HttpRequestTest.java index fec0c39..bd07044 100644 --- a/src/test/java/http/HttpRequestTest.java +++ b/src/test/java/http/HttpRequestTest.java @@ -19,4 +19,16 @@ public void request_GET() throws Exception{ assertThat("javajigi").isEqualTo(request.getParameter("userId")); } + + @Test + public void request_POST() throws Exception{ + InputStream in = new FileInputStream(new File(testDirectory + "Http_POST.txt")); + HttpRequest request = new HttpRequest(in); + + assertThat("POST").isEqualTo(request.getMethod()); + assertThat("/user/create").isEqualTo(request.getPath()); + assertThat("keep-alive").isEqualTo(request.getHeader("Connection")); + assertThat("javajigi").isEqualTo(request.getParameter("userId")); + + } } From 4e647f25efdd671b796fae8b7c989c171e01f632 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Wed, 3 Aug 2022 16:45:44 +0900 Subject: [PATCH 14/25] =?UTF-8?q?Fix:=20HttpRequestTest.request=5FGET?= =?UTF-8?q?=EC=97=90=EC=84=9C=20NPE=20=EB=B0=9C=EC=83=9D=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Http_GET.txt 파일에 한 줄 더 추가함. - br.readline()은 캐리지 리턴을 포함해 한 줄을 전부 읽어오는데 마지막줄에서 끝나버리니 null이 발생. 한줄을 추가해서 line이 빈 줄이라는 것을 확인하고 while문을 탈출하면 npe가 발생하지 않는다. --- src/test/resources/Http_GET.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/Http_GET.txt b/src/test/resources/Http_GET.txt index 437b554..0313030 100644 --- a/src/test/resources/Http_GET.txt +++ b/src/test/resources/Http_GET.txt @@ -2,3 +2,4 @@ GET /user/create?userId=javajigi&password=password&name=tester HTTP/1.1 Host: localhost:8080 Connection: keep-alive Accept: */* + From 937f17e316be9f52320533a6b21402e113ac8e13 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Fri, 5 Aug 2022 18:07:58 +0900 Subject: [PATCH 15/25] =?UTF-8?q?Test:=20HttpResponseTest=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 넥스트스텝에서 제공해주는 HttpResponseTest 작성 --- src/test/java/http/HttpResponseTest.java | 40 ++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/java/http/HttpResponseTest.java diff --git a/src/test/java/http/HttpResponseTest.java b/src/test/java/http/HttpResponseTest.java new file mode 100644 index 0000000..2982e85 --- /dev/null +++ b/src/test/java/http/HttpResponseTest.java @@ -0,0 +1,40 @@ +package http; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; + +public class HttpResponseTest { + private String testDirectory = "./src/test/resources/"; + + @Test + public void responseForward() throws Exception{ + //http_forward.txt 결과는 응답 body에 index.html이 포함되어 있어야 한다. + HttpResponse response = new HttpResponse(createOutputStream("Http_Forward.txt")); + response.forward("/index.html"); + } + + @Test + public void responseRedirect() throws Exception{ + // http_redirect.txt 결과는 응답 header에 + // location 정보가 /index.html로 포함되어 있어야 한다 + HttpResponse response = new HttpResponse(createOutputStream("Http_Forward.txt")); + response.sendRedirect("/index.html"); + } + + @Test + public void responseCookies() throws Exception{ + //http_cookie.txt 결과는 응답 header에 set-cookie 값으로 + //logined=true 값이 포함되어 있어야 한다. + HttpResponse response = new HttpResponse(createOutputStream("Http_Forward.txt")); + response.addHeader("Set-Cookie", "logined=true"); + response.sendRedirect("/index.html"); + } + + private OutputStream createOutputStream(String filename) throws FileNotFoundException { + return new FileOutputStream(new File(testDirectory + filename)); + } +} From 72c2506f139c21db72da9b896ca4d2b02473e07a Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Fri, 5 Aug 2022 18:14:03 +0900 Subject: [PATCH 16/25] =?UTF-8?q?Feat:=20HttpResponse=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HttpResponse 클래스를 생성하고 테스트코드에서 힌트를 얻어 필요한 메서드들을 생성 - RequestHandler에서 response 관련 분리하여 메서드 생성 --- src/main/java/http/HttpResponse.java | 84 ++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/main/java/http/HttpResponse.java diff --git a/src/main/java/http/HttpResponse.java b/src/main/java/http/HttpResponse.java new file mode 100644 index 0000000..1c58154 --- /dev/null +++ b/src/main/java/http/HttpResponse.java @@ -0,0 +1,84 @@ +package http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class HttpResponse { + private static final Logger log = LoggerFactory.getLogger(HttpResponse.class); + private DataOutputStream dos = null; + private Map header = new HashMap(); + + public HttpResponse(OutputStream out) { + dos = new DataOutputStream(out); + } + + public void forward(String url) { + try { + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + if (url.endsWith(".css")) { + header.put("Content-Type", "text/css"); + } else { + header.put("Content-Type", "text/html;charset=uft-8"); + } + header.put("Content-length", body.length + ""); + response200Header(body.length); + responseBody(body); + } catch (IOException e) { + log.debug(e.getMessage()); + } + } + + public void response200Header(int length) { + try { + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + writeHeaders(); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + public void responseBody(byte[] body) { + try { + dos.write(body, 0, body.length); + dos.flush(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + private void writeHeaders() { + try { + Set keys = header.keySet(); + for (String key : keys) { + dos.writeBytes(key + ": " + header.get(key) + "\r\n"); + } + } catch (IOException e){ + log.error(e.getMessage()); + } + } + + public void sendRedirect(String url) { + try { + dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); + writeHeaders(); + dos.writeBytes("Location: " + url + "\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + public void addHeader(String key, String value) { + header.put(key, value); + } + +} From d518a8f37c131d2d1cba6a17f7ae3171816f32bf Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 6 Aug 2022 18:08:15 +0900 Subject: [PATCH 17/25] =?UTF-8?q?Refactor:=20RequestHandler=EC=97=90=20Htt?= =?UTF-8?q?pResponse=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RequestHandler에 있던 response 관련 로직 삭제하고 HttpResponse 사용하도록 수정 - httpResponse의 기존 메서드로는 유저리스트를 보여줄 수 없어 httpResponse에 forwardBody라는 메서드 추가. --- src/main/java/http/HttpResponse.java | 8 ++ src/main/java/webserver/RequestHandler.java | 94 +++------------------ 2 files changed, 20 insertions(+), 82 deletions(-) diff --git a/src/main/java/http/HttpResponse.java b/src/main/java/http/HttpResponse.java index 1c58154..baecf24 100644 --- a/src/main/java/http/HttpResponse.java +++ b/src/main/java/http/HttpResponse.java @@ -37,6 +37,13 @@ public void forward(String url) { } } + public void forwardBody(byte[] body) { + header.put("Content-Type", "text/html;charset=uft-8"); + header.put("Content-length", body.length + ""); + response200Header(body.length); + responseBody(body); + } + public void response200Header(int length) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); @@ -77,6 +84,7 @@ public void sendRedirect(String url) { } } + public void addHeader(String key, String value) { header.put(key, value); } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index fad854b..390c7e6 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -10,6 +10,7 @@ import java.util.Map; import db.DataBase; +import http.HttpResponse; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +33,7 @@ public void run() { try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { // 3.4.3.1 1단계: 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. + HttpResponse httpResponse = new HttpResponse(out); BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line = br.readLine(); log.debug("request line: {}", line); @@ -53,7 +55,7 @@ public void run() { log.debug("쿠키: {}", cookies); } if(line.contains("Accept: text/css")){ - responseCss(out, url); + httpResponse.forward(url); } log.debug("header: {}", line); } @@ -68,8 +70,7 @@ public void run() { DataBase.addUser(user); log.debug("user: {}", user); - DataOutputStream dos = new DataOutputStream(out); - response302Header(dos, "/index.html"); + httpResponse.sendRedirect("/index.html"); } else if (url.equals("/user/login")){ String body = IOUtils.readData(br, contentLength); @@ -78,19 +79,14 @@ public void run() { log.debug("로그인유저: {}", user ); if (user == null) { - response(out, "/user/login_failed.html"); + httpResponse.forward("/user/login_failed.html"); return; } if (user.getPassword().equals(params.get("password"))){ - DataOutputStream dos = new DataOutputStream(out); - String cookie = "logined=true"; - String redirect ="/index.html"; - responseLogin302Header(dos, cookie, redirect); + httpResponse.addHeader("Set-Cookie", "logined=true"); + httpResponse.sendRedirect("/index.html"); } else { - DataOutputStream dos = new DataOutputStream(out); - String cookie = "logined=false"; - String redirect = "/user/login_failed.html"; - responseLogin302Header(dos, cookie, redirect); + httpResponse.sendRedirect("/user/login_failed.html"); } } else if (url.equals("/user/list")){ @@ -111,86 +107,20 @@ public void run() { } sb.append(""); sb.append(""); - byte[] body = sb.toString().getBytes(StandardCharsets.UTF_8); - DataOutputStream dos = new DataOutputStream(out); - response200Header(dos, body.length); - responseBody(dos, body); + + httpResponse.forwardBody(sb.toString().getBytes(StandardCharsets.UTF_8)); } else { - response(out, "/user/login.html"); + httpResponse.sendRedirect("/user/login.html"); } } else { - response(out, url); + httpResponse.forward(url); } } catch (IOException e) { log.error(e.getMessage()); } } - private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - }private void responseCss200Header(DataOutputStream dos, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/css;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void responseLogin302Header(DataOutputStream dos, String cookie, String url) { - try { - dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); - dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); - dos.writeBytes("Location: " + url + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void response302Header(DataOutputStream dos, String url) { - try { - dos.writeBytes("HTTP/1.1 302 Found \r\n"); - dos.writeBytes("Location: " + url + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos, byte[] body) { - try { - dos.write(body, 0, body.length); - dos.flush(); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void response(OutputStream out, String url) throws IOException { - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - response200Header(dos, body.length); - responseBody(dos, body); - } - - private void responseCss(OutputStream out, String url) throws IOException { - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - responseCss200Header(dos, body.length); - responseBody(dos, body); - } - private int getContentLength(String line) { String[] split = line.split(":"); return Integer.parseInt(split[1].trim()); From b08aaeffa4d0b245fcf45199aad5c8e09259a620 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 9 Aug 2022 17:12:09 +0900 Subject: [PATCH 18/25] =?UTF-8?q?Refactor:=20HttpResponse=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=98=A4=ED=83=88=EC=9E=90,=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=EB=90=9C=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HttpResponse.responseBody에서 마지막에 캐리지리턴을 빼먹어서 해당부분 추가함 - "Content-length"를 "Content-Length"로 수정 - .js 파일 읽을 수 있도록 헤더에 해당 부분 추가 로직 구현 --- src/main/java/http/HttpResponse.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/http/HttpResponse.java b/src/main/java/http/HttpResponse.java index baecf24..12f4f0c 100644 --- a/src/main/java/http/HttpResponse.java +++ b/src/main/java/http/HttpResponse.java @@ -20,16 +20,17 @@ public class HttpResponse { public HttpResponse(OutputStream out) { dos = new DataOutputStream(out); } - public void forward(String url) { try { byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); if (url.endsWith(".css")) { header.put("Content-Type", "text/css"); + } else if (url.endsWith(".js")){ + header.put("Content-Type", "application/javascript"); } else { header.put("Content-Type", "text/html;charset=uft-8"); } - header.put("Content-length", body.length + ""); + header.put("Content-Length", body.length + ""); response200Header(body.length); responseBody(body); } catch (IOException e) { @@ -39,12 +40,12 @@ public void forward(String url) { public void forwardBody(byte[] body) { header.put("Content-Type", "text/html;charset=uft-8"); - header.put("Content-length", body.length + ""); + header.put("Content-Length", body.length + ""); response200Header(body.length); responseBody(body); } - public void response200Header(int length) { + public void response200Header(int lengthOfBody) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); writeHeaders(); @@ -57,6 +58,7 @@ public void response200Header(int length) { public void responseBody(byte[] body) { try { dos.write(body, 0, body.length); + dos.writeBytes("\r\n"); dos.flush(); } catch (IOException e) { log.error(e.getMessage()); From a7c8eccea239976fcaef665465674f3c3d23a84e Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 9 Aug 2022 17:13:27 +0900 Subject: [PATCH 19/25] =?UTF-8?q?Refactor:=20HttpRequest.parseRequestLine?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET 방식이지만 Parameter를 받지 않는 경우에 대응하기 위해 코드 수정 --- src/main/java/http/HttpRequest.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/http/HttpRequest.java b/src/main/java/http/HttpRequest.java index 3a9a49a..3a06f00 100644 --- a/src/main/java/http/HttpRequest.java +++ b/src/main/java/http/HttpRequest.java @@ -33,8 +33,8 @@ public HttpRequest(InputStream in) { } line = br.readLine(); - log.debug("라인: {}", line); while (!line.equals("")) { + log.debug("헤더: {}", line); String[] split = line.split(":"); header.put(split[0].trim(), split[1].trim()); line = br.readLine(); @@ -50,16 +50,22 @@ public HttpRequest(InputStream in) { } public void parseRequestLine(String line){ + log.debug("라인: {}", line); String[] parsedLines = line.split(" "); method = parsedLines[0]; if (method.equals("POST")){ path = parsedLines[1]; return; } - String[] split1 = parsedLines[1].split("[?]"); - path = split1[0]; - parameter = HttpRequestUtils.parseQueryString(split1[1]); - log.debug("유저아이디: {}, 비밀번호: {}, 유저이름: {}", parameter.get("userId"), parameter.get("password"), parameter.get("name")); + + int index = parsedLines[1].indexOf("?"); + if (index == -1) { + path = parsedLines[1]; + } else { + path = parsedLines[1].substring(0, index); + parameter = HttpRequestUtils.parseQueryString(parsedLines[1].substring(index+1)); + } +// log.debug("유저아이디: {}, 비밀번호: {}, 유저이름: {}", parameter.get("userId"), parameter.get("password"), parameter.get("name")); } public String getMethod() { From f2672b6e1b7a52d6d74e4f8407e9edde9f79e17a Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Tue, 9 Aug 2022 17:32:06 +0900 Subject: [PATCH 20/25] =?UTF-8?q?Refactor:=20RequestHandler=EC=97=90=20Htt?= =?UTF-8?q?pRequest=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RequestHandler에 있던 request 관련 로직 삭제 하고 HttpRequest 사용하도록 수정 - 로그인 여부 체크하기 위해 isLogined 메서드 생성 --- src/main/java/webserver/RequestHandler.java | 86 +++++++-------------- 1 file changed, 27 insertions(+), 59 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 390c7e6..f9e2cdb 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,21 +1,19 @@ package webserver; -import java.io.*; -import java.net.Socket; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - import db.DataBase; +import http.HttpRequest; import http.HttpResponse; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; -import util.IOUtils; + +import java.io.*; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; public class RequestHandler extends Thread { @@ -32,66 +30,37 @@ public void run() { connection.getPort()); try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // 3.4.3.1 1단계: 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. + HttpRequest httpRequest = new HttpRequest(in); HttpResponse httpResponse = new HttpResponse(out); - BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); - String line = br.readLine(); - log.debug("request line: {}", line); - String url = parseLine(line); - - int contentLength = 0; - Map cookies = new HashMap<>(); - //2단계 + 3단계 - if (line == null) { - return; - } - while (!line.equals("")){ - line = br.readLine(); - if (line.contains("Content-Length")){ - contentLength = getContentLength(line); - } - if (line.contains("Cookie")){ - cookies = HttpRequestUtils.parseCookies(line); - log.debug("쿠키: {}", cookies); - } - if(line.contains("Accept: text/css")){ - httpResponse.forward(url); - } - log.debug("header: {}", line); - } + String path = httpRequest.getPath(); + - if (url.startsWith("/user/create")){ + if (("/user/create").equals(path)){ + User user = new User(httpRequest.getParameter("userId"), httpRequest.getParameter("password"), + httpRequest.getParameter("name"), httpRequest.getParameter("email")); - String body = URLDecoder.decode(IOUtils.readData(br, contentLength), StandardCharsets.UTF_8); - log.debug("바디: {}", body); - Map params = HttpRequestUtils.parseQueryString(body); - User user = new User(params.get("userId"), params.get("password"), params.get("name"), - params.get("email")); DataBase.addUser(user); log.debug("user: {}", user); httpResponse.sendRedirect("/index.html"); - } else if (url.equals("/user/login")){ - String body = IOUtils.readData(br, contentLength); - Map params = HttpRequestUtils.parseQueryString(body); - User user = DataBase.findUserById(params.get("userId")); + } else if (("/user/login").equals(path)){ + User user = DataBase.findUserById(httpRequest.getParameter("userId")); log.debug("로그인유저: {}", user ); if (user == null) { httpResponse.forward("/user/login_failed.html"); return; } - if (user.getPassword().equals(params.get("password"))){ + if (user.getPassword().equals(httpRequest.getParameter("password"))){ httpResponse.addHeader("Set-Cookie", "logined=true"); httpResponse.sendRedirect("/index.html"); } else { httpResponse.sendRedirect("/user/login_failed.html"); } - } else if (url.equals("/user/list")){ - if (cookies.get("logined").equals("true")) { - log.debug("쿠키확인: {}" , cookies.get("logined")); + } else if (("/user/list").equals(path)){ + if (isLogined(httpRequest.getHeader("Cookie"))) { Collection users = DataBase.findAll(); StringBuilder sb = new StringBuilder(); sb.append(""); @@ -114,20 +83,19 @@ public void run() { } } else { - httpResponse.forward(url); + httpResponse.forward(path); } } catch (IOException e) { log.error(e.getMessage()); } } - private int getContentLength(String line) { - String[] split = line.split(":"); - return Integer.parseInt(split[1].trim()); - } - - private String parseLine(String line){ - String[] parsedLines = line.split(" "); - return parsedLines[1]; + //TODO: HttpRequest에 있어야 하는게 맞겠지..? 생각해보기. + private boolean isLogined(String cookie) { + Map cookies = HttpRequestUtils.parseCookies(cookie); + if(cookies.get("logined") != null && cookies.get("logined").equals("true")) { + return true; + } + return false; } } From 3d8bd7a46d1b11e56f296e03a10080deee8286ef Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Wed, 17 Aug 2022 22:35:30 +0900 Subject: [PATCH 21/25] =?UTF-8?q?fix:=20socket=20closed=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 웹서버 실행 중에 socket closed 에러가 발생했는데 try안에 in을 받아서였다. 해당 부분 수정하니 에러 해결. --- src/main/java/http/HttpRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/http/HttpRequest.java b/src/main/java/http/HttpRequest.java index 3a06f00..2dfe721 100644 --- a/src/main/java/http/HttpRequest.java +++ b/src/main/java/http/HttpRequest.java @@ -22,7 +22,7 @@ public class HttpRequest { private Map parameter = new HashMap<>(); public HttpRequest(InputStream in) { - try(in){ + try { BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line = br.readLine(); parseRequestLine(line); From fd5a7af8e596aa273de1d4dfb23bee4ed462a420 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 17 Sep 2022 09:04:06 +0900 Subject: [PATCH 22/25] =?UTF-8?q?Refactor:=20RequestMapping=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 들어오는 요청에 따라 알맞은 컨트롤러를 탈 수 있도록 RequestMapping 클래스를 생성함 --- src/main/java/webserver/RequestMapping.java | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/webserver/RequestMapping.java diff --git a/src/main/java/webserver/RequestMapping.java b/src/main/java/webserver/RequestMapping.java new file mode 100644 index 0000000..320e576 --- /dev/null +++ b/src/main/java/webserver/RequestMapping.java @@ -0,0 +1,23 @@ +package webserver; + +import controller.Controller; +import controller.CreateUserController; +import controller.ListUserController; +import controller.LoginController; + +import java.util.HashMap; +import java.util.Map; + +public class RequestMapping { + private static Map controllers = new HashMap(); + + static { + controllers.put("/user/create", new CreateUserController()); + controllers.put("/user/login", new LoginController()); + controllers.put("/user/list", new ListUserController()); + } + + public static Controller getController (String requestUrl) { + return controllers.get(requestUrl); + } +} From 47e946e3010614d79f48147032a84973a23ac41a Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 17 Sep 2022 09:05:35 +0900 Subject: [PATCH 23/25] =?UTF-8?q?Refactor:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4,=20?= =?UTF-8?q?=EC=B6=94=EC=83=81=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 공통된 부분을 추출해 컨트롤러 인터페이스를 작성하고 해당 인터페이스를 구현하는 추상 클래스를 생성 --- .../java/controller/AbstractController.java | 20 +++++++++++++++++++ src/main/java/controller/Controller.java | 8 ++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/main/java/controller/AbstractController.java create mode 100644 src/main/java/controller/Controller.java diff --git a/src/main/java/controller/AbstractController.java b/src/main/java/controller/AbstractController.java new file mode 100644 index 0000000..eed12b9 --- /dev/null +++ b/src/main/java/controller/AbstractController.java @@ -0,0 +1,20 @@ +package controller; + +import http.HttpRequest; +import http.HttpResponse; + +public abstract class AbstractController implements Controller{ + @Override + public void service(HttpRequest request, HttpResponse response) { + + } + + public void doPost(HttpRequest request, HttpResponse response) { + + } + + public void doGet(HttpRequest request, HttpResponse response) { + + } + +} diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java new file mode 100644 index 0000000..3d23ddc --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,8 @@ +package controller; + +import http.HttpRequest; +import http.HttpResponse; + +public interface Controller { + void service(HttpRequest request, HttpResponse response); +} From 97df9a0799653978fe8e23af060143cd536407f5 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 17 Sep 2022 09:06:13 +0900 Subject: [PATCH 24/25] =?UTF-8?q?Refactor:=20=EC=9A=94=EC=B2=AD=EC=97=90?= =?UTF-8?q?=20=EB=A7=9E=EB=8A=94=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유저 생성 컨트롤러, 유저 리스트 컨트롤러, 로그인 컨트롤러 생성 --- .../java/controller/CreateUserController.java | 22 +++++++++ .../java/controller/ListUserController.java | 49 +++++++++++++++++++ src/main/java/controller/LoginController.java | 28 +++++++++++ 3 files changed, 99 insertions(+) create mode 100644 src/main/java/controller/CreateUserController.java create mode 100644 src/main/java/controller/ListUserController.java create mode 100644 src/main/java/controller/LoginController.java diff --git a/src/main/java/controller/CreateUserController.java b/src/main/java/controller/CreateUserController.java new file mode 100644 index 0000000..3a5fb5e --- /dev/null +++ b/src/main/java/controller/CreateUserController.java @@ -0,0 +1,22 @@ +package controller; + +import db.DataBase; +import http.HttpRequest; +import http.HttpResponse; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CreateUserController extends AbstractController{ + private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); + @Override + public void doPost(HttpRequest request, HttpResponse response) { + User user = new User(request.getParameter("userId"), request.getParameter("password"), + request.getParameter("name"), request.getParameter("email")); + + DataBase.addUser(user); + log.debug("user: {}", user); + + response.sendRedirect("/index.html"); + } +} diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java new file mode 100644 index 0000000..cbac2d7 --- /dev/null +++ b/src/main/java/controller/ListUserController.java @@ -0,0 +1,49 @@ +package controller; + +import db.DataBase; +import http.HttpRequest; +import http.HttpResponse; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Map; + +public class ListUserController extends AbstractController{ + private final Logger log = LoggerFactory.getLogger(ListUserController.class); + @Override + public void doPost(HttpRequest request, HttpResponse response) { + if (isLogined(request.getHeader("Cookie"))) { + Collection users = DataBase.findAll(); + StringBuilder sb = new StringBuilder(); + sb.append("
"); + sb.append(""); + sb.append(""); + for (User u : users) { + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + } + sb.append(""); + sb.append("
# 사용자 아이디 이름 이메일
#" + u.getUserId() + "" + u.getName() + "" + u.getEmail() + "
"); + + response.forwardBody(sb.toString().getBytes(StandardCharsets.UTF_8)); + } else { + response.sendRedirect("/user/login.html"); + } + } + + public boolean isLogined(String s) { + Map cookies = HttpRequestUtils.parseCookies(s); + if(cookies.get("logined") != null && cookies.get("logined").equals("true")) { + return true; + } + return false; + } +} diff --git a/src/main/java/controller/LoginController.java b/src/main/java/controller/LoginController.java new file mode 100644 index 0000000..325d115 --- /dev/null +++ b/src/main/java/controller/LoginController.java @@ -0,0 +1,28 @@ +package controller; + +import db.DataBase; +import http.HttpRequest; +import http.HttpResponse; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoginController extends AbstractController{ + private final Logger log = LoggerFactory.getLogger(LoginController.class); + @Override + public void doPost(HttpRequest request, HttpResponse response) { + User user = DataBase.findUserById(request.getParameter("userId")); + log.debug("로그인유저: {}", user ); + + if (user == null) { + response.forward("/user/login_failed.html"); + return; + } + if (user.getPassword().equals(request.getParameter("password"))){ + response.addHeader("Set-Cookie", "logined=true"); + response.sendRedirect("/index.html"); + } else { + response.sendRedirect("/user/login_failed.html"); + } + } +} From 33c0dc44f44cc152d922f73a1131b156094a5bd5 Mon Sep 17 00:00:00 2001 From: leekm0310 Date: Sat, 17 Sep 2022 09:07:14 +0900 Subject: [PATCH 25/25] =?UTF-8?q?Refactor:=20RequestHandler=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 앞에서 생성한 컨트롤러를 요청에 따라 탈 수 있도록 RequestHandler 수정 --- src/main/java/webserver/RequestHandler.java | 72 +++------------------ 1 file changed, 10 insertions(+), 62 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index f9e2cdb..abace9c 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,19 +1,13 @@ package webserver; -import db.DataBase; +import controller.Controller; import http.HttpRequest; import http.HttpResponse; -import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; import java.io.*; import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; public class RequestHandler extends Thread { @@ -32,70 +26,24 @@ public void run() { try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { HttpRequest httpRequest = new HttpRequest(in); HttpResponse httpResponse = new HttpResponse(out); - String path = httpRequest.getPath(); - if (("/user/create").equals(path)){ - User user = new User(httpRequest.getParameter("userId"), httpRequest.getParameter("password"), - httpRequest.getParameter("name"), httpRequest.getParameter("email")); - - DataBase.addUser(user); - log.debug("user: {}", user); - - httpResponse.sendRedirect("/index.html"); - - } else if (("/user/login").equals(path)){ - User user = DataBase.findUserById(httpRequest.getParameter("userId")); - log.debug("로그인유저: {}", user ); - - if (user == null) { - httpResponse.forward("/user/login_failed.html"); - return; - } - if (user.getPassword().equals(httpRequest.getParameter("password"))){ - httpResponse.addHeader("Set-Cookie", "logined=true"); - httpResponse.sendRedirect("/index.html"); - } else { - httpResponse.sendRedirect("/user/login_failed.html"); - } - - } else if (("/user/list").equals(path)){ - if (isLogined(httpRequest.getHeader("Cookie"))) { - Collection users = DataBase.findAll(); - StringBuilder sb = new StringBuilder(); - sb.append(""); - sb.append(""); - sb.append(""); - for (User u : users) { - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""); - } - sb.append(""); - sb.append("
# 사용자 아이디 이름 이메일
#" + u.getUserId() + "" + u.getName() + "" + u.getEmail() + "
"); - - httpResponse.forwardBody(sb.toString().getBytes(StandardCharsets.UTF_8)); - } else { - httpResponse.sendRedirect("/user/login.html"); - } - - } else { + Controller controller = RequestMapping.getController(httpRequest.getPath()); + if (controller == null) { + String path = getDefaultPath(httpRequest.getPath()); httpResponse.forward(path); + } else { + controller.service(httpRequest, httpResponse); } } catch (IOException e) { log.error(e.getMessage()); } } - //TODO: HttpRequest에 있어야 하는게 맞겠지..? 생각해보기. - private boolean isLogined(String cookie) { - Map cookies = HttpRequestUtils.parseCookies(cookie); - if(cookies.get("logined") != null && cookies.get("logined").equals("true")) { - return true; + private String getDefaultPath(String path) { + if (path.equals("/")) { + return "/index.html"; } - return false; + return path; } }