From 00797bccd4c459a3ba258377193251712cc56c87 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 16:55:05 +0900 Subject: [PATCH 01/24] =?UTF-8?q?test(IOStreamTest):=20IOStream=20?= =?UTF-8?q?=ED=95=99=EC=8A=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/test/java/study/IOStreamTest.java | 38 +++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/study/src/test/java/study/IOStreamTest.java b/study/src/test/java/study/IOStreamTest.java index 47a79356b6..0ff7775262 100644 --- a/study/src/test/java/study/IOStreamTest.java +++ b/study/src/test/java/study/IOStreamTest.java @@ -7,6 +7,7 @@ import java.io.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.in; import static org.mockito.Mockito.*; /** @@ -53,6 +54,7 @@ class OutputStream_학습_테스트 { * todo * OutputStream 객체의 write 메서드를 사용해서 테스트를 통과시킨다 */ + outputStream.write(bytes); final String actual = outputStream.toString(); @@ -78,6 +80,7 @@ class OutputStream_학습_테스트 { * flush를 사용해서 테스트를 통과시킨다. * ByteArrayOutputStream과 어떤 차이가 있을까? */ + outputStream.flush(); verify(outputStream, atLeastOnce()).flush(); outputStream.close(); @@ -96,6 +99,12 @@ class OutputStream_학습_테스트 { * try-with-resources를 사용한다. * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. */ + try (final var output = outputStream) { + output.write("test".getBytes()); + output.flush(); + } catch (IOException e) { + System.out.println(e.getMessage()); + } verify(outputStream, atLeastOnce()).close(); } @@ -128,7 +137,10 @@ class InputStream_학습_테스트 { * todo * inputStream에서 바이트로 반환한 값을 문자열로 어떻게 바꿀까? */ - final String actual = ""; + final OutputStream outputStream = new ByteArrayOutputStream(); + outputStream.write(inputStream.readAllBytes()); + + final String actual = outputStream.toString(); assertThat(actual).isEqualTo("🤩"); assertThat(inputStream.read()).isEqualTo(-1); @@ -148,6 +160,11 @@ class InputStream_학습_테스트 { * try-with-resources를 사용한다. * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. */ + try (final var input = inputStream) { + input.read(); + } catch (IOException e) { + System.out.println(e.getMessage()); + } verify(inputStream, atLeastOnce()).close(); } @@ -172,9 +189,14 @@ class FilterStream_학습_테스트 { void 필터인_BufferedInputStream를_사용해보자() { final String text = "필터에 연결해보자."; final InputStream inputStream = new ByteArrayInputStream(text.getBytes()); - final InputStream bufferedInputStream = null; + final InputStream bufferedInputStream = new BufferedInputStream(inputStream); - final byte[] actual = new byte[0]; + final byte[] actual; + try (bufferedInputStream){ + actual = bufferedInputStream.readAllBytes(); + } catch (IOException e) { + throw new RuntimeException(); + } assertThat(bufferedInputStream).isInstanceOf(FilterInputStream.class); assertThat(actual).isEqualTo("필터에 연결해보자.".getBytes()); @@ -204,8 +226,18 @@ class InputStreamReader_학습_테스트 { "😋😛😝😜🤪🤨🧐🤓😎🥸🤩", ""); final InputStream inputStream = new ByteArrayInputStream(emoji.getBytes()); + final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); final StringBuilder actual = new StringBuilder(); + try (bufferedReader){ + for(String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()){ + actual.append(s); + actual.append("\r\n"); + } + } catch (IOException e) { + System.out.println(e.getMessage()); + } assertThat(actual).hasToString(emoji); } From 5d15f31225d25e429544ae1fe8f2a3a53270284e Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 16:56:12 +0900 Subject: [PATCH 02/24] =?UTF-8?q?feat(Http11Request):=20HttpRequest=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/request/Http11Request.java | 34 +++++++++++++++++++ .../apache/coyote/http11/request/Method.java | 22 ++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Method.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java new file mode 100644 index 0000000000..eed8256eee --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -0,0 +1,34 @@ +package org.apache.coyote.http11.request; + +public class Http11Request { + + public static final String LINE_SEPARATOR = "\r\n"; + final Method method; + final String uri; + + public Http11Request(final Method method, final String uri) { + this.method = method; + this.uri = uri; + } + + public static Http11Request from(final String request) { + final String[] lines = request.split(LINE_SEPARATOR); + + final String[] requestUri = lines[0].split(" "); + final String method = requestUri[0]; + final String uri = requestUri[1]; + + return new Http11Request( + Method.getMethod(method), + uri + ); + } + + public Method getMethod() { + return method; + } + + public String getUri() { + return uri; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java new file mode 100644 index 0000000000..bb29ed8770 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -0,0 +1,22 @@ +package org.apache.coyote.http11.request; + +import java.util.Arrays; + +public enum Method { + + GET("GET"), + POST("POST"); + + final String name; + + Method(final String name) { + this.name = name; + } + + public static Method getMethod(final String input) { + return Arrays.stream(Method.values()) + .filter(method -> method.name.equals(input)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Invalid Method Request")); + } +} From 722eaadf3c3f5d506075737af53479d7fa3b32b8 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 16:56:33 +0900 Subject: [PATCH 03/24] =?UTF-8?q?feat(Http11Response):=20HttpResponse=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/response/Http11Response.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java new file mode 100644 index 0000000000..3c687267a3 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java @@ -0,0 +1,19 @@ +package org.apache.coyote.http11.response; + +public class Http11Response { + + final String body; + + public Http11Response(final String body) { + this.body = body; + } + + public String getResponse() { + return String.join("\r\n", + "HTTP/1.1 200 OK ", + "Content-Type: text/html;charset=utf-8 ", + "Content-Length: " + body.getBytes().length + " ", + "", + body); + } +} From 8986f2d325181e9aff5ad180f8c1b4790343036e Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 16:57:55 +0900 Subject: [PATCH 04/24] =?UTF-8?q?feat(Http11Processor):=20=EC=9D=B8?= =?UTF-8?q?=EB=8D=B1=EC=8A=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EA=B5=AC=ED=98=84=20(=EB=AF=B8=EC=85=981-1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 7f1b2c7e96..fb6cabbf68 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,17 +1,26 @@ package org.apache.coyote.http11; +import static org.apache.coyote.http11.request.Method.GET; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.Socket; +import java.net.URL; +import java.nio.file.Files; import nextstep.jwp.exception.UncheckedServletException; import org.apache.coyote.Processor; +import org.apache.coyote.http11.request.Http11Request; +import org.apache.coyote.http11.response.Http11Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.net.Socket; - public class Http11Processor implements Runnable, Processor { + public static final String LINE_SEPARATOR = "\r\n"; private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); - private final Socket connection; public Http11Processor(final Socket connection) { @@ -29,19 +38,45 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final var responseBody = "Hello world!"; - - final var response = String.join("\r\n", - "HTTP/1.1 200 OK ", - "Content-Type: text/html;charset=utf-8 ", - "Content-Length: " + responseBody.getBytes().length + " ", - "", - responseBody); + final Http11Request request = Http11Request.from(readInputStream(inputStream)); + final Http11Response response = makeResponseOf(request); - outputStream.write(response.getBytes()); + outputStream.write(response.getResponse().getBytes()); outputStream.flush(); - } catch (IOException | UncheckedServletException e) { + + } catch (final IOException | UncheckedServletException e) { + log.error(e.getMessage(), e); + } + } + + private String readInputStream(final InputStream inputStream) { + final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + + final StringBuilder input = new StringBuilder(); + try (bufferedReader) { + for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) { + input.append(s); + input.append(LINE_SEPARATOR); + } + } catch (final IOException e) { log.error(e.getMessage(), e); } + + return input.toString(); + } + + private Http11Response makeResponseOf(final Http11Request request) throws IOException { + if (request.getMethod() == GET) { + if (request.getUri().equals("/")) { + return new Http11Response("Hello world!"); + } + + final URL resource = getClass().getClassLoader().getResource("static" + request.getUri()); + final String responseBody = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + return new Http11Response(responseBody); + } + + throw new IllegalArgumentException("Invalid Request Uri"); } } From c647bc94c4976ee96bb7ef124203dfdc9d55e9b7 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 18:29:47 +0900 Subject: [PATCH 05/24] =?UTF-8?q?refactor(Http11Processor):=20NPE=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index fb6cabbf68..7c6430793d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -10,6 +10,7 @@ import java.net.Socket; import java.net.URL; import java.nio.file.Files; +import java.nio.file.Path; import nextstep.jwp.exception.UncheckedServletException; import org.apache.coyote.Processor; import org.apache.coyote.http11.request.Http11Request; @@ -54,8 +55,10 @@ private String readInputStream(final InputStream inputStream) { final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); final StringBuilder input = new StringBuilder(); - try (bufferedReader) { - for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) { + try { + for (String s = bufferedReader.readLine(); + !"".equals(s); + s = bufferedReader.readLine()) { input.append(s); input.append(LINE_SEPARATOR); } @@ -66,17 +69,29 @@ private String readInputStream(final InputStream inputStream) { return input.toString(); } - private Http11Response makeResponseOf(final Http11Request request) throws IOException { + private Http11Response makeResponseOf(final Http11Request request) { if (request.getMethod() == GET) { if (request.getUri().equals("/")) { return new Http11Response("Hello world!"); } - final URL resource = getClass().getClassLoader().getResource("static" + request.getUri()); - final String responseBody = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + final String responseBody = getResponseBodyFromResource(request.getUri()); return new Http11Response(responseBody); } throw new IllegalArgumentException("Invalid Request Uri"); } + + private String getResponseBodyFromResource(final String uri) { + final URL resource = getClass().getClassLoader().getResource("static" + uri); + + try { + final Path filePath = new File(resource.getFile()).toPath(); + return new String(Files.readAllBytes(filePath)); + + } catch (final NullPointerException | IOException e) { + log.error(e.getMessage(), e); + return "Resource Not Exist"; + } + } } From e0382851632f9fb912c47fe25cee1cd9c254e58a Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 19:30:11 +0900 Subject: [PATCH 06/24] =?UTF-8?q?feat(Http11*):=20css=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 18 +++++----- .../coyote/http11/request/Http11Request.java | 32 ++++++++++++++--- .../http11/response/Http11Response.java | 36 ++++++++++++++++--- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 7c6430793d..a03d64a957 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -20,7 +20,7 @@ public class Http11Processor implements Runnable, Processor { - public static final String LINE_SEPARATOR = "\r\n"; + private static final String LINE_SEPARATOR = "\r\n"; private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; @@ -40,6 +40,7 @@ public void process(final Socket connection) { final var outputStream = connection.getOutputStream()) { final Http11Request request = Http11Request.from(readInputStream(inputStream)); + final Http11Response response = makeResponseOf(request); outputStream.write(response.getResponse().getBytes()); @@ -71,18 +72,17 @@ private String readInputStream(final InputStream inputStream) { private Http11Response makeResponseOf(final Http11Request request) { if (request.getMethod() == GET) { - if (request.getUri().equals("/")) { - return new Http11Response("Hello world!"); - } - final String responseBody = getResponseBodyFromResource(request.getUri()); - return new Http11Response(responseBody); + return Http11Response.of(request.getHeader("Accept"), responseBody); } - throw new IllegalArgumentException("Invalid Request Uri"); } private String getResponseBodyFromResource(final String uri) { + if (uri.equals("/")) { + return "Hello world!"; + } + final URL resource = getClass().getClassLoader().getResource("static" + uri); try { @@ -90,8 +90,8 @@ private String getResponseBodyFromResource(final String uri) { return new String(Files.readAllBytes(filePath)); } catch (final NullPointerException | IOException e) { - log.error(e.getMessage(), e); - return "Resource Not Exist"; + log.error(e.getMessage() + uri, e); + return "Resource Not Exist: " + uri; } } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index eed8256eee..3add38f543 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -1,26 +1,44 @@ package org.apache.coyote.http11.request; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class Http11Request { - public static final String LINE_SEPARATOR = "\r\n"; + private static final String LINE_SEPARATOR = "\r\n"; final Method method; final String uri; - public Http11Request(final Method method, final String uri) { + final Map headers; + + public Http11Request(final Method method, final String uri, final Map headers) { this.method = method; this.uri = uri; + this.headers = headers; } public static Http11Request from(final String request) { - final String[] lines = request.split(LINE_SEPARATOR); + final List lines = new ArrayList<>(List.of(request.split(LINE_SEPARATOR))); - final String[] requestUri = lines[0].split(" "); + final String[] requestUri = lines.remove(0).split(" "); final String method = requestUri[0]; final String uri = requestUri[1]; + final Map headers = new HashMap<>(); + for (final String line : lines) { + if ("".equals(line)) { + break; + } + final String[] header = line.split(": ", 2); + headers.put(header[0], header[1]); + } + return new Http11Request( Method.getMethod(method), - uri + uri, + headers ); } @@ -31,4 +49,8 @@ public Method getMethod() { public String getUri() { return uri; } + + public String getHeader(final String headerName) { + return headers.get(headerName); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java index 3c687267a3..f171318ae7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java @@ -1,19 +1,47 @@ package org.apache.coyote.http11.response; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Collectors; + public class Http11Response { + private static final String LINE_SEPARATOR = "\r\n"; + final Map headers; final String body; - public Http11Response(final String body) { + public Http11Response(final Map headers, final String body) { + this.headers = headers; this.body = body; } + public static Http11Response of(final String accept, final String body) { + final Map headers = new LinkedHashMap<>(); + + headers.put("Content-Type", "text/html;charset=utf-8 "); + if (accept != null && accept.contains("css")) { + headers.replace("Content-Type", "text/css;charset=utf-8 "); + } + + headers.put("Content-Length", body.getBytes().length + " "); + + return new Http11Response(headers, body); + } + + public String getResponse() { - return String.join("\r\n", + final String header = headers.keySet().stream() + .map(this::formatHeader) + .collect(Collectors.joining(LINE_SEPARATOR)); + + return String.join(LINE_SEPARATOR, "HTTP/1.1 200 OK ", - "Content-Type: text/html;charset=utf-8 ", - "Content-Length: " + body.getBytes().length + " ", + header, "", body); } + + private String formatHeader(final String h) { + return h + ": " + headers.get(h); + } } From fe1459fc878526b736d5cb682fe5a22e9d80f913 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Sun, 3 Sep 2023 20:32:08 +0900 Subject: [PATCH 07/24] =?UTF-8?q?feat(Http11*):=20QueryString=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 37 ++++++++-- .../coyote/http11/request/Http11Request.java | 72 +++++++++++++++---- 2 files changed, 91 insertions(+), 18 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index a03d64a957..2167fe5905 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -11,7 +11,9 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.exception.UncheckedServletException; +import nextstep.jwp.model.User; import org.apache.coyote.Processor; import org.apache.coyote.http11.request.Http11Request; import org.apache.coyote.http11.response.Http11Response; @@ -72,26 +74,49 @@ private String readInputStream(final InputStream inputStream) { private Http11Response makeResponseOf(final Http11Request request) { if (request.getMethod() == GET) { - final String responseBody = getResponseBodyFromResource(request.getUri()); + final String path = request.getPath(); + final String responseBody = getResponseBodyFromResource(path); + + if (path.equals("/login") && request.isQueryParamExist("account", "password")) { + final String account = request.getQueryParam("account"); + final String password = request.getQueryParam("password"); + processQueryString(account, password); + } + return Http11Response.of(request.getHeader("Accept"), responseBody); } throw new IllegalArgumentException("Invalid Request Uri"); } - private String getResponseBodyFromResource(final String uri) { - if (uri.equals("/")) { + private void processQueryString(final String account, final String password) { + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(IllegalArgumentException::new); + + if (user.checkPassword(password)) { + log.info(user.toString()); + } + } + + private String getResponseBodyFromResource(String path) { + if (path.equals("/")) { return "Hello world!"; } + if (path.equals("/favicon.ico")) { + return "Icon Not Exist"; + } + if (!path.contains(".")) { + path += ".html"; + } - final URL resource = getClass().getClassLoader().getResource("static" + uri); + final URL resource = getClass().getClassLoader().getResource("static" + path); try { final Path filePath = new File(resource.getFile()).toPath(); return new String(Files.readAllBytes(filePath)); } catch (final NullPointerException | IOException e) { - log.error(e.getMessage() + uri, e); - return "Resource Not Exist: " + uri; + log.error(e.getMessage() + path, e); + return "Resource Not Exist: " + path; } } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index 3add38f543..0d8e8fdd3c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -9,13 +9,18 @@ public class Http11Request { private static final String LINE_SEPARATOR = "\r\n"; final Method method; - final String uri; - + final String path; + final Map queryParams; final Map headers; - public Http11Request(final Method method, final String uri, final Map headers) { + public Http11Request(final Method method, + final String path, + final Map queryParams, + final Map headers + ) { this.method = method; - this.uri = uri; + this.path = path; + this.queryParams = queryParams; this.headers = headers; } @@ -26,6 +31,42 @@ public static Http11Request from(final String request) { final String method = requestUri[0]; final String uri = requestUri[1]; + final String[] uris = uri.split("\\?"); + final String path = uris[0]; + + String queryString = ""; + if (uris.length > 1) { + queryString = uris[1]; + } + final Map queryParams = parseQueryString(queryString); + final Map headers = parseHeaders(lines); + + return new Http11Request( + Method.getMethod(method), + path, + queryParams, + headers + ); + } + + private static Map parseQueryString(final String queryString) { + final Map queryParams = new HashMap<>(); + + if (!queryString.contains("&")) { + return queryParams; + } + + for (final String query : queryString.split("&")) { + final String[] param = query.split("=", 2); + final String key = param[0]; + final String value = param[1]; + + queryParams.put(key, value); + } + return queryParams; + } + + private static Map parseHeaders(final List lines) { final Map headers = new HashMap<>(); for (final String line : lines) { if ("".equals(line)) { @@ -34,20 +75,27 @@ public static Http11Request from(final String request) { final String[] header = line.split(": ", 2); headers.put(header[0], header[1]); } - - return new Http11Request( - Method.getMethod(method), - uri, - headers - ); + return headers; } public Method getMethod() { return method; } - public String getUri() { - return uri; + public String getPath() { + return path; + } + + public boolean isQueryParamExist(final String... parameterNames) { + boolean isExist = true; + for (final String parameterName : parameterNames) { + isExist = isExist && queryParams.containsKey(parameterName); + } + return isExist; + } + + public String getQueryParam(final String parameterName) { + return queryParams.get(parameterName); } public String getHeader(final String headerName) { From a83ca3e99016a208fc6d721ec19745ec24c0beda Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 01:24:48 +0900 Subject: [PATCH 08/24] =?UTF-8?q?feat(Http11Response):=20Response=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=81=ED=83=9C=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/response/Http11Response.java | 34 +++++++++---------- .../apache/coyote/http11/response/Status.java | 23 +++++++++++++ 2 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/Status.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java index f171318ae7..9bc7448c10 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java @@ -5,42 +5,42 @@ import java.util.stream.Collectors; public class Http11Response { - private static final String LINE_SEPARATOR = "\r\n"; + + final Status status; final Map headers; final String body; - public Http11Response(final Map headers, final String body) { - this.headers = headers; - this.body = body; - } - - public static Http11Response of(final String accept, final String body) { - final Map headers = new LinkedHashMap<>(); - + public Http11Response(final Status status, final String body) { + this.status = status; + this.headers = new LinkedHashMap<>(); headers.put("Content-Type", "text/html;charset=utf-8 "); - if (accept != null && accept.contains("css")) { - headers.replace("Content-Type", "text/css;charset=utf-8 "); - } - headers.put("Content-Length", body.getBytes().length + " "); - return new Http11Response(headers, body); + this.body = body; } + public void addHeader(final String headerName, final String value) { + headers.put(headerName, value); + } public String getResponse() { - final String header = headers.keySet().stream() + final String formattedStatus = formatStatus(status); + final String formattedHeaders = headers.keySet().stream() .map(this::formatHeader) .collect(Collectors.joining(LINE_SEPARATOR)); return String.join(LINE_SEPARATOR, - "HTTP/1.1 200 OK ", - header, + "HTTP/1.1 " + formattedStatus, + formattedHeaders, "", body); } + private String formatStatus(final Status s) { + return s.getCode() + " " + s.getName() + " "; + } + private String formatHeader(final String h) { return h + ": " + headers.get(h); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java new file mode 100644 index 0000000000..d13aea9489 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java @@ -0,0 +1,23 @@ +package org.apache.coyote.http11.response; + +public enum Status { + OK(200, "OK"), + FOUND(302, "Found"), + UNAUTHORIZED(401, "Unauthorized"); + + final int code; + final String name; + + Status(final int code, final String name) { + this.code = code; + this.name = name; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } +} From 9f0af06ab10c0c01a1a1290c06c26b710dbbdf55 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 01:26:12 +0900 Subject: [PATCH 09/24] =?UTF-8?q?feat(Http11Processor):=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=97=AC=EB=B6=80=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 2167fe5905..d2e00f39bd 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,6 +1,9 @@ package org.apache.coyote.http11; import static org.apache.coyote.http11.request.Method.GET; +import static org.apache.coyote.http11.response.Status.FOUND; +import static org.apache.coyote.http11.response.Status.OK; +import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; import java.io.BufferedReader; import java.io.File; @@ -17,12 +20,13 @@ import org.apache.coyote.Processor; import org.apache.coyote.http11.request.Http11Request; import org.apache.coyote.http11.response.Http11Response; +import org.apache.coyote.http11.response.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { - private static final String LINE_SEPARATOR = "\r\n"; + private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; @@ -72,38 +76,57 @@ private String readInputStream(final InputStream inputStream) { return input.toString(); } + private Http11Response makeResponseOf(final Http11Request request) { if (request.getMethod() == GET) { final String path = request.getPath(); - final String responseBody = getResponseBodyFromResource(path); + Status status = OK; if (path.equals("/login") && request.isQueryParamExist("account", "password")) { - final String account = request.getQueryParam("account"); - final String password = request.getQueryParam("password"); - processQueryString(account, password); + status = processLogIn(request); + } + + final String responseBody = getResponseBodyFromResource(status, path); + + final Http11Response response = new Http11Response(status, responseBody); + final String accept = request.getHeader("Accept"); + if (accept != null && accept.contains("css")) { + response.addHeader("Content-Type", "text/css;charset=utf-8 "); + } + if (status == FOUND) { + response.addHeader("Location", "/index.html"); } - return Http11Response.of(request.getHeader("Accept"), responseBody); + return response; } throw new IllegalArgumentException("Invalid Request Uri"); } - private void processQueryString(final String account, final String password) { + private Status processLogIn(final Http11Request request) { + final String account = request.getQueryParam("account"); + final String password = request.getQueryParam("password"); + final User user = InMemoryUserRepository.findByAccount(account) .orElseThrow(IllegalArgumentException::new); if (user.checkPassword(password)) { log.info(user.toString()); + return FOUND; } + + return UNAUTHORIZED; } - private String getResponseBodyFromResource(String path) { + private String getResponseBodyFromResource(final Status status, String path) { if (path.equals("/")) { return "Hello world!"; } if (path.equals("/favicon.ico")) { return "Icon Not Exist"; } + if (status.getCode() >= 400) { + path = "/" + status.getCode(); + } if (!path.contains(".")) { path += ".html"; } From d95d07cbc881ddfbbd2dd59bccd882711f61a64f Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 02:36:28 +0900 Subject: [PATCH 10/24] =?UTF-8?q?chore(login.html):=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=9A=94=EC=B2=AD=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/resources/static/login.html | 114 ++++++++++---------- 1 file changed, 59 insertions(+), 55 deletions(-) diff --git a/tomcat/src/main/resources/static/login.html b/tomcat/src/main/resources/static/login.html index f4ed9de875..ff5bdacd5d 100644 --- a/tomcat/src/main/resources/static/login.html +++ b/tomcat/src/main/resources/static/login.html @@ -1,66 +1,70 @@ - - - - - - - 로그인 - - - - -
-
-
-
-
-
-
-

로그인

-
-
-
- - -
-
- - -
-
- -
-
+ + + + + + + 로그인 + + + + +
+
+
+
+
+
+
+

로그인

+
+
+
+ +
- +
+ +
+
+
+
-
+
-
+
+
- - - - + + + + + + From a4f5414b79fba3f05cfb9e1e148314c6f7d8a10c Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 02:37:08 +0900 Subject: [PATCH 11/24] =?UTF-8?q?feat(Http11*):=20POST=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 98 +++++++++++++++---- .../coyote/http11/request/Http11Request.java | 9 ++ .../apache/coyote/http11/response/Status.java | 3 +- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index d2e00f39bd..9e7cca44cc 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,7 +1,9 @@ package org.apache.coyote.http11; import static org.apache.coyote.http11.request.Method.GET; +import static org.apache.coyote.http11.request.Method.POST; import static org.apache.coyote.http11.response.Status.FOUND; +import static org.apache.coyote.http11.response.Status.NOT_FOUND; import static org.apache.coyote.http11.response.Status.OK; import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; @@ -14,11 +16,14 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.exception.UncheckedServletException; import nextstep.jwp.model.User; import org.apache.coyote.Processor; import org.apache.coyote.http11.request.Http11Request; +import org.apache.coyote.http11.request.Method; import org.apache.coyote.http11.response.Http11Response; import org.apache.coyote.http11.response.Status; import org.slf4j.Logger; @@ -45,8 +50,7 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final Http11Request request = Http11Request.from(readInputStream(inputStream)); - + final Http11Request request = readRequest(inputStream); final Http11Response response = makeResponseOf(request); outputStream.write(response.getResponse().getBytes()); @@ -57,10 +61,20 @@ public void process(final Socket connection) { } } - private String readInputStream(final InputStream inputStream) { + private Http11Request readRequest(final InputStream inputStream) { final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + final Http11Request request = readRequestHeader(bufferedReader); + final String contentLength = request.getHeader("Content-Length"); + if (contentLength != null) { + final String requestBody = readRequestBody(bufferedReader, Integer.parseInt(contentLength)); + request.setBody(requestBody); + } + return request; + } + + private Http11Request readRequestHeader(final BufferedReader bufferedReader) { final StringBuilder input = new StringBuilder(); try { for (String s = bufferedReader.readLine(); @@ -73,38 +87,59 @@ private String readInputStream(final InputStream inputStream) { log.error(e.getMessage(), e); } - return input.toString(); + return Http11Request.from(input.toString()); } + private String readRequestBody(final BufferedReader bufferedReader, final int contentLength) { + final char[] buffer = new char[contentLength]; + try { + bufferedReader.read(buffer, 0, contentLength); + } catch (final IOException e) { + throw new RuntimeException(e); + } + return new String(buffer); + } private Http11Response makeResponseOf(final Http11Request request) { - if (request.getMethod() == GET) { - final String path = request.getPath(); - Status status = OK; - - if (path.equals("/login") && request.isQueryParamExist("account", "password")) { - status = processLogIn(request); - } - - final String responseBody = getResponseBodyFromResource(status, path); - - final Http11Response response = new Http11Response(status, responseBody); + final Method method = request.getMethod(); + final String path = request.getPath(); + Status status; + final Http11Response response; + + if (method == GET) { + status = OK; + final String responseBody = getResponseBodyFromResource(OK, path); + response = new Http11Response(status, responseBody); final String accept = request.getHeader("Accept"); if (accept != null && accept.contains("css")) { response.addHeader("Content-Type", "text/css;charset=utf-8 "); } + return response; + } + if (method == POST) { + status = NOT_FOUND; + if (path.equals("/login")) { + status = logIn(request); + } + if (path.equals("/register")) { + status = register(request); + } + + final String responseBody = getResponseBodyFromResource(status, path); + + response = new Http11Response(status, responseBody); if (status == FOUND) { response.addHeader("Location", "/index.html"); } - return response; } throw new IllegalArgumentException("Invalid Request Uri"); } - private Status processLogIn(final Http11Request request) { - final String account = request.getQueryParam("account"); - final String password = request.getQueryParam("password"); + private Status logIn(final Http11Request request) { + final Map bodyFields = parseFormData(request.getBody()); + final String account = bodyFields.get("account"); + final String password = bodyFields.get("password"); final User user = InMemoryUserRepository.findByAccount(account) .orElseThrow(IllegalArgumentException::new); @@ -117,6 +152,31 @@ private Status processLogIn(final Http11Request request) { return UNAUTHORIZED; } + private Status register(final Http11Request request) { + final Map bodyFields = parseFormData(request.getBody()); + + final String account = bodyFields.get("account"); + final String password = bodyFields.get("password"); + final String email = bodyFields.get("email"); + + final User user = new User(account, password, email); + + InMemoryUserRepository.save(user); + return FOUND; + } + + private Map parseFormData(final String body) { + final Map fields = new HashMap<>(); + + for (final String field : body.split("&")) { + final String[] param = field.split("=", 2); + final String name = param[0]; + final String value = param[1]; + fields.put(name, value); + } + return fields; + } + private String getResponseBodyFromResource(final Status status, String path) { if (path.equals("/")) { return "Hello world!"; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index 0d8e8fdd3c..c42420c4ca 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -12,6 +12,7 @@ public class Http11Request { final String path; final Map queryParams; final Map headers; + String body; public Http11Request(final Method method, final String path, @@ -101,4 +102,12 @@ public String getQueryParam(final String parameterName) { public String getHeader(final String headerName) { return headers.get(headerName); } + + public String getBody() { + return body; + } + + public void setBody(final String body) { + this.body = body; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java index d13aea9489..6389be4e9f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java @@ -3,7 +3,8 @@ public enum Status { OK(200, "OK"), FOUND(302, "Found"), - UNAUTHORIZED(401, "Unauthorized"); + UNAUTHORIZED(401, "Unauthorized"), + NOT_FOUND(404, "Not Found"); final int code; final String name; From 54dbe206a10f96cfbc43f5c040bc205acddef711 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 03:05:06 +0900 Subject: [PATCH 12/24] =?UTF-8?q?feat(Http11*):=20Cookie=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 5 ++++ .../coyote/http11/request/Http11Request.java | 25 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 9e7cca44cc..679430c58e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -18,6 +18,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.UUID; import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.exception.UncheckedServletException; import nextstep.jwp.model.User; @@ -130,6 +131,10 @@ private Http11Response makeResponseOf(final Http11Request request) { response = new Http11Response(status, responseBody); if (status == FOUND) { response.addHeader("Location", "/index.html"); + if (!request.isCookieExist("JSESSIONID")) { + final UUID uuid = UUID.randomUUID(); + response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); + } } return response; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index c42420c4ca..fe1e817e12 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -12,17 +12,20 @@ public class Http11Request { final String path; final Map queryParams; final Map headers; + final Map cookies; String body; public Http11Request(final Method method, final String path, final Map queryParams, - final Map headers + final Map headers, + final Map cookies ) { this.method = method; this.path = path; this.queryParams = queryParams; this.headers = headers; + this.cookies = cookies; } public static Http11Request from(final String request) { @@ -42,11 +45,15 @@ public static Http11Request from(final String request) { final Map queryParams = parseQueryString(queryString); final Map headers = parseHeaders(lines); + final String cookieFields = headers.remove("Cookie"); + final Map cookies = parseCookies(cookieFields); + return new Http11Request( Method.getMethod(method), path, queryParams, - headers + headers, + cookies ); } @@ -79,6 +86,16 @@ private static Map parseHeaders(final List lines) { return headers; } + private static Map parseCookies(final String cookieFields) { + final Map cookies = new HashMap<>(); + + for (final String field : cookieFields.split("; ")) { + final String[] cookie = field.split("=", 2); + cookies.put(cookie[0], cookie[1]); + } + return cookies; + } + public Method getMethod() { return method; } @@ -103,6 +120,10 @@ public String getHeader(final String headerName) { return headers.get(headerName); } + public boolean isCookieExist(final String cookieName) { + return cookies.containsKey(cookieName); + } + public String getBody() { return body; } From 63ce5fe3114a10fa3220b954bba8cf42bd1c2e7f Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 03:56:28 +0900 Subject: [PATCH 13/24] =?UTF-8?q?feat(Http11*):=20Session=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 64 ++++++++++++------- .../org/apache/coyote/http11/Session.java | 30 +++++++++ .../apache/coyote/http11/SessionManager.java | 24 +++++++ .../coyote/http11/request/Http11Request.java | 7 ++ 4 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/Session.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 679430c58e..8a0b3acf27 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -3,7 +3,6 @@ import static org.apache.coyote.http11.request.Method.GET; import static org.apache.coyote.http11.request.Method.POST; import static org.apache.coyote.http11.response.Status.FOUND; -import static org.apache.coyote.http11.response.Status.NOT_FOUND; import static org.apache.coyote.http11.response.Status.OK; import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; @@ -31,8 +30,8 @@ import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { + public static final String SESSION_COOKIE_NAME = "JSESSIONID"; private static final String LINE_SEPARATOR = "\r\n"; - private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; @@ -104,11 +103,16 @@ private String readRequestBody(final BufferedReader bufferedReader, final int co private Http11Response makeResponseOf(final Http11Request request) { final Method method = request.getMethod(); final String path = request.getPath(); - Status status; + final Status status; final Http11Response response; if (method == GET) { status = OK; + if (path.equals("/login") && request.isCookieExist(SESSION_COOKIE_NAME)) { + + return makeAuthResponse(FOUND, request, request.getCookie(SESSION_COOKIE_NAME)); + } + final String responseBody = getResponseBodyFromResource(OK, path); response = new Http11Response(status, responseBody); final String accept = request.getHeader("Accept"); @@ -118,46 +122,54 @@ private Http11Response makeResponseOf(final Http11Request request) { return response; } if (method == POST) { - status = NOT_FOUND; if (path.equals("/login")) { - status = logIn(request); + return logIn(request); } if (path.equals("/register")) { - status = register(request); + return register(request); } - - final String responseBody = getResponseBodyFromResource(status, path); - - response = new Http11Response(status, responseBody); - if (status == FOUND) { - response.addHeader("Location", "/index.html"); - if (!request.isCookieExist("JSESSIONID")) { - final UUID uuid = UUID.randomUUID(); - response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); - } - } - return response; } throw new IllegalArgumentException("Invalid Request Uri"); } - private Status logIn(final Http11Request request) { + private Http11Response logIn(final Http11Request request) { final Map bodyFields = parseFormData(request.getBody()); final String account = bodyFields.get("account"); final String password = bodyFields.get("password"); + // TODO: 유저가 존재하지 않는 경우 예외 처리 final User user = InMemoryUserRepository.findByAccount(account) .orElseThrow(IllegalArgumentException::new); + Status status = UNAUTHORIZED; + String id = null; if (user.checkPassword(password)) { log.info(user.toString()); - return FOUND; + + id = UUID.randomUUID().toString(); + final Session session = new Session(id); + session.setAttribute("user", user); + SessionManager.add(session); + status = FOUND; } - return UNAUTHORIZED; + return makeAuthResponse(status, request, id); + } + + private Http11Response makeAuthResponse(final Status status, final Http11Request request, final String uuid) { + final String responseBody = getResponseBodyFromResource(status, request.getPath()); + final Http11Response response = new Http11Response(status, responseBody); + + if (status == FOUND) { + response.addHeader("Location", "/index.html"); + if (!request.isCookieExist(SESSION_COOKIE_NAME)) { + response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); + } + } + return response; } - private Status register(final Http11Request request) { + private Http11Response register(final Http11Request request) { final Map bodyFields = parseFormData(request.getBody()); final String account = bodyFields.get("account"); @@ -167,7 +179,13 @@ private Status register(final Http11Request request) { final User user = new User(account, password, email); InMemoryUserRepository.save(user); - return FOUND; + + final String id = UUID.randomUUID().toString(); + final Session session = new Session(id); + session.setAttribute("user", user); + SessionManager.add(session); + + return makeAuthResponse(FOUND, request, id); } private Map parseFormData(final String body) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/Session.java new file mode 100644 index 0000000000..8da0297c80 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/Session.java @@ -0,0 +1,30 @@ +package org.apache.coyote.http11; + +import java.util.HashMap; +import java.util.Map; + +public class Session { + + private final String id; + private final Map values = new HashMap<>(); + + public Session(final String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public Object getAttribute(final String name) { + return values.get(name); + } + + public void setAttribute(final String name, final Object value) { + values.put(name, value); + } + + public void removeAttribute(final String name) { + values.remove(name); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java new file mode 100644 index 0000000000..a4b368f463 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java @@ -0,0 +1,24 @@ +package org.apache.coyote.http11; + +import java.util.HashMap; +import java.util.Map; + +public class SessionManager { + + private static final Map SESSIONS = new HashMap<>(); + + private SessionManager() { + } + + public static void add(final Session session) { + SESSIONS.put(session.getId(), session); + } + + public static Session findSession(final String id) { + return SESSIONS.get(id); + } + + public static void remove(final String id) { + SESSIONS.remove(id); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index fe1e817e12..41449fda96 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -88,6 +88,9 @@ private static Map parseHeaders(final List lines) { private static Map parseCookies(final String cookieFields) { final Map cookies = new HashMap<>(); + if (cookieFields == null) { + return cookies; + } for (final String field : cookieFields.split("; ")) { final String[] cookie = field.split("=", 2); @@ -124,6 +127,10 @@ public boolean isCookieExist(final String cookieName) { return cookies.containsKey(cookieName); } + public String getCookie(final String cookieName) { + return cookies.get(cookieName); + } + public String getBody() { return body; } From c840b3e6a97e101b4678bbdf2b44f3ea4d59590c Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 16:24:44 +0900 Subject: [PATCH 14/24] =?UTF-8?q?refactor(all):=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/jwp/service/UserService.java | 57 ++++++ .../apache/coyote/http11/Http11Processor.java | 188 ++++++++---------- .../exception/PageNotFoundException.java | 9 + .../exception/UnauthorizedException.java | 9 + .../coyote/http11/request/Http11Request.java | 23 +-- .../apache/coyote/http11/request/Method.java | 1 - .../http11/response/Http11Response.java | 44 +++- .../apache/coyote/http11/response/Status.java | 3 +- .../apache/coyote/http11/utils/Parser.java | 25 +++ 9 files changed, 223 insertions(+), 136 deletions(-) create mode 100644 tomcat/src/main/java/nextstep/jwp/service/UserService.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/exception/PageNotFoundException.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/exception/UnauthorizedException.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/utils/Parser.java diff --git a/tomcat/src/main/java/nextstep/jwp/service/UserService.java b/tomcat/src/main/java/nextstep/jwp/service/UserService.java new file mode 100644 index 0000000000..5517bc22f7 --- /dev/null +++ b/tomcat/src/main/java/nextstep/jwp/service/UserService.java @@ -0,0 +1,57 @@ +package nextstep.jwp.service; + +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import nextstep.jwp.db.InMemoryUserRepository; +import nextstep.jwp.model.User; +import org.apache.coyote.http11.Session; +import org.apache.coyote.http11.SessionManager; +import org.apache.coyote.http11.exception.UnauthorizedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UserService { + private static final Logger log = LoggerFactory.getLogger(UserService.class); + + public String logIn(final Map requestBody) { + final String account = requestBody.get("account"); + final String password = requestBody.get("password"); + + final Optional user = InMemoryUserRepository.findByAccount(account); + + if (user.isEmpty()) { + throw new UnauthorizedException(account); + } + if (!user.get().checkPassword(password)) { + throw new UnauthorizedException(account); + } + log.info(user.toString()); + + return setSessionWithUUID(user.get()); + } + + private String setSessionWithUUID(final User user) { + final String id = UUID.randomUUID().toString(); + final Session session = new Session(id); + session.setAttribute("user", user); + SessionManager.add(session); + return id; + } + + public String register(final Map requestBody) { + final String account = requestBody.get("account"); + final String password = requestBody.get("password"); + final String email = requestBody.get("email"); + + if (InMemoryUserRepository.findByAccount(account).isPresent()) { + throw new UnauthorizedException(account); + } + + final User user = new User(account, password, email); + InMemoryUserRepository.save(user); + + return setSessionWithUUID(user); + } + +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 8a0b3acf27..8dd382cbf5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -3,25 +3,24 @@ import static org.apache.coyote.http11.request.Method.GET; import static org.apache.coyote.http11.request.Method.POST; import static org.apache.coyote.http11.response.Status.FOUND; +import static org.apache.coyote.http11.response.Status.INTERNAL_SERVER_ERROR; +import static org.apache.coyote.http11.response.Status.NOT_FOUND; import static org.apache.coyote.http11.response.Status.OK; import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; +import static org.apache.coyote.http11.utils.Parser.parseFormData; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; import java.util.Map; -import java.util.UUID; -import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.exception.UncheckedServletException; -import nextstep.jwp.model.User; +import nextstep.jwp.service.UserService; import org.apache.coyote.Processor; +import org.apache.coyote.http11.exception.PageNotFoundException; +import org.apache.coyote.http11.exception.UnauthorizedException; import org.apache.coyote.http11.request.Http11Request; import org.apache.coyote.http11.request.Method; import org.apache.coyote.http11.response.Http11Response; @@ -30,10 +29,12 @@ import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { - public static final String SESSION_COOKIE_NAME = "JSESSIONID"; + private static final String SESSION_COOKIE_NAME = "JSESSIONID"; private static final String LINE_SEPARATOR = "\r\n"; private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); + private final Socket connection; + private final UserService userService = new UserService(); public Http11Processor(final Socket connection) { this.connection = connection; @@ -51,7 +52,7 @@ public void process(final Socket connection) { final var outputStream = connection.getOutputStream()) { final Http11Request request = readRequest(inputStream); - final Http11Response response = makeResponseOf(request); + final Http11Response response = handleRequest(request); outputStream.write(response.getResponse().getBytes()); outputStream.flush(); @@ -100,129 +101,104 @@ private String readRequestBody(final BufferedReader bufferedReader, final int co return new String(buffer); } - private Http11Response makeResponseOf(final Http11Request request) { - final Method method = request.getMethod(); - final String path = request.getPath(); - final Status status; - final Http11Response response; + private Http11Response handleRequest(final Http11Request request) { + try { + return handleRequestWithMethod(request); + } catch (final PageNotFoundException e) { + log.error(e.getMessage()); + return handleResponseWithException(NOT_FOUND); + } catch (final UnauthorizedException e) { + log.error(e.getMessage()); + return handleResponseWithException(UNAUTHORIZED); + } catch (final Exception e) { + log.error(e.getMessage()); + return handleResponseWithException(INTERNAL_SERVER_ERROR); + } + } + private Http11Response handleRequestWithMethod(final Http11Request request) { + final Method method = request.getMethod(); if (method == GET) { - status = OK; - if (path.equals("/login") && request.isCookieExist(SESSION_COOKIE_NAME)) { - - return makeAuthResponse(FOUND, request, request.getCookie(SESSION_COOKIE_NAME)); - } - - final String responseBody = getResponseBodyFromResource(OK, path); - response = new Http11Response(status, responseBody); - final String accept = request.getHeader("Accept"); - if (accept != null && accept.contains("css")) { - response.addHeader("Content-Type", "text/css;charset=utf-8 "); - } - return response; + return handleGetRequest(request); } if (method == POST) { - if (path.equals("/login")) { - return logIn(request); - } - if (path.equals("/register")) { - return register(request); - } + return handlePostRequest(request); } - throw new IllegalArgumentException("Invalid Request Uri"); + throw new PageNotFoundException(request.getPath()); } - private Http11Response logIn(final Http11Request request) { - final Map bodyFields = parseFormData(request.getBody()); - final String account = bodyFields.get("account"); - final String password = bodyFields.get("password"); - - // TODO: 유저가 존재하지 않는 경우 예외 처리 - final User user = InMemoryUserRepository.findByAccount(account) - .orElseThrow(IllegalArgumentException::new); + private Http11Response handleGetRequest(final Http11Request request) { + final String path = request.getPath(); + if (path.equals("/")) { + return new Http11Response(OK, "Hello world!"); + } + if (path.equals("/favicon.ico")) { + return new Http11Response(OK, "Icon Not Exist!"); + } + if (path.equals("/login") && request.isCookieExist(SESSION_COOKIE_NAME)) { + return handleAuthResponse(request, request.getCookie(SESSION_COOKIE_NAME)); + } - Status status = UNAUTHORIZED; - String id = null; - if (user.checkPassword(password)) { - log.info(user.toString()); + try { + final URL resource = convertPathToUrl(path); + final Http11Response response = new Http11Response(OK, resource); + checkContentType(request, response); + return response; - id = UUID.randomUUID().toString(); - final Session session = new Session(id); - session.setAttribute("user", user); - SessionManager.add(session); - status = FOUND; + } catch (final Exception e) { + throw new PageNotFoundException(path); } - - return makeAuthResponse(status, request, id); } - private Http11Response makeAuthResponse(final Status status, final Http11Request request, final String uuid) { - final String responseBody = getResponseBodyFromResource(status, request.getPath()); - final Http11Response response = new Http11Response(status, responseBody); + private Http11Response handleAuthResponse(final Http11Request request, final String uuid) { + final Http11Response response = new Http11Response(FOUND); - if (status == FOUND) { - response.addHeader("Location", "/index.html"); - if (!request.isCookieExist(SESSION_COOKIE_NAME)) { - response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); - } + response.addHeader("Location", "/index.html"); + if (!request.isCookieExist(SESSION_COOKIE_NAME)) { + response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); } return response; } - private Http11Response register(final Http11Request request) { - final Map bodyFields = parseFormData(request.getBody()); - - final String account = bodyFields.get("account"); - final String password = bodyFields.get("password"); - final String email = bodyFields.get("email"); - - final User user = new User(account, password, email); - - InMemoryUserRepository.save(user); - - final String id = UUID.randomUUID().toString(); - final Session session = new Session(id); - session.setAttribute("user", user); - SessionManager.add(session); - - return makeAuthResponse(FOUND, request, id); + private URL convertPathToUrl(String path) { + if (!path.contains(".")) { + path += ".html"; + } + return getClass().getClassLoader().getResource("static" + path); } - private Map parseFormData(final String body) { - final Map fields = new HashMap<>(); - - for (final String field : body.split("&")) { - final String[] param = field.split("=", 2); - final String name = param[0]; - final String value = param[1]; - fields.put(name, value); + private void checkContentType(final Http11Request request, final Http11Response response) { + final String accept = request.getHeader("Accept"); + if (accept != null && accept.contains("css")) { + response.addHeader("Content-Type", "text/css;charset=utf-8 "); } - return fields; } - private String getResponseBodyFromResource(final Status status, String path) { - if (path.equals("/")) { - return "Hello world!"; - } - if (path.equals("/favicon.ico")) { - return "Icon Not Exist"; + private Http11Response handlePostRequest(final Http11Request request) throws UnauthorizedException { + final String path = request.getPath(); + if (path.equals("/login")) { + return logIn(request); } - if (status.getCode() >= 400) { - path = "/" + status.getCode(); - } - if (!path.contains(".")) { - path += ".html"; + if (path.equals("/register")) { + return register(request); } + throw new PageNotFoundException(request.getPath()); + } - final URL resource = getClass().getClassLoader().getResource("static" + path); + private Http11Response logIn(final Http11Request request) throws UnauthorizedException { + final Map bodyFields = parseFormData(request.getBody()); + final String uuid = userService.logIn(bodyFields); + return handleAuthResponse(request, uuid); + } - try { - final Path filePath = new File(resource.getFile()).toPath(); - return new String(Files.readAllBytes(filePath)); + private Http11Response register(final Http11Request request) { + final Map bodyFields = parseFormData(request.getBody()); + final String uuid = userService.register(bodyFields); + return handleAuthResponse(request, uuid); + } - } catch (final NullPointerException | IOException e) { - log.error(e.getMessage() + path, e); - return "Resource Not Exist: " + path; - } + private Http11Response handleResponseWithException(final Status status) { + final URL resource = convertPathToUrl("/" + status.getCode()); + return new Http11Response(status, resource); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/exception/PageNotFoundException.java b/tomcat/src/main/java/org/apache/coyote/http11/exception/PageNotFoundException.java new file mode 100644 index 0000000000..5be57e0d11 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/exception/PageNotFoundException.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.exception; + +public class PageNotFoundException extends RuntimeException { + private final String message; + + public PageNotFoundException(final String path) { + this.message = "요청하신 페이지를 찾을 수 없습니다 :" + path; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/exception/UnauthorizedException.java b/tomcat/src/main/java/org/apache/coyote/http11/exception/UnauthorizedException.java new file mode 100644 index 0000000000..c6168de996 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/exception/UnauthorizedException.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.exception; + +public class UnauthorizedException extends RuntimeException { + private final String message; + + public UnauthorizedException(final String account) { + this.message = "인증에 실패하였습니다 :" + account; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java index 41449fda96..6ccef4464d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java @@ -1,13 +1,15 @@ package org.apache.coyote.http11.request; +import static org.apache.coyote.http11.utils.Parser.parseFormData; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Http11Request { - private static final String LINE_SEPARATOR = "\r\n"; + final Method method; final String path; final Map queryParams; @@ -42,7 +44,7 @@ public static Http11Request from(final String request) { if (uris.length > 1) { queryString = uris[1]; } - final Map queryParams = parseQueryString(queryString); + final Map queryParams = parseFormData(queryString); final Map headers = parseHeaders(lines); final String cookieFields = headers.remove("Cookie"); @@ -57,23 +59,6 @@ public static Http11Request from(final String request) { ); } - private static Map parseQueryString(final String queryString) { - final Map queryParams = new HashMap<>(); - - if (!queryString.contains("&")) { - return queryParams; - } - - for (final String query : queryString.split("&")) { - final String[] param = query.split("=", 2); - final String key = param[0]; - final String value = param[1]; - - queryParams.put(key, value); - } - return queryParams; - } - private static Map parseHeaders(final List lines) { final Map headers = new HashMap<>(); for (final String line : lines) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index bb29ed8770..b680c2ee49 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -3,7 +3,6 @@ import java.util.Arrays; public enum Method { - GET("GET"), POST("POST"); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java index 9bc7448c10..bfa2675ed1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java @@ -1,8 +1,14 @@ package org.apache.coyote.http11.response; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; +import org.apache.coyote.http11.exception.PageNotFoundException; public class Http11Response { private static final String LINE_SEPARATOR = "\r\n"; @@ -15,15 +21,43 @@ public Http11Response(final Status status, final String body) { this.status = status; this.headers = new LinkedHashMap<>(); headers.put("Content-Type", "text/html;charset=utf-8 "); - headers.put("Content-Length", body.getBytes().length + " "); this.body = body; + if (body.length() > 0) { + headers.put("Content-Length", body.getBytes().length + " "); + } + } + + public Http11Response(final Status status) { + this(status, ""); + } + + public Http11Response(final Status status, final URL resource) { + this(status, readResponseBody(resource)); + } + + private static String readResponseBody(final URL resource) { + try { + final Path filePath = new File(resource.getFile()).toPath(); + return new String(Files.readAllBytes(filePath)); + + } catch (final NullPointerException | IOException e) { + throw new PageNotFoundException(resource.toString()); + } } public void addHeader(final String headerName, final String value) { headers.put(headerName, value); } + private String formatStatus(final Status s) { + return s.getCode() + " " + s.getName() + " "; + } + + private String formatHeader(final String h) { + return h + ": " + headers.get(h); + } + public String getResponse() { final String formattedStatus = formatStatus(status); final String formattedHeaders = headers.keySet().stream() @@ -36,12 +70,4 @@ public String getResponse() { "", body); } - - private String formatStatus(final Status s) { - return s.getCode() + " " + s.getName() + " "; - } - - private String formatHeader(final String h) { - return h + ": " + headers.get(h); - } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java index 6389be4e9f..4764d87efe 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java @@ -4,7 +4,8 @@ public enum Status { OK(200, "OK"), FOUND(302, "Found"), UNAUTHORIZED(401, "Unauthorized"), - NOT_FOUND(404, "Not Found"); + NOT_FOUND(404, "Not Found"), + INTERNAL_SERVER_ERROR(500, "Internal Server Error"); final int code; final String name; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/utils/Parser.java b/tomcat/src/main/java/org/apache/coyote/http11/utils/Parser.java new file mode 100644 index 0000000000..131a6dd69e --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/utils/Parser.java @@ -0,0 +1,25 @@ +package org.apache.coyote.http11.utils; + +import java.util.HashMap; +import java.util.Map; + +public class Parser { + + private Parser() { + } + + public static Map parseFormData(final String formData) { + final Map fields = new HashMap<>(); + if (!formData.contains("&")) { + return fields; + } + + for (final String field : formData.split("&")) { + final String[] param = field.split("=", 2); + final String name = param[0]; + final String value = param[1]; + fields.put(name, value); + } + return fields; + } +} From 6fdde09dd0ae4acad252989d84c895d636cb8e1a Mon Sep 17 00:00:00 2001 From: LJW25 Date: Mon, 4 Sep 2023 17:46:33 +0900 Subject: [PATCH 15/24] =?UTF-8?q?test(Http11Processor):=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/Http11ProcessorTest.java | 182 +++++++++++++++++- 1 file changed, 173 insertions(+), 9 deletions(-) diff --git a/tomcat/src/test/java/nextstep/org/apache/coyote/http11/Http11ProcessorTest.java b/tomcat/src/test/java/nextstep/org/apache/coyote/http11/Http11ProcessorTest.java index 512b919f09..47eec9f69f 100644 --- a/tomcat/src/test/java/nextstep/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/nextstep/org/apache/coyote/http11/Http11ProcessorTest.java @@ -1,15 +1,16 @@ package nextstep.org.apache.coyote.http11; -import support.StubSocket; -import org.apache.coyote.http11.Http11Processor; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.file.Files; - -import static org.assertj.core.api.Assertions.assertThat; +import org.apache.coyote.http11.Http11Processor; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import support.StubSocket; class Http11ProcessorTest { @@ -23,7 +24,7 @@ void process() { processor.process(socket); // then - var expected = String.join("\r\n", + final var expected = String.join("\r\n", "HTTP/1.1 200 OK ", "Content-Type: text/html;charset=utf-8 ", "Content-Length: 12 ", @@ -36,7 +37,7 @@ void process() { @Test void index() throws IOException { // given - final String httpRequest= String.join("\r\n", + final String httpRequest = String.join("\r\n", "GET /index.html HTTP/1.1 ", "Host: localhost:8080 ", "Connection: keep-alive ", @@ -51,12 +52,175 @@ void index() throws IOException { // then final URL resource = getClass().getClassLoader().getResource("static/index.html"); - var expected = "HTTP/1.1 200 OK \r\n" + + final var expected = "HTTP/1.1 200 OK \r\n" + "Content-Type: text/html;charset=utf-8 \r\n" + "Content-Length: 5564 \r\n" + - "\r\n"+ + "\r\n" + new String(Files.readAllBytes(new File(resource.getFile()).toPath())); assertThat(socket.output()).isEqualTo(expected); } + + @DisplayName("css 요청이 들어오면 css 타입으로 응답한다.") + @Test + void css() { + // given + final String httpRequest = String.join("\r\n", + "GET /css/styles.css HTTP/1.1 ", + "Accept: text/css,*/*;q=0.1 ", + "", + ""); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + assertThat(socket.output()).contains("text/css;"); + } + + @DisplayName("login 페이지를 조회한다.") + @Test + void login() throws IOException { + // given + final String httpRequest = String.join("\r\n", + "GET /login HTTP/1.1 ", + "Host: localhost:8080 ", + "Connection: keep-alive ", + "", + ""); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + final URL resource = getClass().getClassLoader().getResource("static/login.html"); + final byte[] body = Files.readAllBytes(new File(resource.getFile()).toPath()); + final var expected = "HTTP/1.1 200 OK \r\n" + + "Content-Type: text/html;charset=utf-8 \r\n" + + "Content-Length: " + body.length + " \r\n" + + "\r\n" + + new String(body); + + assertThat(socket.output()).isEqualTo(expected); + } + + @DisplayName("로그인에 성공할 시 Cookie와 리다이렉트 Location을 응답 헤더에 추가한다.") + @Test + void post_Login_Success() { + // given + final String requestBody = "account=gugu&password=password"; + final String httpRequest = String.join("\r\n", + "POST /login HTTP/1.1 ", + "Host: localhost:8080 ", + "Connection: keep-alive ", + "Content-Length: " + requestBody.getBytes().length, + "", + requestBody); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + assertSoftly(softly -> { + assertThat(socket.output()).contains("HTTP/1.1 302 Found"); + assertThat(socket.output()).contains("JSESSIONID"); + assertThat(socket.output()).contains("Location: /index.html"); + }); + } + + @DisplayName("로그인에 실패하면 401 에러 페이지를 응답한다.") + @Test + void post_Login_Unauthorized() throws IOException { + // given + final String requestBody = "account=zeeto&password=zeeto"; + final String httpRequest = String.join("\r\n", + "POST /login HTTP/1.1 ", + "Host: localhost:8080 ", + "Connection: keep-alive ", + "Content-Length: " + requestBody.getBytes().length, + "", + requestBody); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + final URL resource = getClass().getClassLoader().getResource("static/401.html"); + final byte[] body = Files.readAllBytes(new File(resource.getFile()).toPath()); + final var expected = "HTTP/1.1 401 Unauthorized \r\n" + + "Content-Type: text/html;charset=utf-8 \r\n" + + "Content-Length: " + body.length + " \r\n" + + "\r\n" + + new String(body); + + assertThat(socket.output()).isEqualTo(expected); + } + + @DisplayName("register 페이지를 조회한다.") + @Test + void register() throws IOException { + // given + final String httpRequest = String.join("\r\n", + "GET /register HTTP/1.1 ", + "Host: localhost:8080 ", + "Connection: keep-alive ", + "", + ""); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + final URL resource = getClass().getClassLoader().getResource("static/register.html"); + final byte[] body = Files.readAllBytes(new File(resource.getFile()).toPath()); + final var expected = "HTTP/1.1 200 OK \r\n" + + "Content-Type: text/html;charset=utf-8 \r\n" + + "Content-Length: " + body.length + " \r\n" + + "\r\n" + + new String(body); + + assertThat(socket.output()).isEqualTo(expected); + } + + @DisplayName("회원가입에 성공할 시 Cookie와 리다이렉트 Location을 응답 헤더에 추가한다.") + @Test + void post_Register_Success() { + // given + final String requestBody = "account=io&password=password&email=hkkang%40woowahan.com"; + final String httpRequest = String.join("\r\n", + "POST /register HTTP/1.1 ", + "Host: localhost:8080 ", + "Connection: keep-alive ", + "Content-Length: " + requestBody.getBytes().length, + "", + requestBody); + + final var socket = new StubSocket(httpRequest); + final Http11Processor processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + assertSoftly(softly -> { + assertThat(socket.output()).contains("HTTP/1.1 302 Found"); + assertThat(socket.output()).contains("JSESSIONID"); + assertThat(socket.output()).contains("Location: /index.html"); + }); + } } From 40c75a8b12c2fa027540e323b4176edfa8e48bb8 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 18:23:08 +0900 Subject: [PATCH 16/24] =?UTF-8?q?refactor(Http11*):=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=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 --- .../apache/coyote/http11/Http11Processor.java | 5 ++--- .../coyote/http11/response/Http11Response.java | 16 ++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 8dd382cbf5..70cac4594b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -81,8 +81,8 @@ private Http11Request readRequestHeader(final BufferedReader bufferedReader) { for (String s = bufferedReader.readLine(); !"".equals(s); s = bufferedReader.readLine()) { - input.append(s); - input.append(LINE_SEPARATOR); + input.append(s) + .append(LINE_SEPARATOR); } } catch (final IOException e) { log.error(e.getMessage(), e); @@ -144,7 +144,6 @@ private Http11Response handleGetRequest(final Http11Request request) { final Http11Response response = new Http11Response(OK, resource); checkContentType(request, response); return response; - } catch (final Exception e) { throw new PageNotFoundException(path); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java index bfa2675ed1..47b23744cd 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java @@ -50,14 +50,6 @@ public void addHeader(final String headerName, final String value) { headers.put(headerName, value); } - private String formatStatus(final Status s) { - return s.getCode() + " " + s.getName() + " "; - } - - private String formatHeader(final String h) { - return h + ": " + headers.get(h); - } - public String getResponse() { final String formattedStatus = formatStatus(status); final String formattedHeaders = headers.keySet().stream() @@ -70,4 +62,12 @@ public String getResponse() { "", body); } + + private String formatStatus(final Status status) { + return status.getCode() + " " + status.getName() + " "; + } + + private String formatHeader(final String header) { + return header + ": " + headers.get(header); + } } From e3c9eced63beb0bf7812370da67e7ab09f8bc0d6 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 23:17:22 +0900 Subject: [PATCH 17/24] =?UTF-8?q?refactor(UserService):=20Optional=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/jwp/service/UserService.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tomcat/src/main/java/nextstep/jwp/service/UserService.java b/tomcat/src/main/java/nextstep/jwp/service/UserService.java index 5517bc22f7..8d32951f6e 100644 --- a/tomcat/src/main/java/nextstep/jwp/service/UserService.java +++ b/tomcat/src/main/java/nextstep/jwp/service/UserService.java @@ -1,7 +1,6 @@ package nextstep.jwp.service; import java.util.Map; -import java.util.Optional; import java.util.UUID; import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.model.User; @@ -18,17 +17,15 @@ public String logIn(final Map requestBody) { final String account = requestBody.get("account"); final String password = requestBody.get("password"); - final Optional user = InMemoryUserRepository.findByAccount(account); + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(() -> new UnauthorizedException(account)); - if (user.isEmpty()) { - throw new UnauthorizedException(account); - } - if (!user.get().checkPassword(password)) { + if (!user.checkPassword(password)) { throw new UnauthorizedException(account); } log.info(user.toString()); - return setSessionWithUUID(user.get()); + return setSessionWithUUID(user); } private String setSessionWithUUID(final User user) { @@ -44,9 +41,10 @@ public String register(final Map requestBody) { final String password = requestBody.get("password"); final String email = requestBody.get("email"); - if (InMemoryUserRepository.findByAccount(account).isPresent()) { - throw new UnauthorizedException(account); - } + InMemoryUserRepository.findByAccount(account) + .ifPresent(ignored -> { + throw new UnauthorizedException(account); + }); final User user = new User(account, password, email); InMemoryUserRepository.save(user); From a35bb6fd02832dbe5a6b2f471d3671c14dd7a15c Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 23:19:05 +0900 Subject: [PATCH 18/24] =?UTF-8?q?refactor(UserService):=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/java/nextstep/jwp/service/UserService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/nextstep/jwp/service/UserService.java b/tomcat/src/main/java/nextstep/jwp/service/UserService.java index 8d32951f6e..8f7215df62 100644 --- a/tomcat/src/main/java/nextstep/jwp/service/UserService.java +++ b/tomcat/src/main/java/nextstep/jwp/service/UserService.java @@ -25,10 +25,10 @@ public String logIn(final Map requestBody) { } log.info(user.toString()); - return setSessionWithUUID(user); + return setSession(user); } - private String setSessionWithUUID(final User user) { + private String setSession(final User user) { final String id = UUID.randomUUID().toString(); final Session session = new Session(id); session.setAttribute("user", user); @@ -49,7 +49,7 @@ public String register(final Map requestBody) { final User user = new User(account, password, email); InMemoryUserRepository.save(user); - return setSessionWithUUID(user); + return setSession(user); } } From 5e1f9dd2f228082027b1c6bde436151f3294bbba Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 23:23:48 +0900 Subject: [PATCH 19/24] =?UTF-8?q?refactor(Http*):=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 44 +++++++++---------- .../{Http11Request.java => HttpRequest.java} | 16 +++---- ...{Http11Response.java => HttpResponse.java} | 8 ++-- 3 files changed, 34 insertions(+), 34 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/request/{Http11Request.java => HttpRequest.java} (89%) rename tomcat/src/main/java/org/apache/coyote/http11/response/{Http11Response.java => HttpResponse.java} (90%) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 70cac4594b..41d5372ed8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -21,9 +21,9 @@ import org.apache.coyote.Processor; import org.apache.coyote.http11.exception.PageNotFoundException; import org.apache.coyote.http11.exception.UnauthorizedException; -import org.apache.coyote.http11.request.Http11Request; +import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.request.Method; -import org.apache.coyote.http11.response.Http11Response; +import org.apache.coyote.http11.response.HttpResponse; import org.apache.coyote.http11.response.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,8 +51,8 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final Http11Request request = readRequest(inputStream); - final Http11Response response = handleRequest(request); + final HttpRequest request = readRequest(inputStream); + final HttpResponse response = handleRequest(request); outputStream.write(response.getResponse().getBytes()); outputStream.flush(); @@ -62,11 +62,11 @@ public void process(final Socket connection) { } } - private Http11Request readRequest(final InputStream inputStream) { + private HttpRequest readRequest(final InputStream inputStream) { final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - final Http11Request request = readRequestHeader(bufferedReader); + final HttpRequest request = readRequestHeader(bufferedReader); final String contentLength = request.getHeader("Content-Length"); if (contentLength != null) { final String requestBody = readRequestBody(bufferedReader, Integer.parseInt(contentLength)); @@ -75,7 +75,7 @@ private Http11Request readRequest(final InputStream inputStream) { return request; } - private Http11Request readRequestHeader(final BufferedReader bufferedReader) { + private HttpRequest readRequestHeader(final BufferedReader bufferedReader) { final StringBuilder input = new StringBuilder(); try { for (String s = bufferedReader.readLine(); @@ -88,7 +88,7 @@ private Http11Request readRequestHeader(final BufferedReader bufferedReader) { log.error(e.getMessage(), e); } - return Http11Request.from(input.toString()); + return HttpRequest.from(input.toString()); } private String readRequestBody(final BufferedReader bufferedReader, final int contentLength) { @@ -101,7 +101,7 @@ private String readRequestBody(final BufferedReader bufferedReader, final int co return new String(buffer); } - private Http11Response handleRequest(final Http11Request request) { + private HttpResponse handleRequest(final HttpRequest request) { try { return handleRequestWithMethod(request); } catch (final PageNotFoundException e) { @@ -116,7 +116,7 @@ private Http11Response handleRequest(final Http11Request request) { } } - private Http11Response handleRequestWithMethod(final Http11Request request) { + private HttpResponse handleRequestWithMethod(final HttpRequest request) { final Method method = request.getMethod(); if (method == GET) { return handleGetRequest(request); @@ -127,13 +127,13 @@ private Http11Response handleRequestWithMethod(final Http11Request request) { throw new PageNotFoundException(request.getPath()); } - private Http11Response handleGetRequest(final Http11Request request) { + private HttpResponse handleGetRequest(final HttpRequest request) { final String path = request.getPath(); if (path.equals("/")) { - return new Http11Response(OK, "Hello world!"); + return new HttpResponse(OK, "Hello world!"); } if (path.equals("/favicon.ico")) { - return new Http11Response(OK, "Icon Not Exist!"); + return new HttpResponse(OK, "Icon Not Exist!"); } if (path.equals("/login") && request.isCookieExist(SESSION_COOKIE_NAME)) { return handleAuthResponse(request, request.getCookie(SESSION_COOKIE_NAME)); @@ -141,7 +141,7 @@ private Http11Response handleGetRequest(final Http11Request request) { try { final URL resource = convertPathToUrl(path); - final Http11Response response = new Http11Response(OK, resource); + final HttpResponse response = new HttpResponse(OK, resource); checkContentType(request, response); return response; } catch (final Exception e) { @@ -149,8 +149,8 @@ private Http11Response handleGetRequest(final Http11Request request) { } } - private Http11Response handleAuthResponse(final Http11Request request, final String uuid) { - final Http11Response response = new Http11Response(FOUND); + private HttpResponse handleAuthResponse(final HttpRequest request, final String uuid) { + final HttpResponse response = new HttpResponse(FOUND); response.addHeader("Location", "/index.html"); if (!request.isCookieExist(SESSION_COOKIE_NAME)) { @@ -166,14 +166,14 @@ private URL convertPathToUrl(String path) { return getClass().getClassLoader().getResource("static" + path); } - private void checkContentType(final Http11Request request, final Http11Response response) { + private void checkContentType(final HttpRequest request, final HttpResponse response) { final String accept = request.getHeader("Accept"); if (accept != null && accept.contains("css")) { response.addHeader("Content-Type", "text/css;charset=utf-8 "); } } - private Http11Response handlePostRequest(final Http11Request request) throws UnauthorizedException { + private HttpResponse handlePostRequest(final HttpRequest request) throws UnauthorizedException { final String path = request.getPath(); if (path.equals("/login")) { return logIn(request); @@ -184,20 +184,20 @@ private Http11Response handlePostRequest(final Http11Request request) throws Una throw new PageNotFoundException(request.getPath()); } - private Http11Response logIn(final Http11Request request) throws UnauthorizedException { + private HttpResponse logIn(final HttpRequest request) throws UnauthorizedException { final Map bodyFields = parseFormData(request.getBody()); final String uuid = userService.logIn(bodyFields); return handleAuthResponse(request, uuid); } - private Http11Response register(final Http11Request request) { + private HttpResponse register(final HttpRequest request) { final Map bodyFields = parseFormData(request.getBody()); final String uuid = userService.register(bodyFields); return handleAuthResponse(request, uuid); } - private Http11Response handleResponseWithException(final Status status) { + private HttpResponse handleResponseWithException(final Status status) { final URL resource = convertPathToUrl("/" + status.getCode()); - return new Http11Response(status, resource); + return new HttpResponse(status, resource); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java similarity index 89% rename from tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 6ccef4464d..c46f299b03 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Http11Request.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Map; -public class Http11Request { +public class HttpRequest { private static final String LINE_SEPARATOR = "\r\n"; final Method method; @@ -17,11 +17,11 @@ public class Http11Request { final Map cookies; String body; - public Http11Request(final Method method, - final String path, - final Map queryParams, - final Map headers, - final Map cookies + public HttpRequest(final Method method, + final String path, + final Map queryParams, + final Map headers, + final Map cookies ) { this.method = method; this.path = path; @@ -30,7 +30,7 @@ public Http11Request(final Method method, this.cookies = cookies; } - public static Http11Request from(final String request) { + public static HttpRequest from(final String request) { final List lines = new ArrayList<>(List.of(request.split(LINE_SEPARATOR))); final String[] requestUri = lines.remove(0).split(" "); @@ -50,7 +50,7 @@ public static Http11Request from(final String request) { final String cookieFields = headers.remove("Cookie"); final Map cookies = parseCookies(cookieFields); - return new Http11Request( + return new HttpRequest( Method.getMethod(method), path, queryParams, diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java similarity index 90% rename from tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java rename to tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 47b23744cd..59c3b03724 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Http11Response.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -10,14 +10,14 @@ import java.util.stream.Collectors; import org.apache.coyote.http11.exception.PageNotFoundException; -public class Http11Response { +public class HttpResponse { private static final String LINE_SEPARATOR = "\r\n"; final Status status; final Map headers; final String body; - public Http11Response(final Status status, final String body) { + public HttpResponse(final Status status, final String body) { this.status = status; this.headers = new LinkedHashMap<>(); headers.put("Content-Type", "text/html;charset=utf-8 "); @@ -28,11 +28,11 @@ public Http11Response(final Status status, final String body) { } } - public Http11Response(final Status status) { + public HttpResponse(final Status status) { this(status, ""); } - public Http11Response(final Status status, final URL resource) { + public HttpResponse(final Status status, final URL resource) { this(status, readResponseBody(resource)); } From de9920224e9609ae6a18929e7742a9337ce5a8c5 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 23:25:40 +0900 Subject: [PATCH 20/24] =?UTF-8?q?refactor(Http11Processor):=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/apache/coyote/http11/Http11Processor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 41d5372ed8..5741b7df5f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -96,7 +96,7 @@ private String readRequestBody(final BufferedReader bufferedReader, final int co try { bufferedReader.read(buffer, 0, contentLength); } catch (final IOException e) { - throw new RuntimeException(e); + log.error(e.getMessage(), e); } return new String(buffer); } From 702c0b795f77439b21fed02a173dc6e7193b6ad5 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Tue, 5 Sep 2023 23:46:35 +0900 Subject: [PATCH 21/24] =?UTF-8?q?refactor(Constant):=20=EC=83=81=EC=88=98?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 12 ++--- .../coyote/http11/request/HttpRequest.java | 45 ++++++++++++------- .../coyote/http11/response/HttpResponse.java | 11 +++-- .../apache/coyote/http11/utils/Constant.java | 13 ++++++ 4 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/utils/Constant.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 5741b7df5f..52bb046389 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -7,6 +7,9 @@ import static org.apache.coyote.http11.response.Status.NOT_FOUND; import static org.apache.coyote.http11.response.Status.OK; import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; +import static org.apache.coyote.http11.utils.Constant.BASE_PATH; +import static org.apache.coyote.http11.utils.Constant.COOKIE_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.LINE_SEPARATOR; import static org.apache.coyote.http11.utils.Parser.parseFormData; import java.io.BufferedReader; @@ -30,7 +33,6 @@ public class Http11Processor implements Runnable, Processor { private static final String SESSION_COOKIE_NAME = "JSESSIONID"; - private static final String LINE_SEPARATOR = "\r\n"; private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; @@ -79,7 +81,7 @@ private HttpRequest readRequestHeader(final BufferedReader bufferedReader) { final StringBuilder input = new StringBuilder(); try { for (String s = bufferedReader.readLine(); - !"".equals(s); + !EMPTY.equals(s); s = bufferedReader.readLine()) { input.append(s) .append(LINE_SEPARATOR); @@ -129,7 +131,7 @@ private HttpResponse handleRequestWithMethod(final HttpRequest request) { private HttpResponse handleGetRequest(final HttpRequest request) { final String path = request.getPath(); - if (path.equals("/")) { + if (path.equals(BASE_PATH)) { return new HttpResponse(OK, "Hello world!"); } if (path.equals("/favicon.ico")) { @@ -154,7 +156,7 @@ private HttpResponse handleAuthResponse(final HttpRequest request, final String response.addHeader("Location", "/index.html"); if (!request.isCookieExist(SESSION_COOKIE_NAME)) { - response.addHeader("Set-Cookie", "JSESSIONID=" + uuid); + response.addHeader("Set-Cookie", SESSION_COOKIE_NAME + COOKIE_DELIMITER + uuid); } return response; } @@ -197,7 +199,7 @@ private HttpResponse register(final HttpRequest request) { } private HttpResponse handleResponseWithException(final Status status) { - final URL resource = convertPathToUrl("/" + status.getCode()); + final URL resource = convertPathToUrl(BASE_PATH + status.getCode()); return new HttpResponse(status, resource); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index c46f299b03..a114ca97d0 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -1,5 +1,10 @@ package org.apache.coyote.http11.request; +import static org.apache.coyote.http11.utils.Constant.COOKIES_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.COOKIE_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.EMPTY; +import static org.apache.coyote.http11.utils.Constant.HEADER_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.LINE_SEPARATOR; import static org.apache.coyote.http11.utils.Parser.parseFormData; import java.util.ArrayList; @@ -8,7 +13,17 @@ import java.util.Map; public class HttpRequest { - private static final String LINE_SEPARATOR = "\r\n"; + private static final String SPLIT_DELIMITER = " "; + private static final int REQUEST_LINE_INDEX = 0; + private static final int METHOD_INDEX = 0; + private static final int URI_INDEX = 1; + private static final int PATH_INDEX = 0; + private static final int QUERY_STRING_INDEX = 1; + private static final String HEADER_COOKIE = "Cookie"; + private static final int SPLIT_LIMIT_SIZE = 2; + private static final int KEY_INDEX = 0; + private static final int VALUE_INDEX = 1; + public static final String QUERY_STRING_DELIMITER = "\\?"; final Method method; final String path; @@ -33,21 +48,21 @@ public HttpRequest(final Method method, public static HttpRequest from(final String request) { final List lines = new ArrayList<>(List.of(request.split(LINE_SEPARATOR))); - final String[] requestUri = lines.remove(0).split(" "); - final String method = requestUri[0]; - final String uri = requestUri[1]; + final String[] requestUri = lines.remove(REQUEST_LINE_INDEX).split(SPLIT_DELIMITER); + final String method = requestUri[METHOD_INDEX]; + final String uri = requestUri[URI_INDEX]; - final String[] uris = uri.split("\\?"); - final String path = uris[0]; + final String[] uris = uri.split(QUERY_STRING_DELIMITER); + final String path = uris[PATH_INDEX]; - String queryString = ""; + String queryString = EMPTY; if (uris.length > 1) { - queryString = uris[1]; + queryString = uris[QUERY_STRING_INDEX]; } final Map queryParams = parseFormData(queryString); final Map headers = parseHeaders(lines); - final String cookieFields = headers.remove("Cookie"); + final String cookieFields = headers.remove(HEADER_COOKIE); final Map cookies = parseCookies(cookieFields); return new HttpRequest( @@ -62,11 +77,11 @@ public static HttpRequest from(final String request) { private static Map parseHeaders(final List lines) { final Map headers = new HashMap<>(); for (final String line : lines) { - if ("".equals(line)) { + if (EMPTY.equals(line)) { break; } - final String[] header = line.split(": ", 2); - headers.put(header[0], header[1]); + final String[] header = line.split(HEADER_DELIMITER, SPLIT_LIMIT_SIZE); + headers.put(header[KEY_INDEX], header[VALUE_INDEX]); } return headers; } @@ -77,9 +92,9 @@ private static Map parseCookies(final String cookieFields) { return cookies; } - for (final String field : cookieFields.split("; ")) { - final String[] cookie = field.split("=", 2); - cookies.put(cookie[0], cookie[1]); + for (final String field : cookieFields.split(COOKIES_DELIMITER)) { + final String[] cookie = field.split(COOKIE_DELIMITER, SPLIT_LIMIT_SIZE); + cookies.put(cookie[KEY_INDEX], cookie[VALUE_INDEX]); } return cookies; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 59c3b03724..502c78796c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,5 +1,9 @@ package org.apache.coyote.http11.response; +import static org.apache.coyote.http11.utils.Constant.EMPTY; +import static org.apache.coyote.http11.utils.Constant.HEADER_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.LINE_SEPARATOR; + import java.io.File; import java.io.IOException; import java.net.URL; @@ -11,7 +15,6 @@ import org.apache.coyote.http11.exception.PageNotFoundException; public class HttpResponse { - private static final String LINE_SEPARATOR = "\r\n"; final Status status; final Map headers; @@ -29,7 +32,7 @@ public HttpResponse(final Status status, final String body) { } public HttpResponse(final Status status) { - this(status, ""); + this(status, EMPTY); } public HttpResponse(final Status status, final URL resource) { @@ -59,7 +62,7 @@ public String getResponse() { return String.join(LINE_SEPARATOR, "HTTP/1.1 " + formattedStatus, formattedHeaders, - "", + EMPTY, body); } @@ -68,6 +71,6 @@ private String formatStatus(final Status status) { } private String formatHeader(final String header) { - return header + ": " + headers.get(header); + return header + HEADER_DELIMITER + headers.get(header); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/utils/Constant.java b/tomcat/src/main/java/org/apache/coyote/http11/utils/Constant.java new file mode 100644 index 0000000000..30ce02ba62 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/utils/Constant.java @@ -0,0 +1,13 @@ +package org.apache.coyote.http11.utils; + +public class Constant { + public static final String LINE_SEPARATOR = "\r\n"; + public static final String EMPTY = ""; + public static final String HEADER_DELIMITER = ": "; + public static final String COOKIES_DELIMITER = "; "; + public static final String COOKIE_DELIMITER = "="; + public static final String BASE_PATH = "/"; + + private Constant() { + } +} From a0b819ca5713d9853810589bbf41142b4f94cd80 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Wed, 6 Sep 2023 13:58:17 +0900 Subject: [PATCH 22/24] =?UTF-8?q?feat(*Header):=20Header=20Enum=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 16 +++++++++++----- .../coyote/http11/request/HttpRequest.java | 7 +++---- .../coyote/http11/request/RequestHeader.java | 16 ++++++++++++++++ .../coyote/http11/response/HttpResponse.java | 10 ++++++---- .../coyote/http11/response/ResponseHeader.java | 18 ++++++++++++++++++ 5 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/RequestHeader.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHeader.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java index 52bb046389..ec8fec73ac 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -2,6 +2,9 @@ import static org.apache.coyote.http11.request.Method.GET; import static org.apache.coyote.http11.request.Method.POST; +import static org.apache.coyote.http11.request.RequestHeader.ACCEPT; +import static org.apache.coyote.http11.response.ResponseHeader.LOCATION; +import static org.apache.coyote.http11.response.ResponseHeader.SET_COOKIE; import static org.apache.coyote.http11.response.Status.FOUND; import static org.apache.coyote.http11.response.Status.INTERNAL_SERVER_ERROR; import static org.apache.coyote.http11.response.Status.NOT_FOUND; @@ -9,6 +12,7 @@ import static org.apache.coyote.http11.response.Status.UNAUTHORIZED; import static org.apache.coyote.http11.utils.Constant.BASE_PATH; import static org.apache.coyote.http11.utils.Constant.COOKIE_DELIMITER; +import static org.apache.coyote.http11.utils.Constant.EMPTY; import static org.apache.coyote.http11.utils.Constant.LINE_SEPARATOR; import static org.apache.coyote.http11.utils.Parser.parseFormData; @@ -26,7 +30,9 @@ import org.apache.coyote.http11.exception.UnauthorizedException; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.request.Method; +import org.apache.coyote.http11.request.RequestHeader; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.ResponseHeader; import org.apache.coyote.http11.response.Status; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,7 +75,7 @@ private HttpRequest readRequest(final InputStream inputStream) { final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); final HttpRequest request = readRequestHeader(bufferedReader); - final String contentLength = request.getHeader("Content-Length"); + final String contentLength = request.getHeader(RequestHeader.CONTENT_LENGTH); if (contentLength != null) { final String requestBody = readRequestBody(bufferedReader, Integer.parseInt(contentLength)); request.setBody(requestBody); @@ -154,9 +160,9 @@ private HttpResponse handleGetRequest(final HttpRequest request) { private HttpResponse handleAuthResponse(final HttpRequest request, final String uuid) { final HttpResponse response = new HttpResponse(FOUND); - response.addHeader("Location", "/index.html"); + response.addHeader(LOCATION, "/index.html"); if (!request.isCookieExist(SESSION_COOKIE_NAME)) { - response.addHeader("Set-Cookie", SESSION_COOKIE_NAME + COOKIE_DELIMITER + uuid); + response.addHeader(SET_COOKIE, SESSION_COOKIE_NAME + COOKIE_DELIMITER + uuid); } return response; } @@ -169,9 +175,9 @@ private URL convertPathToUrl(String path) { } private void checkContentType(final HttpRequest request, final HttpResponse response) { - final String accept = request.getHeader("Accept"); + final String accept = request.getHeader(ACCEPT); if (accept != null && accept.contains("css")) { - response.addHeader("Content-Type", "text/css;charset=utf-8 "); + response.addHeader(ResponseHeader.CONTENT_LENGTH, "text/css;charset=utf-8 "); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index a114ca97d0..19b4332730 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -13,6 +13,7 @@ import java.util.Map; public class HttpRequest { + private static final String QUERY_STRING_DELIMITER = "\\?"; private static final String SPLIT_DELIMITER = " "; private static final int REQUEST_LINE_INDEX = 0; private static final int METHOD_INDEX = 0; @@ -23,8 +24,6 @@ public class HttpRequest { private static final int SPLIT_LIMIT_SIZE = 2; private static final int KEY_INDEX = 0; private static final int VALUE_INDEX = 1; - public static final String QUERY_STRING_DELIMITER = "\\?"; - final Method method; final String path; final Map queryParams; @@ -119,8 +118,8 @@ public String getQueryParam(final String parameterName) { return queryParams.get(parameterName); } - public String getHeader(final String headerName) { - return headers.get(headerName); + public String getHeader(final RequestHeader header) { + return headers.get(header.getName()); } public boolean isCookieExist(final String cookieName) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHeader.java new file mode 100644 index 0000000000..c596cde216 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHeader.java @@ -0,0 +1,16 @@ +package org.apache.coyote.http11.request; + +public enum RequestHeader { + CONTENT_LENGTH("Content-Length"), + ACCEPT("Accept"); + + private final String name; + + RequestHeader(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 502c78796c..3430a2f30f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,5 +1,7 @@ package org.apache.coyote.http11.response; +import static org.apache.coyote.http11.response.ResponseHeader.CONTENT_LENGTH; +import static org.apache.coyote.http11.response.ResponseHeader.CONTENT_TYPE; import static org.apache.coyote.http11.utils.Constant.EMPTY; import static org.apache.coyote.http11.utils.Constant.HEADER_DELIMITER; import static org.apache.coyote.http11.utils.Constant.LINE_SEPARATOR; @@ -23,11 +25,11 @@ public class HttpResponse { public HttpResponse(final Status status, final String body) { this.status = status; this.headers = new LinkedHashMap<>(); - headers.put("Content-Type", "text/html;charset=utf-8 "); + headers.put(CONTENT_TYPE.getName(), "text/html;charset=utf-8 "); this.body = body; if (body.length() > 0) { - headers.put("Content-Length", body.getBytes().length + " "); + headers.put(CONTENT_LENGTH.getName(), body.getBytes().length + " "); } } @@ -49,8 +51,8 @@ private static String readResponseBody(final URL resource) { } } - public void addHeader(final String headerName, final String value) { - headers.put(headerName, value); + public void addHeader(final ResponseHeader header, final String value) { + headers.put(header.getName(), value); } public String getResponse() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHeader.java new file mode 100644 index 0000000000..cb261d8dcc --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHeader.java @@ -0,0 +1,18 @@ +package org.apache.coyote.http11.response; + +public enum ResponseHeader { + CONTENT_LENGTH("Content-Length"), + CONTENT_TYPE("Content-Type"), + LOCATION("Location"), + SET_COOKIE("Set-Cookie"); + + private final String name; + + ResponseHeader(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} From d62ae1128442339a39689e9a778480d29580b9b1 Mon Sep 17 00:00:00 2001 From: LJW25 Date: Wed, 6 Sep 2023 17:52:44 +0900 Subject: [PATCH 23/24] =?UTF-8?q?refactor(Status):=20status=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/response/HttpResponse.java | 6 +----- .../main/java/org/apache/coyote/http11/response/Status.java | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 3430a2f30f..1f5a29526e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -56,7 +56,7 @@ public void addHeader(final ResponseHeader header, final String value) { } public String getResponse() { - final String formattedStatus = formatStatus(status); + final String formattedStatus = status.getStatusLine(); final String formattedHeaders = headers.keySet().stream() .map(this::formatHeader) .collect(Collectors.joining(LINE_SEPARATOR)); @@ -68,10 +68,6 @@ public String getResponse() { body); } - private String formatStatus(final Status status) { - return status.getCode() + " " + status.getName() + " "; - } - private String formatHeader(final String header) { return header + HEADER_DELIMITER + headers.get(header); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java index 4764d87efe..602cac81f6 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java @@ -15,6 +15,10 @@ public enum Status { this.name = name; } + public String getStatusLine() { + return code + " " + name + " "; + } + public int getCode() { return code; } From 90b384e570013661c69a679737bc0a1f230bd43b Mon Sep 17 00:00:00 2001 From: LJW25 Date: Wed, 6 Sep 2023 17:55:12 +0900 Subject: [PATCH 24/24] =?UTF-8?q?refactor(all):=20=EC=BD=94=EB=93=9C=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 --- .../main/java/nextstep/jwp/service/UserService.java | 2 +- .../apache/coyote/http11/request/HttpRequest.java | 13 +++++++------ .../org/apache/coyote/http11/request/Method.java | 2 +- .../apache/coyote/http11/response/HttpResponse.java | 6 +++--- .../org/apache/coyote/http11/response/Status.java | 4 ++-- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tomcat/src/main/java/nextstep/jwp/service/UserService.java b/tomcat/src/main/java/nextstep/jwp/service/UserService.java index 8f7215df62..5fe12fdb74 100644 --- a/tomcat/src/main/java/nextstep/jwp/service/UserService.java +++ b/tomcat/src/main/java/nextstep/jwp/service/UserService.java @@ -23,7 +23,7 @@ public String logIn(final Map requestBody) { if (!user.checkPassword(password)) { throw new UnauthorizedException(account); } - log.info(user.toString()); + log.info("{}", user); return setSession(user); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 19b4332730..0334d25b55 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -24,12 +24,13 @@ public class HttpRequest { private static final int SPLIT_LIMIT_SIZE = 2; private static final int KEY_INDEX = 0; private static final int VALUE_INDEX = 1; - final Method method; - final String path; - final Map queryParams; - final Map headers; - final Map cookies; - String body; + + private final Method method; + private final String path; + private final Map queryParams; + private final Map headers; + private final Map cookies; + private String body; public HttpRequest(final Method method, final String path, diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index b680c2ee49..8625d55197 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -6,7 +6,7 @@ public enum Method { GET("GET"), POST("POST"); - final String name; + private final String name; Method(final String name) { this.name = name; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 1f5a29526e..743169f695 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -18,9 +18,9 @@ public class HttpResponse { - final Status status; - final Map headers; - final String body; + private final Status status; + private final Map headers; + private final String body; public HttpResponse(final Status status, final String body) { this.status = status; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java index 602cac81f6..6959d97a27 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/Status.java @@ -7,8 +7,8 @@ public enum Status { NOT_FOUND(404, "Not Found"), INTERNAL_SERVER_ERROR(500, "Internal Server Error"); - final int code; - final String name; + private final int code; + private final String name; Status(final int code, final String name) { this.code = code;