From e6e490dbe2f0c4c28582d915cabd11cfe5f2b74b Mon Sep 17 00:00:00 2001 From: Shion Date: Sat, 27 Mar 2021 15:16:45 +0900 Subject: [PATCH 01/14] =?UTF-8?q?2=EB=8B=A8=EA=B3=84=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EA=B0=80=EC=9D=B4=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f7ef2e..4d234ad 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,9 @@ ### 요구사항 7 - 지금까지 구현한 소스 코드는 stylesheet 파일을 지원하지 못하고 있다. Stylesheet 파일을 지원하도록 구현하도록 한다. +## 2단계 - 리팩토링 - - - +- 리팩토링 접근 방법 - 메소드 분리 및 클래스 분리 +- 클라이언트 요청 데이터를 처리하는 로직을 별도의 클래스로 분리한다.(HttpRequest) +- 클라이언트 응답 데이터를 처리하는 로직을 별도의 클래스로 분리한다.(HttpResponse) +- 다형성을 활용해 클라이언트 요청 URL에 대한 분기 처리를 제거한다. From 074a52e05d5439a93ed370ee08ec5e6dae5bb3ce Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 15:46:42 +0900 Subject: [PATCH 02/14] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EB=A0=88=EA=B1=B0=EC=8B=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- src/test/java/util/HttpRequestUtilsTest.java | 13 ++++++++----- src/test/java/util/IOUtilsTest.java | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 039b2bc..f3e7889 100644 --- a/build.gradle +++ b/build.gradle @@ -23,4 +23,4 @@ dependencies { test { useJUnitPlatform() -} \ No newline at end of file +} diff --git a/src/test/java/util/HttpRequestUtilsTest.java b/src/test/java/util/HttpRequestUtilsTest.java index a4265f5..b3e41a8 100644 --- a/src/test/java/util/HttpRequestUtilsTest.java +++ b/src/test/java/util/HttpRequestUtilsTest.java @@ -7,8 +7,11 @@ import org.junit.Test; +import org.junit.jupiter.api.Test; import util.HttpRequestUtils.Pair; +import static org.assertj.core.api.Assertions.assertThat; + public class HttpRequestUtilsTest { @Test public void parseQueryString() { @@ -26,21 +29,21 @@ public void parseQueryString() { @Test public void parseQueryString_null() { Map parameters = HttpRequestUtils.parseQueryString(null); - assertThat(parameters.isEmpty(), is(true)); + assertThat(parameters.isEmpty()).isTrue(); parameters = HttpRequestUtils.parseQueryString(""); - assertThat(parameters.isEmpty(), is(true)); + assertThat(parameters.isEmpty()).isTrue(); parameters = HttpRequestUtils.parseQueryString(" "); - assertThat(parameters.isEmpty(), is(true)); + assertThat(parameters.isEmpty()).isTrue(); } @Test public void parseQueryString_invalid() { String queryString = "userId=javajigi&password"; Map parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId"), is("javajigi")); - assertThat(parameters.get("password"), is(nullValue())); + assertThat(parameters.get("userId")).isEqualTo("javajigi"); + assertThat(parameters.get("password")).isNull(); } @Test diff --git a/src/test/java/util/IOUtilsTest.java b/src/test/java/util/IOUtilsTest.java index 3c00cc4..eb8812b 100644 --- a/src/test/java/util/IOUtilsTest.java +++ b/src/test/java/util/IOUtilsTest.java @@ -3,7 +3,7 @@ import java.io.BufferedReader; import java.io.StringReader; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From c5a9085f0cefd45edfb90bd1b0cbba6460fbeb09 Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 17:36:06 +0900 Subject: [PATCH 03/14] =?UTF-8?q?test:=20Request=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/webserver/HttpRequestTest.java | 37 ++++++++++++++++++++ src/test/resources/Http_GET.txt | 4 +++ src/test/resources/Http_POST.txt | 8 +++++ 3 files changed, 49 insertions(+) create mode 100644 src/test/java/webserver/HttpRequestTest.java create mode 100644 src/test/resources/Http_GET.txt create mode 100644 src/test/resources/Http_POST.txt diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java new file mode 100644 index 0000000..52e2040 --- /dev/null +++ b/src/test/java/webserver/HttpRequestTest.java @@ -0,0 +1,37 @@ +package webserver; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import static org.assertj.core.api.Assertions.assertThat; + +class HttpRequestTest { + + private String testDirectory = "./src/test/resources/"; + + @Test + public void request_GET() throws Exception { + InputStream in = new FileInputStream(testDirectory + "Http_GET.txt"); + HttpRequest request = new HttpRequest(in); + + assertThat("GET").isEqualTo(request.getMethod().name()); + assertThat("/user/create").isEqualTo(request.getPath()); + assertThat("keep-alive").isEqualTo(request.getHeader("Connection")); + assertThat("javajigi").isEqualTo(request.getParameter("userId")); + } + + @Test + public void request_POST() throws Exception { + InputStream in = new FileInputStream(testDirectory + "Http_POST.txt"); + HttpRequest request = new HttpRequest(in); + + assertThat("POST").isEqualTo(request.getMethod().name()); + 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..bd2324b --- /dev/null +++ b/src/test/resources/Http_GET.txt @@ -0,0 +1,4 @@ +GET /user/create?userId=javajigi&password=password&name=JaeSung 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..2b62495 --- /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=JaeSung From 732de5b2e3f154d035f810539d24f4ca8f9e1952 Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 17:41:39 +0900 Subject: [PATCH 04/14] =?UTF-8?q?fix:=20GET=EC=9D=BC=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=20=EC=8A=A4=ED=8A=B8=EB=A7=81=EC=97=90?= =?UTF-8?q?=EC=84=9C,=20POST=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=EB=A6=AC?= =?UTF-8?q?=ED=80=98=EC=8A=A4=ED=8A=B8=20=EB=B0=94=EB=94=94=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/HttpRequest.java | 61 ++++++++++++++++---- src/main/java/webserver/RequestHandler.java | 38 +++--------- src/test/java/util/HttpRequestUtilsTest.java | 31 +++++----- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java index 9be415f..84590b2 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/webserver/HttpRequest.java @@ -5,28 +5,66 @@ import util.HttpRequestUtils; import util.IOUtils; -import java.io.BufferedReader; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; public class HttpRequest { private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); - private String startLine; + private String requestLine; private Map headers; + private BufferedReader br; + private String RequestBody; + private Map parameters; - public HttpRequest(String startLine, Map headers) { - this.startLine = startLine; - this.headers = headers; + public HttpRequest(InputStream in) { + try { + br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + requestLine = br.readLine(); + String line = requestLine; + if (line == null) { + return; + } + headers = new HashMap<>(); + while (!"".equals(line)) { + System.out.println(line); + line = br.readLine(); + if (line == null) { + break; + } + String[] headerTokens = line.split(": "); + if (headerTokens.length == 2) { + headers.put(headerTokens[0], headerTokens[1]); + } + } + if (headers.get("Content-Length") == null) { + String tokens = requestLine.split(" ")[1]; + String queryString = tokens.substring(tokens.indexOf("?") + 1); + parameters = HttpRequestUtils.parseQueryString(queryString); + } + if (headers.get("Content-Length") != null) { + RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); + parameters = HttpRequestUtils.parseQueryString(RequestBody); + } + log.info("parameters : {}", parameters.toString()); + } catch (IOException e) { + e.printStackTrace(); + } } public HttpMethod getMethod() { - String[] tokens = startLine.split(" "); + String[] tokens = requestLine.split(" "); String method = tokens[0]; return HttpMethod.valueOf(method); } public String getPath() { - String[] tokens = startLine.split(" "); + String[] tokens = requestLine.split(" "); + if (tokens[1].contains("?")) { + return tokens[1].substring(0, tokens[1].indexOf("?")); + } return tokens[1]; } @@ -34,10 +72,11 @@ public String getHeader(String fieldName) { return headers.get(fieldName); } - public String getParameter(String fieldName, BufferedReader br) throws Exception { - String RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); - Map parameters = HttpRequestUtils.parseQueryString(RequestBody); - log.info("parameters : {}", parameters.toString()); + public Map headers() { + return headers; + } + + public String getParameter(String fieldName) throws IOException { return parameters.get(fieldName); } } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 75f3e21..c4be650 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -27,21 +27,7 @@ public void run() { try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. - BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); - - String requestLine = br.readLine(); - String line = requestLine; - Map headers = new HashMap<>(); - while (!"".equals(line)) { - System.out.println(line); - line = br.readLine(); - String[] headerTokens = line.split(": "); - if (headerTokens.length == 2) { - headers.put(headerTokens[0], headerTokens[1]); - } - } - - HttpRequest httpRequest = new HttpRequest(requestLine, headers); + HttpRequest httpRequest = new HttpRequest(in); HttpResponse httpResponse = new HttpResponse(out); HttpMethod method = httpRequest.getMethod(); @@ -51,22 +37,16 @@ public void run() { DataOutputStream dos = new DataOutputStream(out); if (url.startsWith("/create")) { - String RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); - Map parameters = HttpRequestUtils.parseQueryString(RequestBody); - log.info("user : {}", parameters.toString()); - DataBase.addUser(new User(parameters.get("userId"), parameters.get("password"), parameters.get("name"), parameters.get("email"))); + String userId = httpRequest.getParameter("userId"); + String password = httpRequest.getParameter("password"); + String name = httpRequest.getParameter("name"); + String email = httpRequest.getParameter("email"); + DataBase.addUser(new User(userId, password, name, email)); httpResponse.sendRedirect("/index.html"); } else if (url.startsWith("/login")) { - String contentLength = headers.get("Content-Length"); - log.info("contentLength : {}", contentLength); - String RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); - - Map info = HttpRequestUtils.parseQueryString(RequestBody); - String userId = info.get("userId"); - String password = info.get("password"); + String userId = httpRequest.getParameter("userId"); + String password = httpRequest.getParameter("password"); User targetUser = DataBase.findUserById(userId); - log.info("userId : {}", userId); - log.info("password : {}", password); if (targetUser == null || !password.equals(targetUser.getPassword())) { httpResponse.addHeader("Set-Cookie", "logined=false"); httpResponse.sendRedirect("/user/login_failed.html"); @@ -76,7 +56,7 @@ public void run() { httpResponse.sendRedirect("/index.html"); } } else if (url.startsWith("/list")) { - String cookies = headers.get("Cookie"); + String cookies = httpRequest.getHeader("Cookie"); Map cookieStringMap = HttpRequestUtils.parseCookies(cookies); log.info("Cookie: {}", cookieStringMap.toString()); if (cookieStringMap.get("logined").equals("false")) { diff --git a/src/test/java/util/HttpRequestUtilsTest.java b/src/test/java/util/HttpRequestUtilsTest.java index b3e41a8..fb83e0b 100644 --- a/src/test/java/util/HttpRequestUtilsTest.java +++ b/src/test/java/util/HttpRequestUtilsTest.java @@ -1,12 +1,7 @@ package util; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; - import java.util.Map; -import org.junit.Test; - import org.junit.jupiter.api.Test; import util.HttpRequestUtils.Pair; @@ -17,13 +12,13 @@ public class HttpRequestUtilsTest { public void parseQueryString() { String queryString = "userId=javajigi"; Map parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId"), is("javajigi")); - assertThat(parameters.get("password"), is(nullValue())); + assertThat(parameters.get("userId")).isEqualTo("javajigi"); + assertThat(parameters.get("password")).isNull(); queryString = "userId=javajigi&password=password2"; parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId"), is("javajigi")); - assertThat(parameters.get("password"), is("password2")); + assertThat(parameters.get("userId")).isEqualTo("javajigi"); + assertThat(parameters.get("password")).isEqualTo("password2"); } @Test @@ -50,27 +45,27 @@ public void parseQueryString_invalid() { public void parseCookies() { String cookies = "logined=true; JSessionId=1234"; Map parameters = HttpRequestUtils.parseCookies(cookies); - assertThat(parameters.get("logined"), is("true")); - assertThat(parameters.get("JSessionId"), is("1234")); - assertThat(parameters.get("session"), is(nullValue())); + assertThat(parameters.get("logined")).isEqualTo("true"); + assertThat(parameters.get("JSessionId")).isEqualTo("1234"); + assertThat(parameters.get("session")).isNull(); } @Test - public void getKeyValue() throws Exception { + public void getKeyValue() { Pair pair = HttpRequestUtils.getKeyValue("userId=javajigi", "="); - assertThat(pair, is(new Pair("userId", "javajigi"))); + assertThat(pair).isEqualTo(new Pair("userId", "javajigi")); } @Test - public void getKeyValue_invalid() throws Exception { + public void getKeyValue_invalid() { Pair pair = HttpRequestUtils.getKeyValue("userId", "="); - assertThat(pair, is(nullValue())); + assertThat(pair).isNull(); } @Test - public void parseHeader() throws Exception { + public void parseHeader() { String header = "Content-Length: 59"; Pair pair = HttpRequestUtils.parseHeader(header); - assertThat(pair, is(new Pair("Content-Length", "59"))); + assertThat(pair).isEqualTo(new Pair("Content-Length", "59")); } } From 65f8d64504e74275d8b67e52ca86f45d5290a198 Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 18:02:58 +0900 Subject: [PATCH 05/14] =?UTF-8?q?test:=20HttpResponse=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/HttpResponse.java | 13 ++ src/test/java/webserver/HttpResponseTest.java | 37 +++++ src/test/resources/Http_Cookie.txt | 3 + src/test/resources/Http_Forward.txt | 152 ++++++++++++++++++ src/test/resources/Http_Redirect.txt | 2 + 5 files changed, 207 insertions(+) create mode 100644 src/test/java/webserver/HttpResponseTest.java create mode 100644 src/test/resources/Http_Cookie.txt create mode 100644 src/test/resources/Http_Forward.txt create mode 100644 src/test/resources/Http_Redirect.txt diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index fa2c929..8b20ad7 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -26,6 +26,8 @@ public void forward(String url) throws IOException { byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); if (url.endsWith(".css")) { response200HeaderWithCss(body.length); + } else if (url.endsWith(".js")) { + response200HeaderWithJs(body.length); } else { response200Header(body.length); } @@ -47,6 +49,17 @@ public void response200HeaderWithCss(int lengthOfBodyContent) { } } + public void response200HeaderWithJs(int lengthOfBodyContent) { + try { + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + dos.writeBytes("Content-Type: application/javascript\r\n"); + dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + public void response200Header(int lengthOfBodyContent) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); diff --git a/src/test/java/webserver/HttpResponseTest.java b/src/test/java/webserver/HttpResponseTest.java new file mode 100644 index 0000000..91514a5 --- /dev/null +++ b/src/test/java/webserver/HttpResponseTest.java @@ -0,0 +1,37 @@ +package webserver; + +import org.junit.jupiter.api.Test; + +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_Redirect.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_Cookie.txt")); + response.addHeader("Set-Cookie", "logined=true"); + response.sendRedirect("/index.html"); + } + + private OutputStream createOutputStream(String filename) throws FileNotFoundException { + return new FileOutputStream(testDirectory + filename); + } +} diff --git a/src/test/resources/Http_Cookie.txt b/src/test/resources/Http_Cookie.txt new file mode 100644 index 0000000..c0a4480 --- /dev/null +++ b/src/test/resources/Http_Cookie.txt @@ -0,0 +1,3 @@ +HTTP/1.1 302 Found +Set-Cookie: logined=true +Location: /index.html diff --git a/src/test/resources/Http_Forward.txt b/src/test/resources/Http_Forward.txt new file mode 100644 index 0000000..d2a8dcd --- /dev/null +++ b/src/test/resources/Http_Forward.txt @@ -0,0 +1,152 @@ +HTTP/1.1 200 OK +Content-Type: text/html;charset=utf-8 +Content-Length: 7049 + + + + + + + SLiPP Java Web Programming + + + + + + + + + + +
+
+
+ +
+
+
+ +
+ +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/src/test/resources/Http_Redirect.txt b/src/test/resources/Http_Redirect.txt new file mode 100644 index 0000000..7f8efa9 --- /dev/null +++ b/src/test/resources/Http_Redirect.txt @@ -0,0 +1,2 @@ +HTTP/1.1 302 Found +Location: /index.html From 47bcfceef2c5e04e28a3ca94f51e23606ad924c1 Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 18:57:45 +0900 Subject: [PATCH 06/14] =?UTF-8?q?Refactor:=20Controller=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=A4=91=EB=B3=B5=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Controller 인터페이스 추가 - AbstractController 추상 클래스 추가 - AbstractController를 상속하는 CreateUserController, ListUserController, LoginController 클래스 추가 --- .../java/controller/AbstractController.java | 27 ++++++++ src/main/java/controller/Controller.java | 8 +++ .../java/controller/CreateUserController.java | 23 +++++++ .../java/controller/ListUserController.java | 62 ++++++++++++++++++ src/main/java/controller/LoginController.java | 28 ++++++++ src/main/java/webserver/HttpMethod.java | 4 ++ src/main/java/webserver/HttpRequest.java | 6 +- src/main/java/webserver/HttpResponse.java | 2 +- src/main/java/webserver/RequestHandler.java | 64 +++---------------- src/test/java/webserver/HttpRequestTest.java | 1 - webapp/index.html | 4 +- 11 files changed, 168 insertions(+), 61 deletions(-) create mode 100644 src/main/java/controller/AbstractController.java create mode 100644 src/main/java/controller/Controller.java 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/AbstractController.java b/src/main/java/controller/AbstractController.java new file mode 100644 index 0000000..a26dbdb --- /dev/null +++ b/src/main/java/controller/AbstractController.java @@ -0,0 +1,27 @@ +package controller; + +import webserver.HttpMethod; +import webserver.HttpRequest; +import webserver.HttpResponse; + +public abstract class AbstractController implements Controller { + + @Override + public void service(HttpRequest request, HttpResponse response) { + HttpMethod method = request.getMethod(); + + if (method.isPost()) { + doPost(request, response); + } else { + doGet(request, 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..a3dda1d --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,8 @@ +package controller; + +import webserver.HttpRequest; +import webserver.HttpResponse; + +public interface Controller { + void service(HttpRequest request, HttpResponse response); +} diff --git a/src/main/java/controller/CreateUserController.java b/src/main/java/controller/CreateUserController.java new file mode 100644 index 0000000..c1e9f6a --- /dev/null +++ b/src/main/java/controller/CreateUserController.java @@ -0,0 +1,23 @@ +package controller; + +import db.DataBase; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import webserver.HttpRequest; +import webserver.HttpResponse; + +public class CreateUserController extends AbstractController { + private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); + + @Override + public void doPost(HttpRequest request, HttpResponse response) { + String userId = request.getParameter("userId"); + String password = request.getParameter("password"); + String name = request.getParameter("name"); + String email = request.getParameter("email"); + DataBase.addUser(new User(userId, password, name, email)); + response.sendRedirect("/index.html"); + log.debug("{}님이 회원가입에 성공하셨습니다.", userId); + } +} diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java new file mode 100644 index 0000000..ea1ad2f --- /dev/null +++ b/src/main/java/controller/ListUserController.java @@ -0,0 +1,62 @@ +package controller; + +import db.DataBase; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; +import webserver.HttpRequest; +import webserver.HttpResponse; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collection; +import java.util.Map; + +public class ListUserController extends AbstractController { + private static final Logger log = LoggerFactory.getLogger(ListUserController.class); + + @Override + public void doGet(HttpRequest request, HttpResponse response) { + String cookies = request.getHeader("Cookie"); + Map cookieStringMap = HttpRequestUtils.parseCookies(cookies); + log.info("Cookie: {}", cookieStringMap.toString()); + if (cookieStringMap.get("logined").equals("false")) { + response.sendRedirect("/user/login.html"); + } else { + String url = "/user/list.html"; + byte[] body = new byte[0]; + try { + body = Files.readAllBytes(new File("./webapp" + url).toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + String bodyStr = new String(body); + int tbodyIndex = bodyStr.indexOf(""); + log.info("bodyStr : {}", bodyStr.substring(0, tbodyIndex + 7)); + + StringBuilder result = new StringBuilder(bodyStr.substring(0, tbodyIndex + 7)); + Collection users = DataBase.findAll(); + int id = 0; + for (User user : users) { + id++; + result.append("") + .append(id).append(" ") + .append(user.getUserId()).append(" ") + .append(user.getName()).append(" ") + .append(user.getEmail()).append(" ") + .append("수정"); + } + result.append(bodyStr.substring(tbodyIndex + 7)); + log.info("result: {}", result.toString()); + response.response200Header(result.toString().getBytes().length); + response.responseBody(result.toString().getBytes()); + } + } + + public boolean isLogin(String id) { + + return false; + } +} diff --git a/src/main/java/controller/LoginController.java b/src/main/java/controller/LoginController.java new file mode 100644 index 0000000..e47db39 --- /dev/null +++ b/src/main/java/controller/LoginController.java @@ -0,0 +1,28 @@ +package controller; + +import db.DataBase; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import webserver.HttpRequest; +import webserver.HttpResponse; + +public class LoginController extends AbstractController { + private static final Logger log = LoggerFactory.getLogger(LoginController.class); + + @Override + public void doPost(HttpRequest request, HttpResponse response) { + String userId = request.getParameter("userId"); + String password = request.getParameter("password"); + User targetUser = DataBase.findUserById(userId); + // todo : 세션의 작동원리를 깊히 생각해보기 + if (targetUser == null || !password.equals(targetUser.getPassword())) { + response.addHeader("Set-Cookie", "logined=false"); + response.sendRedirect("/user/login_failed.html"); + } else if (password.equals(targetUser.getPassword())) { + response.addHeader("Set-Cookie", "logined=true"); + response.sendRedirect("/index.html"); + log.info("{}님이 로그인하셨습니다.", userId); + } + } +} diff --git a/src/main/java/webserver/HttpMethod.java b/src/main/java/webserver/HttpMethod.java index 3db4524..a6214f9 100644 --- a/src/main/java/webserver/HttpMethod.java +++ b/src/main/java/webserver/HttpMethod.java @@ -2,4 +2,8 @@ public enum HttpMethod { GET, POST; + + public boolean isPost() { + return this == POST; + } } diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java index 84590b2..df29087 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/webserver/HttpRequest.java @@ -28,8 +28,8 @@ public HttpRequest(InputStream in) { return; } headers = new HashMap<>(); - while (!"".equals(line)) { - System.out.println(line); + while (!line.isEmpty()) { + log.info("headers : {}", line); line = br.readLine(); if (line == null) { break; @@ -76,7 +76,7 @@ public Map headers() { return headers; } - public String getParameter(String fieldName) throws IOException { + public String getParameter(String fieldName) { return parameters.get(fieldName); } } diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index 8b20ad7..b8f3b3b 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -86,7 +86,7 @@ public void sendRedirect(String url) { processHeaders(); dos.writeBytes("Location: " + url + "\r\n"); } catch (IOException e) { - + e.printStackTrace(); } } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index c4be650..fba7632 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,15 +2,13 @@ import java.io.*; import java.net.Socket; -import java.nio.file.Files; -import java.util.*; -import db.DataBase; -import model.User; +import controller.Controller; +import controller.CreateUserController; +import controller.ListUserController; +import controller.LoginController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; -import util.IOUtils; public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); @@ -26,7 +24,6 @@ public void run() { connection.getPort()); try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. HttpRequest httpRequest = new HttpRequest(in); HttpResponse httpResponse = new HttpResponse(out); @@ -34,57 +31,16 @@ public void run() { log.info("Http Method: {}", method.name()); String url = httpRequest.getPath(); log.info("path : {}", url); - DataOutputStream dos = new DataOutputStream(out); if (url.startsWith("/create")) { - String userId = httpRequest.getParameter("userId"); - String password = httpRequest.getParameter("password"); - String name = httpRequest.getParameter("name"); - String email = httpRequest.getParameter("email"); - DataBase.addUser(new User(userId, password, name, email)); - httpResponse.sendRedirect("/index.html"); + Controller createUserController = new CreateUserController(); + createUserController.service(httpRequest, httpResponse); } else if (url.startsWith("/login")) { - String userId = httpRequest.getParameter("userId"); - String password = httpRequest.getParameter("password"); - User targetUser = DataBase.findUserById(userId); - if (targetUser == null || !password.equals(targetUser.getPassword())) { - httpResponse.addHeader("Set-Cookie", "logined=false"); - httpResponse.sendRedirect("/user/login_failed.html"); - } else if (password.equals(targetUser.getPassword())) { - log.info("로그인 성공"); - httpResponse.addHeader("Set-Cookie", "logined=true"); - httpResponse.sendRedirect("/index.html"); - } + Controller loginController = new LoginController(); + loginController.service(httpRequest, httpResponse); } else if (url.startsWith("/list")) { - String cookies = httpRequest.getHeader("Cookie"); - Map cookieStringMap = HttpRequestUtils.parseCookies(cookies); - log.info("Cookie: {}", cookieStringMap.toString()); - if (cookieStringMap.get("logined").equals("false")) { - httpResponse.sendRedirect("/user/login.html"); - } else { - url = "/user/list.html"; - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - String bodyStr = new String(body); - int tbodyIndex = bodyStr.indexOf(""); - log.info("bodyStr : {}", bodyStr.substring(0, tbodyIndex + 7)); - - StringBuilder result = new StringBuilder(bodyStr.substring(0, tbodyIndex + 7)); - Collection users = DataBase.findAll(); - int id = 0; - for (User user : users) { - id++; - result.append("") - .append(id).append(" ") - .append(user.getUserId()).append(" ") - .append(user.getName()).append(" ") - .append(user.getEmail()).append(" ") - .append("수정"); - } - result.append(bodyStr.substring(tbodyIndex + 7)); - log.info("result: {}", result.toString()); - httpResponse.response200Header(result.toString().getBytes().length); - httpResponse.responseBody(result.toString().getBytes()); - } + Controller listUserController = new ListUserController(); + listUserController.service(httpRequest, httpResponse); } else { httpResponse.forward(url); } diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java index 52e2040..8ff7196 100644 --- a/src/test/java/webserver/HttpRequestTest.java +++ b/src/test/java/webserver/HttpRequestTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.Test; -import java.io.File; import java.io.FileInputStream; import java.io.InputStream; diff --git a/webapp/index.html b/webapp/index.html index 1675898..92f6b0b 100644 --- a/webapp/index.html +++ b/webapp/index.html @@ -40,7 +40,7 @@
  • Facebook
  • -
  • +
  • @@ -145,4 +145,4 @@ - \ No newline at end of file + From 2ef2e763bd2138bfff47d95669ce75a9f0091271 Mon Sep 17 00:00:00 2001 From: janeljs Date: Mon, 29 Mar 2021 19:23:46 +0900 Subject: [PATCH 07/14] =?UTF-8?q?Refactor:=20URL=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EB=B6=84=EA=B8=B0=20=EC=B2=98=EB=A6=AC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20response200Header=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=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 - URL과 Controller를 Map에 저장해서 if문 제거 - response200Header 메서드에 contentType 파라미터를 추가하여 리팩토링 --- .../java/controller/ListUserController.java | 2 +- src/main/java/webserver/HttpResponse.java | 32 +++---------------- src/main/java/webserver/RequestHandler.java | 26 ++++++++------- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java index ea1ad2f..475d925 100644 --- a/src/main/java/controller/ListUserController.java +++ b/src/main/java/controller/ListUserController.java @@ -50,7 +50,7 @@ public void doGet(HttpRequest request, HttpResponse response) { } result.append(bodyStr.substring(tbodyIndex + 7)); log.info("result: {}", result.toString()); - response.response200Header(result.toString().getBytes().length); + response.response200Header(result.toString().getBytes().length, "text/html"); response.responseBody(result.toString().getBytes()); } } diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index b8f3b3b..08fd717 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -25,11 +25,11 @@ public void addHeader(String fieldName, String fieldValue) { public void forward(String url) throws IOException { byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); if (url.endsWith(".css")) { - response200HeaderWithCss(body.length); + response200Header(body.length, "text/css"); } else if (url.endsWith(".js")) { - response200HeaderWithJs(body.length); + response200Header(body.length, "application/javascript"); } else { - response200Header(body.length); + response200Header(body.length, "text/html"); } responseBody(body); } @@ -38,32 +38,10 @@ public void forwardBody(String string) { } - public void response200HeaderWithCss(int lengthOfBodyContent) { + public void response200Header(int lengthOfBodyContent, String contentType) { 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()); - } - } - - public void response200HeaderWithJs(int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: application/javascript\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - public void response200Header(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-Type:" + contentType + ";charset=utf-8\r\n"); dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); dos.writeBytes("\r\n"); } catch (IOException e) { diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index fba7632..c45ac6b 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,6 +2,8 @@ import java.io.*; import java.net.Socket; +import java.util.HashMap; +import java.util.Map; import controller.Controller; import controller.CreateUserController; @@ -13,7 +15,14 @@ public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - private Socket connection; + private static final Map CONTROLLER_MAP = new HashMap<>(); + private final Socket connection; + + static { + CONTROLLER_MAP.put("/create", new CreateUserController()); + CONTROLLER_MAP.put("/login", new LoginController()); + CONTROLLER_MAP.put("/list", new ListUserController()); + } public RequestHandler(Socket connectionSocket) { this.connection = connectionSocket; @@ -31,19 +40,12 @@ public void run() { log.info("Http Method: {}", method.name()); String url = httpRequest.getPath(); log.info("path : {}", url); - - if (url.startsWith("/create")) { - Controller createUserController = new CreateUserController(); - createUserController.service(httpRequest, httpResponse); - } else if (url.startsWith("/login")) { - Controller loginController = new LoginController(); - loginController.service(httpRequest, httpResponse); - } else if (url.startsWith("/list")) { - Controller listUserController = new ListUserController(); - listUserController.service(httpRequest, httpResponse); - } else { + if (!CONTROLLER_MAP.containsKey(url)) { httpResponse.forward(url); + return; } + Controller controller = CONTROLLER_MAP.get(url); + controller.service(httpRequest, httpResponse); } catch (IOException e) { log.error(e.getMessage()); } From 2dfd22b8428c3f36953e83bfd6fa4ee65d5c68a4 Mon Sep 17 00:00:00 2001 From: Shion Date: Tue, 30 Mar 2021 14:43:17 +0900 Subject: [PATCH 08/14] =?UTF-8?q?fix=20:=20POST=EC=97=90=EC=84=9C=EB=8F=84?= =?UTF-8?q?=20queryString=EC=9D=84=20=ED=99=9C=EC=9A=A9=ED=95=9C=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=84=EB=8B=AC=20=EC=A7=80?= =?UTF-8?q?=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/HttpRequest.java | 14 +++++----- src/test/java/webserver/HttpRequestTest.java | 27 ++++++++++++++------ src/test/resources/Http_Forward.txt | 8 +++--- src/test/resources/Http_POST2.txt | 8 ++++++ 4 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 src/test/resources/Http_POST2.txt diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java index df29087..ea49912 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/webserver/HttpRequest.java @@ -16,7 +16,8 @@ public class HttpRequest { private String requestLine; private Map headers; private BufferedReader br; - private String RequestBody; + private String RequestBody = ""; + private String queryString = ""; private Map parameters; public HttpRequest(InputStream in) { @@ -39,15 +40,16 @@ public HttpRequest(InputStream in) { headers.put(headerTokens[0], headerTokens[1]); } } - if (headers.get("Content-Length") == null) { - String tokens = requestLine.split(" ")[1]; - String queryString = tokens.substring(tokens.indexOf("?") + 1); - parameters = HttpRequestUtils.parseQueryString(queryString); + + String[] tokens = requestLine.split(" "); + if (tokens[1].contains("?")) { + queryString = tokens[1].substring(tokens[1].indexOf("?") + 1); } if (headers.get("Content-Length") != null) { RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); - parameters = HttpRequestUtils.parseQueryString(RequestBody); } + parameters = HttpRequestUtils.parseQueryString(queryString + "&" + RequestBody); + log.info("parameters : {}", parameters.toString()); } catch (IOException e) { e.printStackTrace(); diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java index 8ff7196..40b9325 100644 --- a/src/test/java/webserver/HttpRequestTest.java +++ b/src/test/java/webserver/HttpRequestTest.java @@ -16,10 +16,10 @@ public void request_GET() throws Exception { InputStream in = new FileInputStream(testDirectory + "Http_GET.txt"); HttpRequest request = new HttpRequest(in); - assertThat("GET").isEqualTo(request.getMethod().name()); - assertThat("/user/create").isEqualTo(request.getPath()); - assertThat("keep-alive").isEqualTo(request.getHeader("Connection")); - assertThat("javajigi").isEqualTo(request.getParameter("userId")); + assertThat(request.getMethod().name()).isEqualTo("GET"); + assertThat(request.getPath()).isEqualTo("/user/create"); + assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + assertThat(request.getParameter("userId")).isEqualTo("javajigi"); } @Test @@ -27,10 +27,21 @@ public void request_POST() throws Exception { InputStream in = new FileInputStream(testDirectory + "Http_POST.txt"); HttpRequest request = new HttpRequest(in); - assertThat("POST").isEqualTo(request.getMethod().name()); - assertThat("/user/create").isEqualTo(request.getPath()); - assertThat("keep-alive").isEqualTo(request.getHeader("Connection")); - assertThat("javajigi").isEqualTo(request.getParameter("userId")); + assertThat(request.getMethod().name()).isEqualTo("POST"); + assertThat(request.getPath()).isEqualTo("/user/create"); + assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + assertThat(request.getParameter("userId")).isEqualTo("javajigi"); } + @Test + public void request_POST2() throws Exception { + InputStream in = new FileInputStream(testDirectory + "Http_POST2.txt"); + HttpRequest request = new HttpRequest(in); + + assertThat(request.getMethod().name()).isEqualTo("POST"); + assertThat(request.getPath()).isEqualTo("/user/create"); + assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + assertThat(request.getParameter("id")).isEqualTo("1"); + assertThat(request.getParameter("userId")).isEqualTo("javajigi"); + } } diff --git a/src/test/resources/Http_Forward.txt b/src/test/resources/Http_Forward.txt index d2a8dcd..abfead4 100644 --- a/src/test/resources/Http_Forward.txt +++ b/src/test/resources/Http_Forward.txt @@ -1,6 +1,6 @@ HTTP/1.1 200 OK -Content-Type: text/html;charset=utf-8 -Content-Length: 7049 +Content-Type:text/html;charset=utf-8 +Content-Length: 6892 @@ -44,7 +44,7 @@ Content-Length: 7049
  • Facebook
  • -
  • +
  • @@ -149,4 +149,4 @@ Content-Length: 7049 - \ No newline at end of file + diff --git a/src/test/resources/Http_POST2.txt b/src/test/resources/Http_POST2.txt new file mode 100644 index 0000000..d8151a6 --- /dev/null +++ b/src/test/resources/Http_POST2.txt @@ -0,0 +1,8 @@ +POST /user/create?id=1 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=JaeSung \ No newline at end of file From 7f1068b0f8edd6f0900bd47cb6300771947e7dcf Mon Sep 17 00:00:00 2001 From: Shion Date: Tue, 30 Mar 2021 16:28:44 +0900 Subject: [PATCH 09/14] =?UTF-8?q?refactor=20:=20HttpRequest,=20HttpRespons?= =?UTF-8?q?e=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 --- src/main/java/webserver/HttpRequest.java | 63 ++++++++++++----------- src/main/java/webserver/HttpResponse.java | 25 +++++---- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java index ea49912..a730239 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/webserver/HttpRequest.java @@ -14,46 +14,51 @@ public class HttpRequest { private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); private String requestLine; - private Map headers; - private BufferedReader br; - private String RequestBody = ""; - private String queryString = ""; + private final Map headers = new HashMap<>(); private Map parameters; public HttpRequest(InputStream in) { try { - br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); requestLine = br.readLine(); - String line = requestLine; + processHeaders(br); + processParameters(br); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void processHeaders(BufferedReader br) throws IOException { + String line = br.readLine(); + while (!line.isEmpty()) { + log.debug("headers : {}", line); + line = br.readLine(); if (line == null) { return; } - headers = new HashMap<>(); - while (!line.isEmpty()) { - log.info("headers : {}", line); - line = br.readLine(); - if (line == null) { - break; - } - String[] headerTokens = line.split(": "); - if (headerTokens.length == 2) { - headers.put(headerTokens[0], headerTokens[1]); - } - } + parseHeader(line); + } + } - String[] tokens = requestLine.split(" "); - if (tokens[1].contains("?")) { - queryString = tokens[1].substring(tokens[1].indexOf("?") + 1); - } - if (headers.get("Content-Length") != null) { - RequestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); - } - parameters = HttpRequestUtils.parseQueryString(queryString + "&" + RequestBody); + private void parseHeader(String line) { + String[] headerTokens = line.split(": "); + if (headerTokens.length == 2) { + headers.put(headerTokens[0], headerTokens[1]); + } + } - log.info("parameters : {}", parameters.toString()); - } catch (IOException e) { - e.printStackTrace(); + private void processParameters(BufferedReader br) throws IOException { + String[] tokens = requestLine.split(" "); + String queryString = ""; + String requestBody = ""; + if (tokens[1].contains("?")) { + queryString = tokens[1].substring(tokens[1].indexOf("?") + 1); + } + if (headers.get("Content-Length") != null) { + requestBody = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); } + queryString = queryString + "&" + requestBody; + parameters = HttpRequestUtils.parseQueryString(queryString); } public HttpMethod getMethod() { diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index 08fd717..dbeb3d4 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -11,8 +11,16 @@ public class HttpResponse { private static final Logger log = LoggerFactory.getLogger(HttpResponse.class); - private Map headers = new HashMap<>(); - private DataOutputStream dos; + + private static final Map EXTENSIONS = new HashMap<>(); + private final Map headers = new HashMap<>(); + private final DataOutputStream dos; + + static { + EXTENSIONS.put(".css", "text/css"); + EXTENSIONS.put(".js", "application/javascript"); + EXTENSIONS.put(".html", "text/html"); + } public HttpResponse(OutputStream out) { this.dos = new DataOutputStream(out); @@ -24,20 +32,11 @@ public void addHeader(String fieldName, String fieldValue) { public void forward(String url) throws IOException { byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - if (url.endsWith(".css")) { - response200Header(body.length, "text/css"); - } else if (url.endsWith(".js")) { - response200Header(body.length, "application/javascript"); - } else { - response200Header(body.length, "text/html"); - } + String extension = url.substring(url.lastIndexOf(".")); + response200Header(body.length, EXTENSIONS.get(extension)); responseBody(body); } - public void forwardBody(String string) { - - } - public void response200Header(int lengthOfBodyContent, String contentType) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); From 950d599e93cf504f6b080459978fdc7f1209d08e Mon Sep 17 00:00:00 2001 From: janeljs Date: Wed, 31 Mar 2021 16:57:48 +0900 Subject: [PATCH 10/14] =?UTF-8?q?refactor:=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=8B=A8=EC=9C=84=EB=A1=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 단일책임원칙을 적용하는 방향으로 리팩토링 --- .../java/controller/CreateUserController.java | 11 ++- .../java/controller/ListUserController.java | 78 +++++++++++-------- src/main/java/webserver/HttpResponse.java | 7 ++ 3 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/main/java/controller/CreateUserController.java b/src/main/java/controller/CreateUserController.java index c1e9f6a..bb4274e 100644 --- a/src/main/java/controller/CreateUserController.java +++ b/src/main/java/controller/CreateUserController.java @@ -12,12 +12,17 @@ public class CreateUserController extends AbstractController { @Override public void doPost(HttpRequest request, HttpResponse response) { + User user = getUserFrom(request); + DataBase.addUser(user); + response.sendRedirect("/index.html"); + log.debug("{}님이 회원가입에 성공하셨습니다.", user.getUserId()); + } + + private User getUserFrom(HttpRequest request) { String userId = request.getParameter("userId"); String password = request.getParameter("password"); String name = request.getParameter("name"); String email = request.getParameter("email"); - DataBase.addUser(new User(userId, password, name, email)); - response.sendRedirect("/index.html"); - log.debug("{}님이 회원가입에 성공하셨습니다.", userId); + return new User(userId, password, name, email); } } diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java index 475d925..afd16ee 100644 --- a/src/main/java/controller/ListUserController.java +++ b/src/main/java/controller/ListUserController.java @@ -1,6 +1,7 @@ package controller; import db.DataBase; +import db.SessionDataBase; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,44 +20,55 @@ public class ListUserController extends AbstractController { @Override public void doGet(HttpRequest request, HttpResponse response) { - String cookies = request.getHeader("Cookie"); - Map cookieStringMap = HttpRequestUtils.parseCookies(cookies); - log.info("Cookie: {}", cookieStringMap.toString()); - if (cookieStringMap.get("logined").equals("false")) { + String sessionId = request.getHeader("Cookie"); + if (!isLogin(sessionId)) { response.sendRedirect("/user/login.html"); } else { - String url = "/user/list.html"; - byte[] body = new byte[0]; - try { - body = Files.readAllBytes(new File("./webapp" + url).toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - String bodyStr = new String(body); - int tbodyIndex = bodyStr.indexOf(""); - log.info("bodyStr : {}", bodyStr.substring(0, tbodyIndex + 7)); - - StringBuilder result = new StringBuilder(bodyStr.substring(0, tbodyIndex + 7)); - Collection users = DataBase.findAll(); - int id = 0; - for (User user : users) { - id++; - result.append("") - .append(id).append(" ") - .append(user.getUserId()).append(" ") - .append(user.getName()).append(" ") - .append(user.getEmail()).append(" ") - .append("수정"); - } - result.append(bodyStr.substring(tbodyIndex + 7)); - log.info("result: {}", result.toString()); - response.response200Header(result.toString().getBytes().length, "text/html"); - response.responseBody(result.toString().getBytes()); + String body = getBody("/user/list.html"); + int tbodyIndex = body.indexOf(""); + String result = addUserList(body, tbodyIndex).toString(); + response.forwardBody(result); } } - public boolean isLogin(String id) { + private boolean isLogin(String id) { + Map cookieStringMap = HttpRequestUtils.parseCookies(id); + log.info("Cookie: {}", cookieStringMap.toString()); + return SessionDataBase.isLoginUser(cookieStringMap.get("JSESSIONID")); + } + + private String getBody(String url) { + byte[] body = new byte[0]; + try { + body = Files.readAllBytes(new File("./webapp" + url).toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + return new String(body); + } + + private StringBuilder processUserList(String body, int tbodyIndex) { + StringBuilder result = new StringBuilder(body.substring(0, tbodyIndex + 7)); + Collection users = DataBase.findAll(); + int id = 0; + for (User user : users) { + id++; + result.append("") + .append(id) + .append(" ") + .append(user.getUserId()) + .append(" ") + .append(user.getName()) + .append(" ") + .append(user.getEmail()) + .append(" ") + .append("수정"); + } + return result; + } - return false; + private StringBuilder addUserList(String body, int tbodyIndex) { + StringBuilder result = processUserList(body, tbodyIndex); + return result.append(body.substring(tbodyIndex + 7)); } } diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index dbeb3d4..d674f7d 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -5,6 +5,7 @@ import java.io.DataOutputStream; import java.io.*; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; @@ -37,6 +38,12 @@ public void forward(String url) throws IOException { responseBody(body); } + public void forwardBody(String result) { + byte[] body = result.getBytes(StandardCharsets.UTF_8); + response200Header(body.length, "text/html"); + responseBody(body); + } + public void response200Header(int lengthOfBodyContent, String contentType) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); From 21d952acecf7b376a8b612d5b30465edf48ce9bc Mon Sep 17 00:00:00 2001 From: janeljs Date: Wed, 31 Mar 2021 16:58:28 +0900 Subject: [PATCH 11/14] =?UTF-8?q?fix:=20=EC=BF=A0=ED=82=A4=20=EB=B3=B4?= =?UTF-8?q?=EC=95=88=EC=9D=98=20=EC=B7=A8=EC=95=BD=EC=A0=90=EC=9D=84=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?=EC=84=B8=EC=85=98=20DB=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/LoginController.java | 9 +++++++-- src/main/java/db/SessionDataBase.java | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/main/java/db/SessionDataBase.java diff --git a/src/main/java/controller/LoginController.java b/src/main/java/controller/LoginController.java index e47db39..4071bd5 100644 --- a/src/main/java/controller/LoginController.java +++ b/src/main/java/controller/LoginController.java @@ -1,12 +1,15 @@ package controller; import db.DataBase; +import db.SessionDataBase; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import webserver.HttpRequest; import webserver.HttpResponse; +import java.util.UUID; + public class LoginController extends AbstractController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); @@ -17,10 +20,12 @@ public void doPost(HttpRequest request, HttpResponse response) { User targetUser = DataBase.findUserById(userId); // todo : 세션의 작동원리를 깊히 생각해보기 if (targetUser == null || !password.equals(targetUser.getPassword())) { - response.addHeader("Set-Cookie", "logined=false"); + response.addHeader("Set-Cookie", "loggedIn=false"); response.sendRedirect("/user/login_failed.html"); } else if (password.equals(targetUser.getPassword())) { - response.addHeader("Set-Cookie", "logined=true"); + UUID uuid = UUID.randomUUID(); + SessionDataBase.sessions.put(uuid.toString(), targetUser); + response.addHeader("Set-Cookie", SessionDataBase.JSESSIONID + "=" + uuid); response.sendRedirect("/index.html"); log.info("{}님이 로그인하셨습니다.", userId); } diff --git a/src/main/java/db/SessionDataBase.java b/src/main/java/db/SessionDataBase.java new file mode 100644 index 0000000..3311983 --- /dev/null +++ b/src/main/java/db/SessionDataBase.java @@ -0,0 +1,20 @@ +package db; + +import com.google.common.collect.Maps; +import model.User; + +import java.util.Map; + +public class SessionDataBase { + public static Map sessions = Maps.newHashMap(); + + public static final String JSESSIONID = "JSESSIONID"; + + public static boolean isLoginUser(String sessionId) { + return getSessionUser(sessionId) != null; + } + + public static User getSessionUser(String sessionId) { + return sessions.get(sessionId); + } +} From 82b8cda446467e5bbe4b9f0560e15737770bc6c6 Mon Sep 17 00:00:00 2001 From: Shion Date: Wed, 31 Mar 2021 23:28:26 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refactor=20:=20=EC=A0=84=EC=B2=B4=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 --- ...actController.java => BaseController.java} | 2 +- .../java/controller/CreateUserController.java | 2 +- .../java/controller/ListUserController.java | 2 +- src/main/java/controller/LoginController.java | 17 +++-- src/main/java/model/User.java | 4 ++ src/main/java/util/HttpRequestUtils.java | 13 ++-- src/main/java/util/IOUtils.java | 10 +-- src/main/java/webserver/RequestHandler.java | 5 +- src/test/java/util/HttpRequestUtilsTest.java | 62 ++++++++++++------- src/test/java/webserver/HttpRequestTest.java | 9 ++- 10 files changed, 75 insertions(+), 51 deletions(-) rename src/main/java/controller/{AbstractController.java => BaseController.java} (89%) diff --git a/src/main/java/controller/AbstractController.java b/src/main/java/controller/BaseController.java similarity index 89% rename from src/main/java/controller/AbstractController.java rename to src/main/java/controller/BaseController.java index a26dbdb..02b691b 100644 --- a/src/main/java/controller/AbstractController.java +++ b/src/main/java/controller/BaseController.java @@ -4,7 +4,7 @@ import webserver.HttpRequest; import webserver.HttpResponse; -public abstract class AbstractController implements Controller { +public class BaseController implements Controller { @Override public void service(HttpRequest request, HttpResponse response) { diff --git a/src/main/java/controller/CreateUserController.java b/src/main/java/controller/CreateUserController.java index bb4274e..2a19f7f 100644 --- a/src/main/java/controller/CreateUserController.java +++ b/src/main/java/controller/CreateUserController.java @@ -7,7 +7,7 @@ import webserver.HttpRequest; import webserver.HttpResponse; -public class CreateUserController extends AbstractController { +public class CreateUserController extends BaseController { private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); @Override diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java index afd16ee..3e2f9a7 100644 --- a/src/main/java/controller/ListUserController.java +++ b/src/main/java/controller/ListUserController.java @@ -15,7 +15,7 @@ import java.util.Collection; import java.util.Map; -public class ListUserController extends AbstractController { +public class ListUserController extends BaseController { private static final Logger log = LoggerFactory.getLogger(ListUserController.class); @Override diff --git a/src/main/java/controller/LoginController.java b/src/main/java/controller/LoginController.java index 4071bd5..d662665 100644 --- a/src/main/java/controller/LoginController.java +++ b/src/main/java/controller/LoginController.java @@ -10,7 +10,7 @@ import java.util.UUID; -public class LoginController extends AbstractController { +public class LoginController extends BaseController { private static final Logger log = LoggerFactory.getLogger(LoginController.class); @Override @@ -18,16 +18,15 @@ public void doPost(HttpRequest request, HttpResponse response) { String userId = request.getParameter("userId"); String password = request.getParameter("password"); User targetUser = DataBase.findUserById(userId); - // todo : 세션의 작동원리를 깊히 생각해보기 - if (targetUser == null || !password.equals(targetUser.getPassword())) { + if (targetUser == null || !targetUser.isValidPassword(password)) { response.addHeader("Set-Cookie", "loggedIn=false"); response.sendRedirect("/user/login_failed.html"); - } else if (password.equals(targetUser.getPassword())) { - UUID uuid = UUID.randomUUID(); - SessionDataBase.sessions.put(uuid.toString(), targetUser); - response.addHeader("Set-Cookie", SessionDataBase.JSESSIONID + "=" + uuid); - response.sendRedirect("/index.html"); - log.info("{}님이 로그인하셨습니다.", userId); + return; } + UUID uuid = UUID.randomUUID(); + SessionDataBase.sessions.put(uuid.toString(), targetUser); + response.addHeader("Set-Cookie", SessionDataBase.JSESSIONID + "=" + uuid); + response.sendRedirect("/index.html"); + log.info("{}님이 로그인하셨습니다.", userId); } } diff --git a/src/main/java/model/User.java b/src/main/java/model/User.java index b7abb73..b3a3127 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/model/User.java @@ -13,6 +13,10 @@ public User(String userId, String password, String name, String email) { this.email = email; } + public boolean isValidPassword(String password) { + return this.password.equals(password); + } + public String getUserId() { return userId; } diff --git a/src/main/java/util/HttpRequestUtils.java b/src/main/java/util/HttpRequestUtils.java index 6386da6..a679d7e 100644 --- a/src/main/java/util/HttpRequestUtils.java +++ b/src/main/java/util/HttpRequestUtils.java @@ -3,6 +3,7 @@ import java.net.URLDecoder; import java.util.Arrays; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import com.google.common.base.Strings; @@ -10,8 +11,8 @@ public class HttpRequestUtils { /** - * @param queryString은 - * URL에서 ? 이후에 전달되는 field1=value1&field2=value2 형식임 + * @param queryString + * 은 URL에서 ? 이후에 전달되는 field1=value1&field2=value2 형식임 * @return */ public static Map parseQueryString(String queryString) { @@ -19,7 +20,7 @@ public static Map parseQueryString(String queryString) { } /** - * @param 쿠키 + * @param cookies * 값은 name1=value1; name2=value2 형식임 * @return */ @@ -32,14 +33,14 @@ private static Map parseValues(String values, String separator) return Maps.newHashMap(); } String[] tokens = values.split(separator); - return Arrays.stream(tokens).map(t -> getKeyValue(t, "=")).filter(p -> p != null) - .collect(Collectors.toMap(p -> p.getKey(), p -> { + return Arrays.stream(tokens).map(t -> getKeyValue(t, "=")).filter(Objects::nonNull) + .collect(Collectors.toMap(Pair::getKey, p -> { try { return URLDecoder.decode(p.getValue(), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } - return null; + return p.getValue(); })); } diff --git a/src/main/java/util/IOUtils.java b/src/main/java/util/IOUtils.java index d88efe7..56186c6 100644 --- a/src/main/java/util/IOUtils.java +++ b/src/main/java/util/IOUtils.java @@ -3,18 +3,18 @@ import java.io.BufferedReader; import java.io.IOException; -public class IOUtils { +public class IOUtils { /** - * @param BufferedReader는 + * @param bufferedReader * Request Body를 시작하는 시점이어야 - * @param contentLength는 + * @param contentLength * Request Header의 Content-Length 값이다. * @return * @throws IOException */ - public static String readData(BufferedReader br, int contentLength) throws IOException { + public static String readData(BufferedReader bufferedReader, int contentLength) throws IOException { char[] body = new char[contentLength]; - br.read(body, 0, contentLength); + bufferedReader.read(body, 0, contentLength); return String.copyValueOf(body); } } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index c45ac6b..2f4214e 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -36,19 +36,16 @@ public void run() { HttpRequest httpRequest = new HttpRequest(in); HttpResponse httpResponse = new HttpResponse(out); - HttpMethod method = httpRequest.getMethod(); - log.info("Http Method: {}", method.name()); String url = httpRequest.getPath(); - log.info("path : {}", url); if (!CONTROLLER_MAP.containsKey(url)) { httpResponse.forward(url); return; } + Controller controller = CONTROLLER_MAP.get(url); controller.service(httpRequest, httpResponse); } catch (IOException e) { log.error(e.getMessage()); } - } } diff --git a/src/test/java/util/HttpRequestUtilsTest.java b/src/test/java/util/HttpRequestUtilsTest.java index fb83e0b..140f7d8 100644 --- a/src/test/java/util/HttpRequestUtilsTest.java +++ b/src/test/java/util/HttpRequestUtilsTest.java @@ -2,70 +2,86 @@ import java.util.Map; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import util.HttpRequestUtils.Pair; import static org.assertj.core.api.Assertions.assertThat; -public class HttpRequestUtilsTest { +class HttpRequestUtilsTest { + + SoftAssertions softly; + + @BeforeEach + void buildSoftAssertions() { + softly = new SoftAssertions(); + } + + @AfterEach + void afterEach() { + softly.assertAll(); + } + @Test - public void parseQueryString() { + void parseQueryString() { String queryString = "userId=javajigi"; Map parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId")).isEqualTo("javajigi"); - assertThat(parameters.get("password")).isNull(); + softly.assertThat(parameters.get("userId")).isEqualTo("javajigi"); + softly.assertThat(parameters.get("password")).isNull(); queryString = "userId=javajigi&password=password2"; parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId")).isEqualTo("javajigi"); - assertThat(parameters.get("password")).isEqualTo("password2"); + softly.assertThat(parameters.get("userId")).isEqualTo("javajigi"); + softly.assertThat(parameters.get("password")).isEqualTo("password2"); } @Test - public void parseQueryString_null() { + void parseQueryString_null() { Map parameters = HttpRequestUtils.parseQueryString(null); - assertThat(parameters.isEmpty()).isTrue(); + softly.assertThat(parameters.isEmpty()).isTrue(); parameters = HttpRequestUtils.parseQueryString(""); - assertThat(parameters.isEmpty()).isTrue(); + softly.assertThat(parameters.isEmpty()).isTrue(); parameters = HttpRequestUtils.parseQueryString(" "); - assertThat(parameters.isEmpty()).isTrue(); + softly.assertThat(parameters.isEmpty()).isTrue(); } @Test - public void parseQueryString_invalid() { + void parseQueryString_invalid() { String queryString = "userId=javajigi&password"; Map parameters = HttpRequestUtils.parseQueryString(queryString); - assertThat(parameters.get("userId")).isEqualTo("javajigi"); - assertThat(parameters.get("password")).isNull(); + softly.assertThat(parameters.get("userId")).isEqualTo("javajigi"); + softly.assertThat(parameters.get("password")).isNull(); } @Test - public void parseCookies() { + void parseCookies() { String cookies = "logined=true; JSessionId=1234"; Map parameters = HttpRequestUtils.parseCookies(cookies); - assertThat(parameters.get("logined")).isEqualTo("true"); - assertThat(parameters.get("JSessionId")).isEqualTo("1234"); - assertThat(parameters.get("session")).isNull(); + softly.assertThat(parameters.get("logined")).isEqualTo("true"); + softly.assertThat(parameters.get("JSessionId")).isEqualTo("1234"); + softly.assertThat(parameters.get("session")).isNull(); } @Test - public void getKeyValue() { + void getKeyValue() { Pair pair = HttpRequestUtils.getKeyValue("userId=javajigi", "="); - assertThat(pair).isEqualTo(new Pair("userId", "javajigi")); + softly.assertThat(pair).isEqualTo(new Pair("userId", "javajigi")); } @Test - public void getKeyValue_invalid() { + void getKeyValue_invalid() { Pair pair = HttpRequestUtils.getKeyValue("userId", "="); - assertThat(pair).isNull(); + softly.assertThat(pair).isNull(); } @Test - public void parseHeader() { + void parseHeader() { String header = "Content-Length: 59"; Pair pair = HttpRequestUtils.parseHeader(header); - assertThat(pair).isEqualTo(new Pair("Content-Length", "59")); + softly.assertThat(pair).isEqualTo(new Pair("Content-Length", "59")); } } diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java index 40b9325..ebee3b3 100644 --- a/src/test/java/webserver/HttpRequestTest.java +++ b/src/test/java/webserver/HttpRequestTest.java @@ -1,15 +1,22 @@ package webserver; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + import java.io.FileInputStream; import java.io.InputStream; import static org.assertj.core.api.Assertions.assertThat; +@ExtendWith(SoftAssertionsExtension.class) class HttpRequestTest { + private final String testDirectory = "./src/test/resources/"; - private String testDirectory = "./src/test/resources/"; + @InjectSoftAssertions + SoftAssertions softly; @Test public void request_GET() throws Exception { From 56be4655648ea3bf1b01c4c6bdbefa96baadbe07 Mon Sep 17 00:00:00 2001 From: janeljs Date: Thu, 1 Apr 2021 00:13:34 +0900 Subject: [PATCH 13/14] =?UTF-8?q?refactor:=20SoftAssertionsExtension?= =?UTF-8?q?=EC=9D=84=20=ED=99=9C=EC=9A=A9=ED=95=98=EC=97=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - assertj v.3.18.0으로 변경 - HttpRequestTest, HttpRequestUtilsTest에 SoftAssertions 적용 --- build.gradle | 2 +- src/test/java/util/HttpRequestUtilsTest.java | 21 ++++--------- src/test/java/webserver/HttpRequestTest.java | 32 +++++++++----------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/build.gradle b/build.gradle index f3e7889..3c7e5e8 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ dependencies { implementation 'org.apache.commons:commons-dbcp2:2.5.0' implementation 'org.reflections:reflections:0.9.11' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' - testImplementation 'org.assertj:assertj-core:3.11.1' + testImplementation 'org.assertj:assertj-core:3.18.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' runtimeOnly 'com.h2database:h2:1.4.200' } diff --git a/src/test/java/util/HttpRequestUtilsTest.java b/src/test/java/util/HttpRequestUtilsTest.java index 140f7d8..d2918c6 100644 --- a/src/test/java/util/HttpRequestUtilsTest.java +++ b/src/test/java/util/HttpRequestUtilsTest.java @@ -3,27 +3,18 @@ import java.util.Map; import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import util.HttpRequestUtils.Pair; -import static org.assertj.core.api.Assertions.assertThat; - +@ExtendWith(SoftAssertionsExtension.class) class HttpRequestUtilsTest { + @InjectSoftAssertions SoftAssertions softly; - @BeforeEach - void buildSoftAssertions() { - softly = new SoftAssertions(); - } - - @AfterEach - void afterEach() { - softly.assertAll(); - } - @Test void parseQueryString() { String queryString = "userId=javajigi"; @@ -46,7 +37,7 @@ void parseQueryString_null() { softly.assertThat(parameters.isEmpty()).isTrue(); parameters = HttpRequestUtils.parseQueryString(" "); - softly.assertThat(parameters.isEmpty()).isTrue(); + softly.assertThat(parameters.isEmpty()).isTrue(); } @Test diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java index ebee3b3..a5a53c0 100644 --- a/src/test/java/webserver/HttpRequestTest.java +++ b/src/test/java/webserver/HttpRequestTest.java @@ -1,16 +1,14 @@ package webserver; import org.assertj.core.api.SoftAssertions; -import org.junit.jupiter.api.*; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; import java.io.FileInputStream; import java.io.InputStream; -import static org.assertj.core.api.Assertions.assertThat; - @ExtendWith(SoftAssertionsExtension.class) class HttpRequestTest { private final String testDirectory = "./src/test/resources/"; @@ -23,10 +21,10 @@ public void request_GET() throws Exception { InputStream in = new FileInputStream(testDirectory + "Http_GET.txt"); HttpRequest request = new HttpRequest(in); - assertThat(request.getMethod().name()).isEqualTo("GET"); - assertThat(request.getPath()).isEqualTo("/user/create"); - assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); - assertThat(request.getParameter("userId")).isEqualTo("javajigi"); + softly.assertThat(request.getMethod().name()).isEqualTo("GET"); + softly.assertThat(request.getPath()).isEqualTo("/user/create"); + softly.assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + softly.assertThat(request.getParameter("userId")).isEqualTo("javajigi"); } @Test @@ -34,10 +32,10 @@ public void request_POST() throws Exception { InputStream in = new FileInputStream(testDirectory + "Http_POST.txt"); HttpRequest request = new HttpRequest(in); - assertThat(request.getMethod().name()).isEqualTo("POST"); - assertThat(request.getPath()).isEqualTo("/user/create"); - assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); - assertThat(request.getParameter("userId")).isEqualTo("javajigi"); + softly.assertThat(request.getMethod().name()).isEqualTo("POST"); + softly.assertThat(request.getPath()).isEqualTo("/user/create"); + softly.assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + softly.assertThat(request.getParameter("userId")).isEqualTo("javajigi"); } @Test @@ -45,10 +43,10 @@ public void request_POST2() throws Exception { InputStream in = new FileInputStream(testDirectory + "Http_POST2.txt"); HttpRequest request = new HttpRequest(in); - assertThat(request.getMethod().name()).isEqualTo("POST"); - assertThat(request.getPath()).isEqualTo("/user/create"); - assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); - assertThat(request.getParameter("id")).isEqualTo("1"); - assertThat(request.getParameter("userId")).isEqualTo("javajigi"); + softly.assertThat(request.getMethod().name()).isEqualTo("POST"); + softly.assertThat(request.getPath()).isEqualTo("/user/create"); + softly.assertThat(request.getHeader("Connection")).isEqualTo("keep-alive"); + softly.assertThat(request.getParameter("id")).isEqualTo("1"); + softly.assertThat(request.getParameter("userId")).isEqualTo("javajigi"); } } From 9084520289799dfb711761d4865d86c43147e2f2 Mon Sep 17 00:00:00 2001 From: janeljs Date: Fri, 2 Apr 2021 15:02:56 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor:=20=EC=93=B0=EB=A0=88=EB=93=9C?= =?UTF-8?q?=ED=92=80=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=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 --- src/main/java/controller/BaseController.java | 6 +++--- src/main/java/controller/Controller.java | 4 ++-- src/main/java/controller/CreateUserController.java | 4 ++-- src/main/java/controller/ListUserController.java | 4 ++-- src/main/java/controller/LoginController.java | 4 ++-- src/main/java/{webserver => http}/HttpMethod.java | 2 +- src/main/java/{webserver => http}/HttpRequest.java | 6 +----- src/main/java/{webserver => http}/HttpResponse.java | 2 +- src/main/java/webserver/RequestHandler.java | 2 ++ src/main/java/webserver/WebServer.java | 6 ++++-- src/test/java/webserver/HttpRequestTest.java | 1 + src/test/java/webserver/HttpResponseTest.java | 1 + 12 files changed, 22 insertions(+), 20 deletions(-) rename src/main/java/{webserver => http}/HttpMethod.java (85%) rename src/main/java/{webserver => http}/HttpRequest.java (96%) rename src/main/java/{webserver => http}/HttpResponse.java (99%) diff --git a/src/main/java/controller/BaseController.java b/src/main/java/controller/BaseController.java index 02b691b..5a6a160 100644 --- a/src/main/java/controller/BaseController.java +++ b/src/main/java/controller/BaseController.java @@ -1,8 +1,8 @@ package controller; -import webserver.HttpMethod; -import webserver.HttpRequest; -import webserver.HttpResponse; +import http.HttpMethod; +import http.HttpRequest; +import http.HttpResponse; public class BaseController implements Controller { diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java index a3dda1d..3d23ddc 100644 --- a/src/main/java/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -1,7 +1,7 @@ package controller; -import webserver.HttpRequest; -import webserver.HttpResponse; +import http.HttpRequest; +import http.HttpResponse; public interface Controller { void service(HttpRequest request, HttpResponse response); diff --git a/src/main/java/controller/CreateUserController.java b/src/main/java/controller/CreateUserController.java index 2a19f7f..906d282 100644 --- a/src/main/java/controller/CreateUserController.java +++ b/src/main/java/controller/CreateUserController.java @@ -4,8 +4,8 @@ import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.HttpRequest; -import webserver.HttpResponse; +import http.HttpRequest; +import http.HttpResponse; public class CreateUserController extends BaseController { private static final Logger log = LoggerFactory.getLogger(CreateUserController.class); diff --git a/src/main/java/controller/ListUserController.java b/src/main/java/controller/ListUserController.java index 3e2f9a7..2b2fad3 100644 --- a/src/main/java/controller/ListUserController.java +++ b/src/main/java/controller/ListUserController.java @@ -6,8 +6,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; -import webserver.HttpRequest; -import webserver.HttpResponse; +import http.HttpRequest; +import http.HttpResponse; import java.io.File; import java.io.IOException; diff --git a/src/main/java/controller/LoginController.java b/src/main/java/controller/LoginController.java index d662665..5f865d6 100644 --- a/src/main/java/controller/LoginController.java +++ b/src/main/java/controller/LoginController.java @@ -5,8 +5,8 @@ import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.HttpRequest; -import webserver.HttpResponse; +import http.HttpRequest; +import http.HttpResponse; import java.util.UUID; diff --git a/src/main/java/webserver/HttpMethod.java b/src/main/java/http/HttpMethod.java similarity index 85% rename from src/main/java/webserver/HttpMethod.java rename to src/main/java/http/HttpMethod.java index a6214f9..d344cc1 100644 --- a/src/main/java/webserver/HttpMethod.java +++ b/src/main/java/http/HttpMethod.java @@ -1,4 +1,4 @@ -package webserver; +package http; public enum HttpMethod { GET, POST; diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/http/HttpRequest.java similarity index 96% rename from src/main/java/webserver/HttpRequest.java rename to src/main/java/http/HttpRequest.java index a730239..0ecb9f5 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/http/HttpRequest.java @@ -1,4 +1,4 @@ -package webserver; +package http; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,10 +79,6 @@ public String getHeader(String fieldName) { return headers.get(fieldName); } - public Map headers() { - return headers; - } - public String getParameter(String fieldName) { return parameters.get(fieldName); } diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/http/HttpResponse.java similarity index 99% rename from src/main/java/webserver/HttpResponse.java rename to src/main/java/http/HttpResponse.java index d674f7d..b1b9e3a 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/http/HttpResponse.java @@ -1,4 +1,4 @@ -package webserver; +package http; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 2f4214e..ec69f02 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -9,6 +9,8 @@ import controller.CreateUserController; import controller.ListUserController; import controller.LoginController; +import http.HttpRequest; +import http.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/webserver/WebServer.java index 91f4a0f..bac543e 100644 --- a/src/main/java/webserver/WebServer.java +++ b/src/main/java/webserver/WebServer.java @@ -2,6 +2,8 @@ import java.net.ServerSocket; import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,9 +27,9 @@ public static void main(String args[]) throws Exception { // 클라이언트가 연결될때까지 대기한다. Socket connection; + ExecutorService executorService = Executors.newFixedThreadPool(10); while ((connection = listenSocket.accept()) != null) { - RequestHandler requestHandler = new RequestHandler(connection); - requestHandler.start(); + executorService.execute(new RequestHandler(connection)); } } } diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java index a5a53c0..d1d4104 100644 --- a/src/test/java/webserver/HttpRequestTest.java +++ b/src/test/java/webserver/HttpRequestTest.java @@ -1,5 +1,6 @@ package webserver; +import http.HttpRequest; import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/webserver/HttpResponseTest.java b/src/test/java/webserver/HttpResponseTest.java index 91514a5..13bbc1a 100644 --- a/src/test/java/webserver/HttpResponseTest.java +++ b/src/test/java/webserver/HttpResponseTest.java @@ -1,5 +1,6 @@ package webserver; +import http.HttpResponse; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException;