From fed02f6f5f4308400e55c160d9495cad010f5bfb Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Thu, 5 Sep 2024 11:11:09 +0900 Subject: [PATCH 01/62] fix: remove implementation logback-classic on gradle (#501) --- study/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/study/build.gradle b/study/build.gradle index 5c69542f84..87a1f0313c 100644 --- a/study/build.gradle +++ b/study/build.gradle @@ -19,7 +19,6 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'ch.qos.logback:logback-classic:1.5.7' implementation 'org.apache.commons:commons-lang3:3.14.0' implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1' implementation 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.4.1' From 7e9135698878932274ddc1f523ba817ed9c56c70 Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Thu, 5 Sep 2024 13:51:07 +0900 Subject: [PATCH 02/62] fix: add threads min-spare configuration on properties (#502) --- study/src/main/resources/application.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index 4e8655a962..e3503a5fb9 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -6,4 +6,5 @@ server: accept-count: 1 max-connections: 1 threads: + min-spare: 2 max: 2 From f96f2f64c1cd3d73b781cbfd38dfc4dbb9e457bf Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 01:49:13 +0900 Subject: [PATCH 03/62] =?UTF-8?q?test:=20FileTest=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/test/java/study/FileTest.java | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/study/src/test/java/study/FileTest.java b/study/src/test/java/study/FileTest.java index e1b6cca042..8b08d1408b 100644 --- a/study/src/test/java/study/FileTest.java +++ b/study/src/test/java/study/FileTest.java @@ -1,13 +1,15 @@ package study; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; /** * 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다. @@ -24,11 +26,12 @@ class FileTest { * resource 디렉터리의 경로는 어떻게 알아낼 수 있을까? */ @Test - void resource_디렉터리에_있는_파일의_경로를_찾는다() { + void resource_디렉터리에_있는_파일의_경로를_찾는다() throws URISyntaxException { final String fileName = "nextstep.txt"; - // todo - final String actual = ""; + URL resource = getClass().getResource("/" + fileName); + Path path = Path.of(resource.toURI()); + final String actual = path.toString(); assertThat(actual).endsWith(fileName); } @@ -40,14 +43,12 @@ class FileTest { * File, Files 클래스를 사용하여 파일의 내용을 읽어보자. */ @Test - void 파일의_내용을_읽는다() { + void 파일의_내용을_읽는다() throws IOException, URISyntaxException { final String fileName = "nextstep.txt"; + URL resource = getClass().getResource("/" + fileName); + Path path = Path.of(resource.toURI()); - // todo - final Path path = null; - - // todo - final List actual = Collections.emptyList(); + List actual = Files.readAllLines(path); assertThat(actual).containsOnly("nextstep"); } From 300e6b537fb164c677db693bdfec95b8abee4489 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 01:53:22 +0900 Subject: [PATCH 04/62] =?UTF-8?q?test:=20IOStreamTest=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/test/java/study/IOStreamTest.java | 73 +++++++++++---------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/study/src/test/java/study/IOStreamTest.java b/study/src/test/java/study/IOStreamTest.java index 47a79356b6..0c3c7780b7 100644 --- a/study/src/test/java/study/IOStreamTest.java +++ b/study/src/test/java/study/IOStreamTest.java @@ -1,14 +1,24 @@ package study; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import java.io.*; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - /** * 자바는 스트림(Stream)으로부터 I/O를 사용한다. * 입출력(I/O)은 하나의 시스템에서 다른 시스템으로 데이터를 이동 시킬 때 사용한다. @@ -49,13 +59,9 @@ class OutputStream_학습_테스트 { final byte[] bytes = {110, 101, 120, 116, 115, 116, 101, 112}; final OutputStream outputStream = new ByteArrayOutputStream(bytes.length); - /** - * todo - * OutputStream 객체의 write 메서드를 사용해서 테스트를 통과시킨다 - */ + outputStream.write(bytes); final String actual = outputStream.toString(); - assertThat(actual).isEqualTo("nextstep"); outputStream.close(); } @@ -73,11 +79,7 @@ class OutputStream_학습_테스트 { void BufferedOutputStream을_사용하면_버퍼링이_가능하다() throws IOException { final OutputStream outputStream = mock(BufferedOutputStream.class); - /** - * todo - * flush를 사용해서 테스트를 통과시킨다. - * ByteArrayOutputStream과 어떤 차이가 있을까? - */ + outputStream.flush(); verify(outputStream, atLeastOnce()).flush(); outputStream.close(); @@ -90,12 +92,10 @@ class OutputStream_학습_테스트 { @Test void OutputStream은_사용하고_나서_close_처리를_해준다() throws IOException { final OutputStream outputStream = mock(OutputStream.class); - - /** - * todo - * try-with-resources를 사용한다. - * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. - */ + try(outputStream) { + outputStream.write(1); + outputStream.flush(); + } verify(outputStream, atLeastOnce()).close(); } @@ -124,12 +124,9 @@ class InputStream_학습_테스트 { byte[] bytes = {-16, -97, -92, -87}; final InputStream inputStream = new ByteArrayInputStream(bytes); - /** - * todo - * inputStream에서 바이트로 반환한 값을 문자열로 어떻게 바꿀까? - */ - final String actual = ""; + byte[] read = inputStream.readAllBytes(); + final String actual = new String(read); assertThat(actual).isEqualTo("🤩"); assertThat(inputStream.read()).isEqualTo(-1); inputStream.close(); @@ -143,11 +140,8 @@ class InputStream_학습_테스트 { void InputStream은_사용하고_나서_close_처리를_해준다() throws IOException { final InputStream inputStream = mock(InputStream.class); - /** - * todo - * try-with-resources를 사용한다. - * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. - */ + try(inputStream) { + } verify(inputStream, atLeastOnce()).close(); } @@ -169,12 +163,12 @@ class FilterStream_학습_테스트 { * 버퍼 크기를 지정하지 않으면 버퍼의 기본 사이즈는 얼마일까? */ @Test - void 필터인_BufferedInputStream를_사용해보자() { + void 필터인_BufferedInputStream를_사용해보자() throws IOException { 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 = bufferedInputStream.readAllBytes(); assertThat(bufferedInputStream).isInstanceOf(FilterInputStream.class); assertThat(actual).isEqualTo("필터에 연결해보자.".getBytes()); @@ -197,15 +191,24 @@ class InputStreamReader_학습_테스트 { * 필터인 BufferedReader를 사용하면 readLine 메서드를 사용해서 문자열(String)을 한 줄 씩 읽어올 수 있다. */ @Test - void BufferedReader를_사용하여_문자열을_읽어온다() { + void BufferedReader를_사용하여_문자열을_읽어온다() throws IOException { final String emoji = String.join("\r\n", "😀😃😄😁😆😅😂🤣🥲☺️😊", "😇🙂🙃😉😌😍🥰😘😗😙😚", "😋😛😝😜🤪🤨🧐🤓😎🥸🤩", ""); final InputStream inputStream = new ByteArrayInputStream(emoji.getBytes()); + final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); final StringBuilder actual = new StringBuilder(); + while (true) { + String txt = bufferedReader.readLine(); + if (txt == null) { + break; + } + actual.append(txt).append("\r\n"); + } assertThat(actual).hasToString(emoji); } From 060bd98a5379c34337c5ada8696a81c52efb3612 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 17:13:55 +0900 Subject: [PATCH 05/62] =?UTF-8?q?feat:=20index.html=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 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 bb14184757..0dc5ac3662 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,16 +1,22 @@ package org.apache.coyote.http11; import com.techcourse.exception.UncheckedServletException; +import java.io.File; +import java.io.IOException; +import java.net.Socket; +import java.net.URL; +import java.nio.file.Files; import org.apache.coyote.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.net.Socket; - public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); + private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; + private static final String HOME_PAGE_METHOD = "GET"; + private static final String HOME_PAGE_ROUTE = "/index.html"; + private static final String HOME_PAGE_RESPONSE_BODY = "static/index.html"; private final Socket connection; @@ -29,8 +35,9 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final var responseBody = "Hello world!"; + String requestMessage = new String(inputStream.readAllBytes()); + final var responseBody = buildResponseBody(requestMessage); final var response = String.join("\r\n", "HTTP/1.1 200 OK ", "Content-Type: text/html;charset=utf-8 ", @@ -44,4 +51,21 @@ public void process(final Socket connection) { log.error(e.getMessage(), e); } } + + private String buildResponseBody(String requestMessage) throws IOException { + String requestFirstLine = requestMessage.split(System.lineSeparator())[0].trim(); + String httpMethod = requestFirstLine.split(" ")[0]; + String route = requestFirstLine.split(" ")[1]; + + if (!HOME_PAGE_METHOD.equals(httpMethod) || !HOME_PAGE_ROUTE.equals(route)) { + return DEFAULT_RESPONSE_BODY; + } + + URL resource = getClass().getClassLoader().getResource(HOME_PAGE_RESPONSE_BODY); + if (resource == null) { + throw new InternalError("기본으로 보여줄 파일을 찾을 수 없습니다."); + } + + return new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + } } From 31a6516640701a758cabbd991a8ff34ede8bab96 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 17:14:19 +0900 Subject: [PATCH 06/62] =?UTF-8?q?refactor:=20import=20=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 우테코 컨벤션에 맞게 --- .../java/org/apache/coyote/http11/Http11ProcessorTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java index 2aba8c56e0..98282f4144 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -1,14 +1,13 @@ package org.apache.coyote.http11; -import org.junit.jupiter.api.Test; -import support.StubSocket; +import static org.assertj.core.api.Assertions.assertThat; 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.junit.jupiter.api.Test; +import support.StubSocket; class Http11ProcessorTest { From fc55c4eaa88dcdeb6b61ecdd0152376199444ba9 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 19:50:12 +0900 Subject: [PATCH 07/62] =?UTF-8?q?refactor:=20inputStreamReader=20=EB=A5=BC?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=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 --- .../org/apache/coyote/http11/Http11Processor.java | 12 +++++++----- 1 file changed, 7 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 0dc5ac3662..e75912974f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,8 +1,10 @@ package org.apache.coyote.http11; import com.techcourse.exception.UncheckedServletException; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.net.Socket; import java.net.URL; import java.nio.file.Files; @@ -35,9 +37,11 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - String requestMessage = new String(inputStream.readAllBytes()); + final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + String requestFirstLine = bufferedReader.readLine(); - final var responseBody = buildResponseBody(requestMessage); + final var responseBody = buildResponseBody(requestFirstLine); final var response = String.join("\r\n", "HTTP/1.1 200 OK ", "Content-Type: text/html;charset=utf-8 ", @@ -52,11 +56,9 @@ public void process(final Socket connection) { } } - private String buildResponseBody(String requestMessage) throws IOException { - String requestFirstLine = requestMessage.split(System.lineSeparator())[0].trim(); + private String buildResponseBody(String requestFirstLine) throws IOException { String httpMethod = requestFirstLine.split(" ")[0]; String route = requestFirstLine.split(" ")[1]; - if (!HOME_PAGE_METHOD.equals(httpMethod) || !HOME_PAGE_ROUTE.equals(route)) { return DEFAULT_RESPONSE_BODY; } From 8f433127c6d62167be552de7b92e653dc194d4a5 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 20:48:39 +0900 Subject: [PATCH 08/62] =?UTF-8?q?feat:=20=EC=A0=95=EC=83=81=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5,=20=EC=98=88=EC=99=B8=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=95=A8=EC=88=98=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 | 53 ++++++++++++------- 1 file changed, 35 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 e75912974f..d8a1bc61af 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -15,8 +15,9 @@ public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); + private static final String GET_METHOD = "GET"; + private static final String DEFAULT_ROUTE = "/"; private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; - private static final String HOME_PAGE_METHOD = "GET"; private static final String HOME_PAGE_ROUTE = "/index.html"; private static final String HOME_PAGE_RESPONSE_BODY = "static/index.html"; @@ -36,19 +37,11 @@ public void run() { public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - String requestFirstLine = bufferedReader.readLine(); - - final var responseBody = buildResponseBody(requestFirstLine); - 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); + String requestFirstLine = bufferedReader.readLine(); + final var response = bindResponse(requestFirstLine); outputStream.write(response.getBytes()); outputStream.flush(); } catch (IOException | UncheckedServletException e) { @@ -56,18 +49,42 @@ public void process(final Socket connection) { } } - private String buildResponseBody(String requestFirstLine) throws IOException { + private String bindResponse(String requestFirstLine) throws IOException { String httpMethod = requestFirstLine.split(" ")[0]; String route = requestFirstLine.split(" ")[1]; - if (!HOME_PAGE_METHOD.equals(httpMethod) || !HOME_PAGE_ROUTE.equals(route)) { - return DEFAULT_RESPONSE_BODY; + + if (DEFAULT_ROUTE.equals(route) && GET_METHOD.equals(httpMethod)) { + return buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); } - URL resource = getClass().getClassLoader().getResource(HOME_PAGE_RESPONSE_BODY); - if (resource == null) { - throw new InternalError("기본으로 보여줄 파일을 찾을 수 없습니다."); + if (HOME_PAGE_ROUTE.equals(route) && GET_METHOD.equals(httpMethod)) { + URL resource = getClass().getClassLoader().getResource(HOME_PAGE_RESPONSE_BODY); + if (resource == null) { + throw new InternalError("기본으로 보여줄 파일을 찾을 수 없습니다."); + } + String body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + return buildSuccessfulResponse(body); } - return new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + return buildFailedResponse(404, "NotFound", + "There is no static resource matched with rout and method"); + } + + private String buildSuccessfulResponse(String responseBody) { + return String.join("\r\n", + "HTTP/1.1 200 OK ", + "Content-Type: text/html;charset=utf-8 ", + "Content-Length: " + responseBody.getBytes().length + " ", + "", + responseBody); + } + + private String buildFailedResponse(int statusCode, String statusMessage, String responseBody) { + return String.join("\r\n", + "HTTP/1.1 " + statusCode + " " + statusMessage, + "Content-Type: text/html;charset=utf-8 ", + "Content-Length: " + responseBody.getBytes().length + " ", + "", + responseBody); } } From c08da98f853e4f5e1a5793ce75334deee7bc19b8 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 20:49:16 +0900 Subject: [PATCH 09/62] =?UTF-8?q?test:=20/=20=EA=B2=BD=EB=A1=9C=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8,=20?= =?UTF-8?q?=EC=9E=98=EB=AA=BB=EB=90=9C=20=EA=B2=BD=EB=A1=9C=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/Http11ProcessorTest.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java index 98282f4144..d2af7fa7e7 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -6,12 +6,14 @@ import java.io.IOException; import java.net.URL; import java.nio.file.Files; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import support.StubSocket; class Http11ProcessorTest { @Test + @DisplayName("요청 내용을 전달하지 않으면 기본 메세지를 보여준다") void process() { // given final var socket = new StubSocket(); @@ -32,6 +34,35 @@ void process() { } @Test + @DisplayName("/ 경로로 요청을 하면, 기본 메세지를 응답한다.") + void home() throws IOException { + // given + final String httpRequest= String.join("\r\n", + "GET / 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 + var expected = String.join("\r\n", + "HTTP/1.1 200 OK ", + "Content-Type: text/html;charset=utf-8 ", + "Content-Length: 12 ", + "", + "Hello world!"); + + assertThat(socket.output()).isEqualTo(expected); + } + + @Test + @DisplayName("/index.html 경로로 요청을 하면, /resource/index.html 페이지를 응답한다.") void index() throws IOException { // given final String httpRequest= String.join("\r\n", @@ -57,4 +88,28 @@ void index() throws IOException { assertThat(socket.output()).isEqualTo(expected); } + + @Test + @DisplayName("HTTP 함수와 경로에 매칭되는 것이 없으면, 예외 메세지를 보여준다") + void failedResponse() { + // given + final String httpRequest= String.join("\r\n", + "GET /inde.html 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 + var expected = "HTTP/1.1 404 NotFound\r\n" + + "Content-Type: text/html;charset=utf-8"; + + assertThat(socket.output()).startsWith(expected); + } } From 679a5e3f1aaf80619651c787d8e6701eb72668c9 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 20:55:43 +0900 Subject: [PATCH 10/62] =?UTF-8?q?style:=20=EC=BD=94=EB=93=9C=20=EC=9E=AC?= =?UTF-8?q?=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/Http11ProcessorTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java index d2af7fa7e7..e71808ba26 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -35,9 +35,9 @@ void process() { @Test @DisplayName("/ 경로로 요청을 하면, 기본 메세지를 응답한다.") - void home() throws IOException { + void home() { // given - final String httpRequest= String.join("\r\n", + final String httpRequest = String.join("\r\n", "GET / HTTP/1.1 ", "Host: localhost:8080 ", "Connection: keep-alive ", @@ -65,7 +65,7 @@ void home() throws IOException { @DisplayName("/index.html 경로로 요청을 하면, /resource/index.html 페이지를 응답한다.") 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 ", @@ -83,7 +83,7 @@ void index() throws IOException { 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); @@ -93,7 +93,7 @@ void index() throws IOException { @DisplayName("HTTP 함수와 경로에 매칭되는 것이 없으면, 예외 메세지를 보여준다") void failedResponse() { // given - final String httpRequest= String.join("\r\n", + final String httpRequest = String.join("\r\n", "GET /inde.html HTTP/1.1 ", "Host: localhost:8080 ", "Connection: keep-alive ", From 111a0350ca09fc96c3ba5d05ea03a0c04eafb2d2 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Wed, 4 Sep 2024 21:21:21 +0900 Subject: [PATCH 11/62] =?UTF-8?q?feat:=20=ED=8C=8C=EC=9D=BC=ED=99=95?= =?UTF-8?q?=EC=9E=A5=EC=9E=90->contentType=20=EB=B3=80=ED=99=98=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/ContentTypeConverter.java | 20 +++++++++++++ .../apache/coyote/http11/Http11Processor.java | 30 ++++++++----------- 2 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java b/tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java new file mode 100644 index 0000000000..9af458be9b --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java @@ -0,0 +1,20 @@ +package org.apache.coyote.http11; + +import java.util.Map; + +class ContentTypeConverter { + + private static final Map MAP = Map.of( + "html", "text/html", + "css", "text/css", + "js", "application/javascript" + ); + + String mapToContentType(String fileExtension) { + if (MAP.get(fileExtension) == null) { + return "text/html"; + } + + return MAP.get(fileExtension); + } +} 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 d8a1bc61af..bc65abf096 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -18,8 +18,6 @@ public class Http11Processor implements Runnable, Processor { private static final String GET_METHOD = "GET"; private static final String DEFAULT_ROUTE = "/"; private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; - private static final String HOME_PAGE_ROUTE = "/index.html"; - private static final String HOME_PAGE_RESPONSE_BODY = "static/index.html"; private final Socket connection; @@ -40,9 +38,11 @@ public void process(final Socket connection) { final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - String requestFirstLine = bufferedReader.readLine(); - final var response = bindResponse(requestFirstLine); - outputStream.write(response.getBytes()); + final String requestFirstLine = bufferedReader.readLine(); + if (GET_METHOD.equals(requestFirstLine.split(" ")[0])) { + final var response = bindResponse(requestFirstLine); + outputStream.write(response.getBytes()); + } outputStream.flush(); } catch (IOException | UncheckedServletException e) { log.error(e.getMessage(), e); @@ -50,24 +50,20 @@ public void process(final Socket connection) { } private String bindResponse(String requestFirstLine) throws IOException { - String httpMethod = requestFirstLine.split(" ")[0]; String route = requestFirstLine.split(" ")[1]; - - if (DEFAULT_ROUTE.equals(route) && GET_METHOD.equals(httpMethod)) { + if (DEFAULT_ROUTE.equals(route)) { return buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); } - if (HOME_PAGE_ROUTE.equals(route) && GET_METHOD.equals(httpMethod)) { - URL resource = getClass().getClassLoader().getResource(HOME_PAGE_RESPONSE_BODY); - if (resource == null) { - throw new InternalError("기본으로 보여줄 파일을 찾을 수 없습니다."); - } - String body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - return buildSuccessfulResponse(body); + URL resource = getClass().getClassLoader().getResource("static" + route); + if (resource == null) { + URL badRequestURL = getClass().getClassLoader().getResource("static/404.html"); + return buildFailedResponse(404, "NotFound", + new String(Files.readAllBytes(new File(badRequestURL.getFile()).toPath()))); } - return buildFailedResponse(404, "NotFound", - "There is no static resource matched with rout and method"); + String body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + return buildSuccessfulResponse(body); } private String buildSuccessfulResponse(String responseBody) { From f516d89eb7efc64647ddd9362b5ceaa2fd205b05 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 00:23:21 +0900 Subject: [PATCH 12/62] =?UTF-8?q?refactor:=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B0=9D=EC=B2=B4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/ResponseBinder.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java b/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java new file mode 100644 index 0000000000..54ee1efef2 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java @@ -0,0 +1,26 @@ +package org.apache.coyote.http11; + +class ResponseBinder { + + String buildSuccessfulResponse(String responseBody) { + return this.buildSuccessfulResponse("text/html", responseBody); + } + + String buildSuccessfulResponse(String contentType, String responseBody) { + return String.join("\r\n", + "HTTP/1.1 200 OK ", + "Content-Type: " + contentType + ";charset=utf-8 ", + "Content-Length: " + responseBody.getBytes().length + " ", + "", + responseBody); + } + + String buildFailedResponse(int statusCode, String statusMessage, String responseBody) { + return String.join("\r\n", + "HTTP/1.1 " + statusCode + " " + statusMessage, + "Content-Type: text/html;charset=utf-8 ", + "Content-Length: " + responseBody.getBytes().length + " ", + "", + responseBody); + } +} From 4a3a161a74d3c17c5665fb62afada74545f6575b Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 00:23:49 +0900 Subject: [PATCH 13/62] =?UTF-8?q?refactor:=20=EB=B6=84=EB=A6=AC=ED=95=9C?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=EC=9D=98=20=ED=95=A8=EC=88=98=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 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 bc65abf096..9167e66985 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -20,6 +20,8 @@ public class Http11Processor implements Runnable, Processor { private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; private final Socket connection; + private final ContentTypeConverter contentTypeConverter = new ContentTypeConverter(); + private final ResponseBinder responseBinder = new ResponseBinder(); public Http11Processor(final Socket connection) { this.connection = connection; @@ -37,8 +39,8 @@ public void process(final Socket connection) { final var outputStream = connection.getOutputStream()) { final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - final String requestFirstLine = bufferedReader.readLine(); + if (GET_METHOD.equals(requestFirstLine.split(" ")[0])) { final var response = bindResponse(requestFirstLine); outputStream.write(response.getBytes()); @@ -52,35 +54,22 @@ public void process(final Socket connection) { private String bindResponse(String requestFirstLine) throws IOException { String route = requestFirstLine.split(" ")[1]; if (DEFAULT_ROUTE.equals(route)) { - return buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); + return responseBinder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); } URL resource = getClass().getClassLoader().getResource("static" + route); if (resource == null) { URL badRequestURL = getClass().getClassLoader().getResource("static/404.html"); - return buildFailedResponse(404, "NotFound", + return responseBinder.buildFailedResponse(404, "NotFound", new String(Files.readAllBytes(new File(badRequestURL.getFile()).toPath()))); } - String body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - return buildSuccessfulResponse(body); - } - - private String buildSuccessfulResponse(String responseBody) { - return String.join("\r\n", - "HTTP/1.1 200 OK ", - "Content-Type: text/html;charset=utf-8 ", - "Content-Length: " + responseBody.getBytes().length + " ", - "", - responseBody); - } - - private String buildFailedResponse(int statusCode, String statusMessage, String responseBody) { - return String.join("\r\n", - "HTTP/1.1 " + statusCode + " " + statusMessage, - "Content-Type: text/html;charset=utf-8 ", - "Content-Length: " + responseBody.getBytes().length + " ", - "", - responseBody); + String staticResource = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + if (route.split("[.]").length == 0) { + return responseBinder.buildSuccessfulResponse(staticResource); + } + String fileExtension = route.split("[.]")[1]; + String contentType = contentTypeConverter.mapToContentType(fileExtension); + return responseBinder.buildSuccessfulResponse(contentType, staticResource); } } From cbc1b3817868c454933b8d1a2c3a7e9f4b6c9697 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 16:16:28 +0900 Subject: [PATCH 14/62] =?UTF-8?q?refactor:=20=EA=B2=BD=EB=A1=9C=EC=99=80?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A7=81=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 18 ++++++++++-------- 1 file changed, 10 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 9167e66985..dafd7b41b2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -40,9 +40,12 @@ public void process(final Socket connection) { final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); final String requestFirstLine = bufferedReader.readLine(); + final String[] requestFirstLine = bufferedReader.readLine().split(" "); + final String httpMethod = requestFirstLine[0]; + final String path = requestFirstLine[1].split("[?]")[0]; - if (GET_METHOD.equals(requestFirstLine.split(" ")[0])) { - final var response = bindResponse(requestFirstLine); + if (GET_METHOD.equals(httpMethod)) { + final var response = bindResponse(path); outputStream.write(response.getBytes()); } outputStream.flush(); @@ -51,13 +54,12 @@ public void process(final Socket connection) { } } - private String bindResponse(String requestFirstLine) throws IOException { - String route = requestFirstLine.split(" ")[1]; - if (DEFAULT_ROUTE.equals(route)) { + private String bindResponse(String path) throws IOException { + if (DEFAULT_ROUTE.equals(path)) { return responseBinder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); } - URL resource = getClass().getClassLoader().getResource("static" + route); + URL resource = getClass().getClassLoader().getResource("static" + path); if (resource == null) { URL badRequestURL = getClass().getClassLoader().getResource("static/404.html"); return responseBinder.buildFailedResponse(404, "NotFound", @@ -65,10 +67,10 @@ private String bindResponse(String requestFirstLine) throws IOException { } String staticResource = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - if (route.split("[.]").length == 0) { + if (path.split("[.]").length == 0) { return responseBinder.buildSuccessfulResponse(staticResource); } - String fileExtension = route.split("[.]")[1]; + String fileExtension = path.split("[.]")[1]; String contentType = contentTypeConverter.mapToContentType(fileExtension); return responseBinder.buildSuccessfulResponse(contentType, staticResource); } From 9bac8268c5e54a3383ba6d1ca5bf84c1f499b2b1 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 18:19:30 +0900 Subject: [PATCH 15/62] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=B0=98=ED=99=98=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=84=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/ViewResolver.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java new file mode 100644 index 0000000000..60ef242f37 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java @@ -0,0 +1,59 @@ +package org.apache.coyote.http11; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; + +class ViewResolver { + + private static final String GET_METHOD = "GET"; + private static final String DEFAULT_ROUTE = "/"; + private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; + + private final ResponseBinder responseBinder = new ResponseBinder(); + private final ContentTypeConverter contentTypeConverter = new ContentTypeConverter(); + + String handle(HttpRequest request) throws IOException { + if (GET_METHOD.equals(request.getHttpMethod())) { + return handleGetRequest(request.getPath()); + } + + return responseBinder.buildNotFoundResponse(); + } + + private String handleGetRequest(String path) throws IOException { + if (DEFAULT_ROUTE.equals(path)) { + return responseBinder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); + } + + URL resource = getClass().getClassLoader().getResource("static" + path); + if (resource == null) { + if (path.split("[.]").length == 0) { + return handleNoFileExtensionRequest(path); + } + return responseBinder.buildNotFoundResponse(); + } + + return handleFileExtensionRequest(path, resource); + } + + private String handleNoFileExtensionRequest(String path) throws IOException { + path += ".html"; + URL staticResourceUrl = getClass().getClassLoader().getResource("static" + path); + if (staticResourceUrl == null) { + return responseBinder.buildNotFoundResponse(); + } + + return responseBinder.buildSuccessfulResponse( + new String(Files.readAllBytes(new File(staticResourceUrl.getFile()).toPath()))); + } + + private String handleFileExtensionRequest(String path, URL resource) throws IOException { + String staticResource = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + String fileExtension = path.split("[.]")[1]; + String contentType = contentTypeConverter.mapToContentType(fileExtension); + + return responseBinder.buildSuccessfulResponse(contentType, staticResource); + } +} From 6b399e679611efdfaa76f7038649e59eb6570f4c Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 18:22:04 +0900 Subject: [PATCH 16/62] =?UTF-8?q?refactor:=20NotFound=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=EB=A1=9C=EC=A7=81=EC=9D=84=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/ResponseBinder.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java b/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java index 54ee1efef2..55822123ea 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java @@ -1,5 +1,10 @@ package org.apache.coyote.http11; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; + class ResponseBinder { String buildSuccessfulResponse(String responseBody) { @@ -15,9 +20,12 @@ String buildSuccessfulResponse(String contentType, String responseBody) { responseBody); } - String buildFailedResponse(int statusCode, String statusMessage, String responseBody) { + String buildNotFoundResponse() throws IOException { + URL badRequestURL = getClass().getClassLoader().getResource("static/404.html"); + String responseBody = new String(Files.readAllBytes(new File(badRequestURL.getFile()).toPath())); + return String.join("\r\n", - "HTTP/1.1 " + statusCode + " " + statusMessage, + "HTTP/1.1 404 NOT_FOUND ", "Content-Type: text/html;charset=utf-8 ", "Content-Length: " + responseBody.getBytes().length + " ", "", From 8aa1d61ce3404351274cb17712c21accd313a645 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 18:22:31 +0900 Subject: [PATCH 17/62] =?UTF-8?q?feat:=20HTTP=20Request=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/HttpRequest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java new file mode 100644 index 0000000000..f9947651e8 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -0,0 +1,43 @@ +package org.apache.coyote.http11; + +import java.util.HashMap; +import java.util.Map; + +class HttpRequest { + + private final String httpMethod; + private final String path; + private final Map queryString; + private final String body; + + public HttpRequest(String request) { + String[] firstLineArgs = request.split(System.lineSeparator())[0].split(" "); + this.httpMethod = firstLineArgs[0]; + this.path = firstLineArgs[1].split("[?]")[0]; + + Map map = new HashMap<>(); + String[] queryStringArgs = firstLineArgs[1].split("[?]")[1].split("[&=]"); + for (int i = 0; i < queryStringArgs.length; i++) { + map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); + } + this.queryString = map; + + this.body = request.split(System.lineSeparator() + System.lineSeparator())[1]; + } + + public String getHttpMethod() { + return this.httpMethod; + } + + public String getPath() { + return this.path; + } + + public String getQueryStringValue(String key) { + return this.queryString.get(key); + } + + public String getBody() { + return this.body; + } +} From 3350344f99656c5ee916a54b43bade0ae13f4560 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 18:23:37 +0900 Subject: [PATCH 18/62] =?UTF-8?q?feat:=20=EC=A0=95=EC=A0=81=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9A=94=EC=B2=AD=EC=9D=B8=EC=A7=80=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84=ED=95=98=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/http11/HandlerMapper.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java b/tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java new file mode 100644 index 0000000000..40668c636e --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java @@ -0,0 +1,12 @@ +package org.apache.coyote.http11; + +import java.util.List; + +class HandlerMapper { + + private static final List nonStaticPaths = List.of("/login"); + + public static boolean isNonStaticRequest(String path) { + return nonStaticPaths.contains(path); + } +} From eed525f6b287f7e01171a0f6dfbc7ff3b635518f Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 18:25:37 +0900 Subject: [PATCH 19/62] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EA=B0=80=EB=8F=85=EC=84=B1=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 59 ++++++++----------- .../coyote/http11/Http11ProcessorTest.java | 4 +- 2 files changed, 28 insertions(+), 35 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 dafd7b41b2..942a2bea78 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,13 +1,13 @@ package org.apache.coyote.http11; +import static org.apache.coyote.http11.HandlerMapper.isNonStaticRequest; + import com.techcourse.exception.UncheckedServletException; 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 org.apache.coyote.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,13 +15,9 @@ public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); - private static final String GET_METHOD = "GET"; - private static final String DEFAULT_ROUTE = "/"; - private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; private final Socket connection; - private final ContentTypeConverter contentTypeConverter = new ContentTypeConverter(); - private final ResponseBinder responseBinder = new ResponseBinder(); + private final ViewResolver viewResolver = new ViewResolver(); public Http11Processor(final Socket connection) { this.connection = connection; @@ -37,41 +33,38 @@ public void run() { public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); - final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - final String requestFirstLine = bufferedReader.readLine(); - final String[] requestFirstLine = bufferedReader.readLine().split(" "); - final String httpMethod = requestFirstLine[0]; - final String path = requestFirstLine[1].split("[?]")[0]; - if (GET_METHOD.equals(httpMethod)) { - final var response = bindResponse(path); - outputStream.write(response.getBytes()); - } + String request = receiveRequest(inputStream); + String response = getResponse(request); + + outputStream.write(response.getBytes()); outputStream.flush(); } catch (IOException | UncheckedServletException e) { log.error(e.getMessage(), e); } } - private String bindResponse(String path) throws IOException { - if (DEFAULT_ROUTE.equals(path)) { - return responseBinder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); - } + private static String receiveRequest(InputStream inputStream) throws IOException { + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - URL resource = getClass().getClassLoader().getResource("static" + path); - if (resource == null) { - URL badRequestURL = getClass().getClassLoader().getResource("static/404.html"); - return responseBinder.buildFailedResponse(404, "NotFound", - new String(Files.readAllBytes(new File(badRequestURL.getFile()).toPath()))); + StringBuilder sb = new StringBuilder(); + while(true) { + String input = bufferedReader.readLine(); + if(input == null) { + break; + } + sb.append(input).append(System.lineSeparator()); } + return sb.toString(); + } - String staticResource = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - if (path.split("[.]").length == 0) { - return responseBinder.buildSuccessfulResponse(staticResource); + private String getResponse(String request) throws IOException { + String response = ""; + HttpRequest httpRequest = new HttpRequest(request); + if (!isNonStaticRequest(httpRequest.getPath())) { + response = viewResolver.handle(httpRequest); } - String fileExtension = path.split("[.]")[1]; - String contentType = contentTypeConverter.mapToContentType(fileExtension); - return responseBinder.buildSuccessfulResponse(contentType, staticResource); + return response; } } diff --git a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java index e71808ba26..803cbc7db1 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -107,8 +107,8 @@ void failedResponse() { processor.process(socket); // then - var expected = "HTTP/1.1 404 NotFound\r\n" + - "Content-Type: text/html;charset=utf-8"; + var expected = "HTTP/1.1 404 NOT_FOUND \r\n" + + "Content-Type: text/html;charset=utf-8"; assertThat(socket.output()).startsWith(expected); } From 6ae13d5133bebcbecc60ac03501dd4e6268226a6 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 21:13:20 +0900 Subject: [PATCH 20/62] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/HttpRequest.java | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index f9947651e8..9e14104550 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -13,16 +13,37 @@ class HttpRequest { public HttpRequest(String request) { String[] firstLineArgs = request.split(System.lineSeparator())[0].split(" "); this.httpMethod = firstLineArgs[0]; - this.path = firstLineArgs[1].split("[?]")[0]; + this.path = initializePath(firstLineArgs[1]); + this.queryString = initializeQueryString(firstLineArgs[1]); + this.body = initializeBody(request); + } + + private String initializePath(String url) { + if (url.contains("?")) { + return url.split("[?]")[0]; + } + return url; + } + private Map initializeQueryString(String url) { Map map = new HashMap<>(); - String[] queryStringArgs = firstLineArgs[1].split("[?]")[1].split("[&=]"); - for (int i = 0; i < queryStringArgs.length; i++) { - map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); + if (url.contains("?")) { + String[] queryStringArgs = url.split("[?]")[1].split("[&=]"); + for (int i = 0; i < queryStringArgs.length; i++) { + map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); + } + } + + return map; + } + + private String initializeBody(String request) { + String[] requests = request.split(System.lineSeparator() + System.lineSeparator()); + if (requests.length == 2) { + return requests[1]; } - this.queryString = map; - this.body = request.split(System.lineSeparator() + System.lineSeparator())[1]; + return null; } public String getHttpMethod() { From 29674ba57fae01d0486de1b60608835ede541965 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:26:53 +0900 Subject: [PATCH 21/62] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HandlerMapping.java} | 4 ++-- .../ContentTypeConverter.java | 2 +- .../ResponseBuilder.java} | 4 ++-- .../coyote/{http11 => view}/ViewResolver.java | 19 ++++++++++--------- 4 files changed, 15 insertions(+), 14 deletions(-) rename tomcat/src/main/java/org/apache/coyote/{http11/HandlerMapper.java => handler/HandlerMapping.java} (76%) rename tomcat/src/main/java/org/apache/coyote/{http11 => view}/ContentTypeConverter.java (92%) rename tomcat/src/main/java/org/apache/coyote/{http11/ResponseBinder.java => view/ResponseBuilder.java} (95%) rename tomcat/src/main/java/org/apache/coyote/{http11 => view}/ViewResolver.java (74%) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java similarity index 76% rename from tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java rename to tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index 40668c636e..83863b21d3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HandlerMapper.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -1,8 +1,8 @@ -package org.apache.coyote.http11; +package org.apache.coyote.handler; import java.util.List; -class HandlerMapper { +public class HandlerMapping { private static final List nonStaticPaths = List.of("/login"); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java b/tomcat/src/main/java/org/apache/coyote/view/ContentTypeConverter.java similarity index 92% rename from tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java rename to tomcat/src/main/java/org/apache/coyote/view/ContentTypeConverter.java index 9af458be9b..789cd7cc3d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/ContentTypeConverter.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ContentTypeConverter.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.view; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java b/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java similarity index 95% rename from tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java rename to tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java index 55822123ea..ef6ca524b9 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/ResponseBinder.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java @@ -1,11 +1,11 @@ -package org.apache.coyote.http11; +package org.apache.coyote.view; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.file.Files; -class ResponseBinder { +class ResponseBuilder { String buildSuccessfulResponse(String responseBody) { return this.buildSuccessfulResponse("text/html", responseBody); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java similarity index 74% rename from tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java rename to tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java index 60ef242f37..cbbbd60938 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/ViewResolver.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java @@ -1,17 +1,18 @@ -package org.apache.coyote.http11; +package org.apache.coyote.view; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.file.Files; +import org.apache.coyote.http11.HttpRequest; -class ViewResolver { +public class ViewResolver { private static final String GET_METHOD = "GET"; private static final String DEFAULT_ROUTE = "/"; private static final String DEFAULT_RESPONSE_BODY = "Hello world!"; - private final ResponseBinder responseBinder = new ResponseBinder(); + private final ResponseBuilder responseBuilder = new ResponseBuilder(); private final ContentTypeConverter contentTypeConverter = new ContentTypeConverter(); String handle(HttpRequest request) throws IOException { @@ -19,12 +20,12 @@ String handle(HttpRequest request) throws IOException { return handleGetRequest(request.getPath()); } - return responseBinder.buildNotFoundResponse(); + return responseBuilder.buildNotFoundResponse(); } private String handleGetRequest(String path) throws IOException { if (DEFAULT_ROUTE.equals(path)) { - return responseBinder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); + return responseBuilder.buildSuccessfulResponse(DEFAULT_RESPONSE_BODY); } URL resource = getClass().getClassLoader().getResource("static" + path); @@ -32,7 +33,7 @@ private String handleGetRequest(String path) throws IOException { if (path.split("[.]").length == 0) { return handleNoFileExtensionRequest(path); } - return responseBinder.buildNotFoundResponse(); + return responseBuilder.buildNotFoundResponse(); } return handleFileExtensionRequest(path, resource); @@ -42,10 +43,10 @@ private String handleNoFileExtensionRequest(String path) throws IOException { path += ".html"; URL staticResourceUrl = getClass().getClassLoader().getResource("static" + path); if (staticResourceUrl == null) { - return responseBinder.buildNotFoundResponse(); + return responseBuilder.buildNotFoundResponse(); } - return responseBinder.buildSuccessfulResponse( + return responseBuilder.buildSuccessfulResponse( new String(Files.readAllBytes(new File(staticResourceUrl.getFile()).toPath()))); } @@ -54,6 +55,6 @@ private String handleFileExtensionRequest(String path, URL resource) throws IOEx String fileExtension = path.split("[.]")[1]; String contentType = contentTypeConverter.mapToContentType(fileExtension); - return responseBinder.buildSuccessfulResponse(contentType, staticResource); + return responseBuilder.buildSuccessfulResponse(contentType, staticResource); } } From 02f203b449ebe29f6d6c7c6ce901b91f51542574 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:27:36 +0900 Subject: [PATCH 22/62] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/apache/coyote/view/ViewResolver.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java index cbbbd60938..28b6912bc9 100644 --- a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java @@ -15,7 +15,11 @@ public class ViewResolver { private final ResponseBuilder responseBuilder = new ResponseBuilder(); private final ContentTypeConverter contentTypeConverter = new ContentTypeConverter(); - String handle(HttpRequest request) throws IOException { + public String resolve(String view) throws IOException { + return handleGetRequest(view); + } + + public String resolve(HttpRequest request) throws IOException { if (GET_METHOD.equals(request.getHttpMethod())) { return handleGetRequest(request.getPath()); } From 77a5bc0719cdb3fb7a629502a2e9954145dec5e3 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:28:07 +0900 Subject: [PATCH 23/62] =?UTF-8?q?feat:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EC=B6=94=EC=83=81=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/controller/Controller.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/controller/Controller.java diff --git a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java new file mode 100644 index 0000000000..2656301fde --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java @@ -0,0 +1,9 @@ +package org.apache.coyote.controller; + +import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.view.ModelAndView; + +public abstract class Controller { + + public abstract ModelAndView process(HttpRequest request); +} From 7de1c2769fb572e1c12bd8cc3e0c6d2b40b47c9f Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:28:26 +0900 Subject: [PATCH 24/62] =?UTF-8?q?feat:=20=EC=9A=94=EC=B2=AD=EC=97=90=20?= =?UTF-8?q?=EB=A7=A4=EC=B9=AD=EB=90=98=EB=8A=94=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EB=B0=98=ED=99=98=20=EB=A1=9C=EC=A7=81=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 --- .../coyote/controller/RequestMapping.java | 31 +++++++++++++++++++ .../apache/coyote/handler/HandlerMapping.java | 15 ++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java b/tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java new file mode 100644 index 0000000000..9ef88eb947 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java @@ -0,0 +1,31 @@ +package org.apache.coyote.controller; + +import java.util.Objects; + +public class RequestMapping { + + private final String httpMethod; + private final String path; + + public RequestMapping(String httpMethod, String path) { + this.httpMethod = httpMethod; + this.path = path; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RequestMapping that = (RequestMapping) o; + return Objects.equals(httpMethod, that.httpMethod) && Objects.equals(path, that.path); + } + + @Override + public int hashCode() { + return Objects.hash(httpMethod, path); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index 83863b21d3..d15685a202 100644 --- a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -1,12 +1,19 @@ package org.apache.coyote.handler; -import java.util.List; +import java.util.Map; +import org.apache.coyote.controller.Controller; +import org.apache.coyote.controller.LogInController; +import org.apache.coyote.controller.RequestMapping; +import org.apache.coyote.http11.HttpRequest; public class HandlerMapping { - private static final List nonStaticPaths = List.of("/login"); + private static final Map HANDLER_MAPPER = Map.of( + new RequestMapping("GET", "/login"), new LogInController() + ); - public static boolean isNonStaticRequest(String path) { - return nonStaticPaths.contains(path); + public Controller getController(HttpRequest request) { + return HANDLER_MAPPER.get( + new RequestMapping(request.getHttpMethod(), request.getPath())); } } From bd62ae07a77ced65f748df88c5a204c9531a33bb Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:28:46 +0900 Subject: [PATCH 25/62] =?UTF-8?q?feat:=20ModelAndView=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/view/ModelAndView.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java diff --git a/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java b/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java new file mode 100644 index 0000000000..4b19eaf522 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java @@ -0,0 +1,22 @@ +package org.apache.coyote.view; + +import java.util.Map; + +public class ModelAndView { + + private final String view; + private final Map model; + + public ModelAndView(String view, Map model) { + this.view = view; + this.model = model; + } + + public String getView() { + return view; + } + + public Map getAttributes() { + return this.model; + } +} From 567a5f500d9e6e4a570ad60cb6fea74e6ce3d799 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:28:59 +0900 Subject: [PATCH 26/62] =?UTF-8?q?feat:=20LogInController=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/controller/LogInController.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/controller/LogInController.java diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java new file mode 100644 index 0000000000..9f1e8e8d47 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -0,0 +1,23 @@ +package org.apache.coyote.controller; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; +import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.view.ModelAndView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogInController extends Controller { + + private static final Logger log = LoggerFactory.getLogger(LogInController.class); + + @Override + public ModelAndView process(HttpRequest request) { + String account = request.getQueryStringValue("account"); + User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(IllegalArgumentException::new); + log.info("user : {}", user); + + return new ModelAndView("login", null); + } +} From 963618347adc5b423f81869f094f70e2687740f6 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:29:26 +0900 Subject: [PATCH 27/62] =?UTF-8?q?refactor:=20=EC=BB=A8=ED=8B=80=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EB=A7=A4=ED=95=91=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 26 +++++++++++-------- 1 file changed, 15 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 942a2bea78..1a6e3a3a0a 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,5 @@ package org.apache.coyote.http11; -import static org.apache.coyote.http11.HandlerMapper.isNonStaticRequest; - import com.techcourse.exception.UncheckedServletException; import java.io.BufferedReader; import java.io.IOException; @@ -9,6 +7,10 @@ import java.io.InputStreamReader; import java.net.Socket; import org.apache.coyote.Processor; +import org.apache.coyote.controller.Controller; +import org.apache.coyote.handler.HandlerMapping; +import org.apache.coyote.view.ModelAndView; +import org.apache.coyote.view.ViewResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +19,7 @@ public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; + private final HandlerMapping handlerMapping = new HandlerMapping(); private final ViewResolver viewResolver = new ViewResolver(); public Http11Processor(final Socket connection) { @@ -34,7 +37,7 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - String request = receiveRequest(inputStream); + HttpRequest request = receiveRequest(inputStream); String response = getResponse(request); outputStream.write(response.getBytes()); @@ -44,7 +47,7 @@ public void process(final Socket connection) { } } - private static String receiveRequest(InputStream inputStream) throws IOException { + private HttpRequest receiveRequest(InputStream inputStream) throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); @@ -56,15 +59,16 @@ private static String receiveRequest(InputStream inputStream) throws IOException } sb.append(input).append(System.lineSeparator()); } - return sb.toString(); + return new HttpRequest(sb.toString()); } - private String getResponse(String request) throws IOException { - String response = ""; - HttpRequest httpRequest = new HttpRequest(request); - if (!isNonStaticRequest(httpRequest.getPath())) { - response = viewResolver.handle(httpRequest); + private String getResponse(HttpRequest request) throws IOException { + Controller controller = handlerMapping.getController(request); + if (controller != null) { + ModelAndView modelAndView = controller.process(request); + return viewResolver.resolve(modelAndView.getView()); } - return response; + + return viewResolver.resolve(request); } } From e92226c01e27cf3634802b6ed07695b861d06860 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:29:39 +0900 Subject: [PATCH 28/62] =?UTF-8?q?style:=20=EA=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index 9e14104550..6d86f3d390 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -3,7 +3,7 @@ import java.util.HashMap; import java.util.Map; -class HttpRequest { +public class HttpRequest { private final String httpMethod; private final String path; @@ -22,6 +22,7 @@ private String initializePath(String url) { if (url.contains("?")) { return url.split("[?]")[0]; } + return url; } From 1c9c044a9be746db7a3e182ffb904df00db50fc0 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Thu, 5 Sep 2024 22:45:38 +0900 Subject: [PATCH 29/62] =?UTF-8?q?fix:=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/apache/coyote/controller/LogInController.java | 2 +- tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java | 2 +- tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index 9f1e8e8d47..392b3b03ec 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -18,6 +18,6 @@ public ModelAndView process(HttpRequest request) { .orElseThrow(IllegalArgumentException::new); log.info("user : {}", user); - return new ModelAndView("login", null); + return new ModelAndView("/login", null); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index 6d86f3d390..bab52bc028 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -30,7 +30,7 @@ private Map initializeQueryString(String url) { Map map = new HashMap<>(); if (url.contains("?")) { String[] queryStringArgs = url.split("[?]")[1].split("[&=]"); - for (int i = 0; i < queryStringArgs.length; i++) { + for (int i = 0; i < queryStringArgs.length / 2; i++) { map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java index 28b6912bc9..3eb2c859b9 100644 --- a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java @@ -34,7 +34,7 @@ private String handleGetRequest(String path) throws IOException { URL resource = getClass().getClassLoader().getResource("static" + path); if (resource == null) { - if (path.split("[.]").length == 0) { + if (path.split("[.]").length == 1) { return handleNoFileExtensionRequest(path); } return responseBuilder.buildNotFoundResponse(); From 50c7e60d20ca7d8b5b19393d164bb59e59fb841f Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:01:23 +0900 Subject: [PATCH 30/62] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/controller/Controller.java | 4 +- .../coyote/controller/LogInController.java | 4 +- .../apache/coyote/handler/HandlerMapping.java | 4 +- .../coyote/http11/HttpRequestHeader.java | 67 +++++++++++++++++++ .../org/apache/coyote/view/ViewResolver.java | 4 +- 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java diff --git a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java index 2656301fde..cc70c0c0bf 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java @@ -1,9 +1,9 @@ package org.apache.coyote.controller; -import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.http11.HttpRequestHeader; import org.apache.coyote.view.ModelAndView; public abstract class Controller { - public abstract ModelAndView process(HttpRequest request); + public abstract ModelAndView process(HttpRequestHeader request); } diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index 392b3b03ec..471a58499e 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -2,7 +2,7 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; -import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.http11.HttpRequestHeader; import org.apache.coyote.view.ModelAndView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,7 +12,7 @@ public class LogInController extends Controller { private static final Logger log = LoggerFactory.getLogger(LogInController.class); @Override - public ModelAndView process(HttpRequest request) { + public ModelAndView process(HttpRequestHeader request) { String account = request.getQueryStringValue("account"); User user = InMemoryUserRepository.findByAccount(account) .orElseThrow(IllegalArgumentException::new); diff --git a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index d15685a202..bf08cb10dd 100644 --- a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -4,7 +4,7 @@ import org.apache.coyote.controller.Controller; import org.apache.coyote.controller.LogInController; import org.apache.coyote.controller.RequestMapping; -import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.http11.HttpRequestHeader; public class HandlerMapping { @@ -12,7 +12,7 @@ public class HandlerMapping { new RequestMapping("GET", "/login"), new LogInController() ); - public Controller getController(HttpRequest request) { + public Controller getController(HttpRequestHeader request) { return HANDLER_MAPPER.get( new RequestMapping(request.getHttpMethod(), request.getPath())); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java new file mode 100644 index 0000000000..e2a52f013b --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -0,0 +1,67 @@ +package org.apache.coyote.http11; + +import java.util.HashMap; +import java.util.Map; + +public class HttpRequestHeader { + + private final String httpMethod; + private final String path; + private final Map queryString; + private final Map headers; + + public HttpRequestHeader(String requestHeader) { + String[] firstLineArgs = requestHeader.split(System.lineSeparator())[0].split(" "); + this.httpMethod = firstLineArgs[0]; + this.path = initializePath(firstLineArgs[1]); + this.queryString = initializeQueryString(firstLineArgs[1]); + this.headers = initializeHeaders(requestHeader); + } + + private String initializePath(String url) { + if (url.contains("?")) { + return url.split("[?]")[0]; + } + + return url; + } + + private Map initializeQueryString(String url) { + Map map = new HashMap<>(); + if (url.contains("?")) { + String[] queryStringArgs = url.split("[?]")[1].split("[&=]"); + for (int i = 0; i < queryStringArgs.length / 2; i++) { + map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); + } + } + + return map; + } + + private Map initializeHeaders(String requestHeader) { + Map map = new HashMap<>(); + String[] lines = requestHeader.split(System.lineSeparator()); + for (int i = 1; i < lines.length; i++) { + String[] headerArgs = lines[i].split(": "); + map.put(headerArgs[0], headerArgs[1]); + } + + return map; + } + + public String getHttpMethod() { + return this.httpMethod; + } + + public String getPath() { + return this.path; + } + + public String getQueryStringValue(String key) { + return this.queryString.get(key); + } + + public String getHeader(String key) { + return headers.get(key); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java index 3eb2c859b9..a61c25f615 100644 --- a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java @@ -4,7 +4,7 @@ import java.io.IOException; import java.net.URL; import java.nio.file.Files; -import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.http11.HttpRequestHeader; public class ViewResolver { @@ -19,7 +19,7 @@ public String resolve(String view) throws IOException { return handleGetRequest(view); } - public String resolve(HttpRequest request) throws IOException { + public String resolve(HttpRequestHeader request) throws IOException { if (GET_METHOD.equals(request.getHttpMethod())) { return handleGetRequest(request.getPath()); } From 2389c2b01b03b23cb6e31038ce21e857ef3cc738 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:02:07 +0900 Subject: [PATCH 31/62] =?UTF-8?q?refactor:=20Http=20Request,=20Body=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 24 ++----- .../org/apache/coyote/http11/HttpRequest.java | 63 +++---------------- .../apache/coyote/http11/HttpRequestBody.java | 14 +++++ .../coyote/http11/HttpRequestReceiver.java | 43 +++++++++++++ 4 files changed, 72 insertions(+), 72 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.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 1a6e3a3a0a..ad3abbe8c8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,10 +1,8 @@ package org.apache.coyote.http11; import com.techcourse.exception.UncheckedServletException; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.Socket; import org.apache.coyote.Processor; import org.apache.coyote.controller.Controller; @@ -43,32 +41,22 @@ public void process(final Socket connection) { outputStream.write(response.getBytes()); outputStream.flush(); } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); + log.error(e.getMessage(), e, this); } } private HttpRequest receiveRequest(InputStream inputStream) throws IOException { - InputStreamReader inputStreamReader = new InputStreamReader(inputStream); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - - StringBuilder sb = new StringBuilder(); - while(true) { - String input = bufferedReader.readLine(); - if(input == null) { - break; - } - sb.append(input).append(System.lineSeparator()); - } - return new HttpRequest(sb.toString()); + HttpRequestReceiver httpRequestReceiver = new HttpRequestReceiver(); + return httpRequestReceiver.receiveRequest(inputStream); } private String getResponse(HttpRequest request) throws IOException { - Controller controller = handlerMapping.getController(request); + Controller controller = handlerMapping.getController(request.getHeader()); if (controller != null) { - ModelAndView modelAndView = controller.process(request); + ModelAndView modelAndView = controller.process(request.getHeader()); return viewResolver.resolve(modelAndView.getView()); } - return viewResolver.resolve(request); + return viewResolver.resolve(request.getHeader()); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index bab52bc028..fc682f63e7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -1,65 +1,20 @@ package org.apache.coyote.http11; -import java.util.HashMap; -import java.util.Map; - public class HttpRequest { - private final String httpMethod; - private final String path; - private final Map queryString; - private final String body; - - public HttpRequest(String request) { - String[] firstLineArgs = request.split(System.lineSeparator())[0].split(" "); - this.httpMethod = firstLineArgs[0]; - this.path = initializePath(firstLineArgs[1]); - this.queryString = initializeQueryString(firstLineArgs[1]); - this.body = initializeBody(request); - } - - private String initializePath(String url) { - if (url.contains("?")) { - return url.split("[?]")[0]; - } - - return url; - } - - private Map initializeQueryString(String url) { - Map map = new HashMap<>(); - if (url.contains("?")) { - String[] queryStringArgs = url.split("[?]")[1].split("[&=]"); - for (int i = 0; i < queryStringArgs.length / 2; i++) { - map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); - } - } - - return map; - } - - private String initializeBody(String request) { - String[] requests = request.split(System.lineSeparator() + System.lineSeparator()); - if (requests.length == 2) { - return requests[1]; - } - - return null; - } - - public String getHttpMethod() { - return this.httpMethod; - } + private final HttpRequestHeader header; + private final HttpRequestBody body; - public String getPath() { - return this.path; + public HttpRequest(HttpRequestHeader header, HttpRequestBody body) { + this.header = header; + this.body = body; } - public String getQueryStringValue(String key) { - return this.queryString.get(key); + public HttpRequestHeader getHeader() { + return header; } - public String getBody() { - return this.body; + public HttpRequestBody getBody() { + return body; } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java new file mode 100644 index 0000000000..31b5d44c93 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java @@ -0,0 +1,14 @@ +package org.apache.coyote.http11; + +public class HttpRequestBody { + + private final String body; + + public HttpRequestBody(String body) { + this.body = body; + } + + public String getBody() { + return body; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java new file mode 100644 index 0000000000..795ddf8152 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java @@ -0,0 +1,43 @@ +package org.apache.coyote.http11; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class HttpRequestReceiver { + + HttpRequest receiveRequest(InputStream inputStream) throws IOException { + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + + HttpRequestHeader header = new HttpRequestHeader(receiveRequestLines(bufferedReader)); + HttpRequestBody body = null; + + int contentLength = Integer.parseInt(header.getHeader("content-length")); + + if ("POST".equals(header.getHttpMethod()) || "PUT".equals(header.getHttpMethod())) { + body = new HttpRequestBody(receiveRequestBody(bufferedReader, contentLength)); + } + + return new HttpRequest(header, body); + } + + private static String receiveRequestLines(BufferedReader bufferedReader) throws IOException { + StringBuilder sb = new StringBuilder(); + while (true) { + String input = bufferedReader.readLine(); + if (input == null || input.isBlank()) { + break; + } + sb.append(input).append(System.lineSeparator()); + } + return sb.toString(); + } + + private static String receiveRequestBody(BufferedReader bufferedReader, int contentLength) throws IOException { + char[] bodyChars = new char[contentLength]; + bufferedReader.read(bodyChars, 0, contentLength); + return new String(bodyChars); + } +} From 312eef2745fd84d71ea985484724c55ea3df71e6 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:10:52 +0900 Subject: [PATCH 32/62] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/{controller => handler}/RequestMapping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tomcat/src/main/java/org/apache/coyote/{controller => handler}/RequestMapping.java (94%) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/RequestMapping.java similarity index 94% rename from tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java rename to tomcat/src/main/java/org/apache/coyote/handler/RequestMapping.java index 9ef88eb947..03f66d0f97 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/RequestMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/RequestMapping.java @@ -1,4 +1,4 @@ -package org.apache.coyote.controller; +package org.apache.coyote.handler; import java.util.Objects; From 5de8074df95110618ff081f2d65ee5eb4b838845 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:12:03 +0900 Subject: [PATCH 33/62] =?UTF-8?q?refactor:=20RequestHeader=20=EA=B0=80=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EB=90=98=EB=8D=98=20=EA=B3=B3=EC=9D=84=20Req?= =?UTF-8?q?uest=20=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/apache/coyote/controller/Controller.java | 4 ++-- .../java/org/apache/coyote/controller/LogInController.java | 4 ++-- .../src/main/java/org/apache/coyote/http11/HttpRequest.java | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java index cc70c0c0bf..2656301fde 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java @@ -1,9 +1,9 @@ package org.apache.coyote.controller; -import org.apache.coyote.http11.HttpRequestHeader; +import org.apache.coyote.http11.HttpRequest; import org.apache.coyote.view.ModelAndView; public abstract class Controller { - public abstract ModelAndView process(HttpRequestHeader request); + public abstract ModelAndView process(HttpRequest request); } diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index 471a58499e..392b3b03ec 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -2,7 +2,7 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; -import org.apache.coyote.http11.HttpRequestHeader; +import org.apache.coyote.http11.HttpRequest; import org.apache.coyote.view.ModelAndView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,7 +12,7 @@ public class LogInController extends Controller { private static final Logger log = LoggerFactory.getLogger(LogInController.class); @Override - public ModelAndView process(HttpRequestHeader request) { + public ModelAndView process(HttpRequest request) { String account = request.getQueryStringValue("account"); User user = InMemoryUserRepository.findByAccount(account) .orElseThrow(IllegalArgumentException::new); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index fc682f63e7..46695cf56e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -17,4 +17,8 @@ public HttpRequestHeader getHeader() { public HttpRequestBody getBody() { return body; } + + public String getQueryStringValue(String key) { + return header.getQueryStringValue(key); + } } From f99e3b6a22f2fc2acc7a3b5cc81e1950f1182103 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:12:55 +0900 Subject: [PATCH 34/62] =?UTF-8?q?refactor:=20=EA=B0=80=EB=8F=85=EC=84=B1?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 개행, 함수 이름 변경, 필드 선언 --- .../org/apache/coyote/handler/HandlerMapping.java | 4 +--- .../org/apache/coyote/http11/Http11Processor.java | 11 +++-------- .../org/apache/coyote/http11/HttpRequestHeader.java | 4 ++++ .../org/apache/coyote/http11/HttpRequestReceiver.java | 9 ++++----- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index bf08cb10dd..6d19773ad1 100644 --- a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -3,7 +3,6 @@ import java.util.Map; import org.apache.coyote.controller.Controller; import org.apache.coyote.controller.LogInController; -import org.apache.coyote.controller.RequestMapping; import org.apache.coyote.http11.HttpRequestHeader; public class HandlerMapping { @@ -13,7 +12,6 @@ public class HandlerMapping { ); public Controller getController(HttpRequestHeader request) { - return HANDLER_MAPPER.get( - new RequestMapping(request.getHttpMethod(), request.getPath())); + return HANDLER_MAPPER.get(new RequestMapping(request.getHttpMethod(), request.getPath())); } } 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 ad3abbe8c8..1aa3f1d20e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -2,7 +2,6 @@ import com.techcourse.exception.UncheckedServletException; import java.io.IOException; -import java.io.InputStream; import java.net.Socket; import org.apache.coyote.Processor; import org.apache.coyote.controller.Controller; @@ -17,6 +16,7 @@ public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; + private final HttpRequestReceiver httpRequestReceiver = new HttpRequestReceiver(); private final HandlerMapping handlerMapping = new HandlerMapping(); private final ViewResolver viewResolver = new ViewResolver(); @@ -35,7 +35,7 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - HttpRequest request = receiveRequest(inputStream); + HttpRequest request = httpRequestReceiver.receiveRequest(inputStream); String response = getResponse(request); outputStream.write(response.getBytes()); @@ -45,15 +45,10 @@ public void process(final Socket connection) { } } - private HttpRequest receiveRequest(InputStream inputStream) throws IOException { - HttpRequestReceiver httpRequestReceiver = new HttpRequestReceiver(); - return httpRequestReceiver.receiveRequest(inputStream); - } - private String getResponse(HttpRequest request) throws IOException { Controller controller = handlerMapping.getController(request.getHeader()); if (controller != null) { - ModelAndView modelAndView = controller.process(request.getHeader()); + ModelAndView modelAndView = controller.process(request); return viewResolver.resolve(modelAndView.getView()); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index e2a52f013b..f887fa31dd 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -49,6 +49,10 @@ private Map initializeHeaders(String requestHeader) { return map; } + public int getContentLength() { + return Integer.parseInt(headers.get("Content-Length")); + } + public String getHttpMethod() { return this.httpMethod; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java index 795ddf8152..dba6e00eea 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java @@ -11,11 +11,10 @@ HttpRequest receiveRequest(InputStream inputStream) throws IOException { InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); - HttpRequestHeader header = new HttpRequestHeader(receiveRequestLines(bufferedReader)); - HttpRequestBody body = null; - - int contentLength = Integer.parseInt(header.getHeader("content-length")); + HttpRequestHeader header = new HttpRequestHeader(receiveRequestHeader(bufferedReader)); + int contentLength = header.getContentLength(); + HttpRequestBody body = null; if ("POST".equals(header.getHttpMethod()) || "PUT".equals(header.getHttpMethod())) { body = new HttpRequestBody(receiveRequestBody(bufferedReader, contentLength)); } @@ -23,7 +22,7 @@ HttpRequest receiveRequest(InputStream inputStream) throws IOException { return new HttpRequest(header, body); } - private static String receiveRequestLines(BufferedReader bufferedReader) throws IOException { + private static String receiveRequestHeader(BufferedReader bufferedReader) throws IOException { StringBuilder sb = new StringBuilder(); while (true) { String input = bufferedReader.readLine(); From 8114b4465e7f1e8ce57bcca497f37ceeba8366d4 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 01:43:14 +0900 Subject: [PATCH 35/62] =?UTF-8?q?refactor:=20=EA=B0=80=EB=8F=85=EC=84=B1?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EB=A0=88=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=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 | 4 +- .../org/apache/coyote/http11/HttpRequest.java | 18 +---- .../apache/coyote/http11/HttpRequestBody.java | 12 +-- .../coyote/http11/HttpRequestHeader.java | 74 +++++++++++-------- .../coyote/http11/HttpRequestReceiver.java | 2 +- 5 files changed, 48 insertions(+), 62 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 1aa3f1d20e..265e274d15 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -46,12 +46,12 @@ public void process(final Socket connection) { } private String getResponse(HttpRequest request) throws IOException { - Controller controller = handlerMapping.getController(request.getHeader()); + Controller controller = handlerMapping.getController(request.header()); if (controller != null) { ModelAndView modelAndView = controller.process(request); return viewResolver.resolve(modelAndView.getView()); } - return viewResolver.resolve(request.getHeader()); + return viewResolver.resolve(request.header()); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index 46695cf56e..773ba4d505 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -1,22 +1,6 @@ package org.apache.coyote.http11; -public class HttpRequest { - - private final HttpRequestHeader header; - private final HttpRequestBody body; - - public HttpRequest(HttpRequestHeader header, HttpRequestBody body) { - this.header = header; - this.body = body; - } - - public HttpRequestHeader getHeader() { - return header; - } - - public HttpRequestBody getBody() { - return body; - } +public record HttpRequest(HttpRequestHeader header, HttpRequestBody body) { public String getQueryStringValue(String key) { return header.getQueryStringValue(key); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java index 31b5d44c93..fa414193c9 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java @@ -1,14 +1,4 @@ package org.apache.coyote.http11; -public class HttpRequestBody { - - private final String body; - - public HttpRequestBody(String body) { - this.body = body; - } - - public String getBody() { - return body; - } +public record HttpRequestBody(String body) { } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index f887fa31dd..fc3e2b3e8b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -1,56 +1,68 @@ package org.apache.coyote.http11; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; -public class HttpRequestHeader { +public record HttpRequestHeader( + String httpMethod, + String path, + Map queryString, + Map headers) { - private final String httpMethod; - private final String path; - private final Map queryString; - private final Map headers; + public HttpRequestHeader(String request) { + this( + extractHttpMethod(request), + extractPath(request), + extractQueryString(request), + extractHeaders(request) + ); + } - public HttpRequestHeader(String requestHeader) { - String[] firstLineArgs = requestHeader.split(System.lineSeparator())[0].split(" "); - this.httpMethod = firstLineArgs[0]; - this.path = initializePath(firstLineArgs[1]); - this.queryString = initializeQueryString(firstLineArgs[1]); - this.headers = initializeHeaders(requestHeader); + private static String extractHttpMethod(String request) { + return request + .split(System.lineSeparator())[0] + .split(" ")[0]; } - private String initializePath(String url) { - if (url.contains("?")) { - return url.split("[?]")[0]; - } + private static String extractPath(String request) { + String url = request + .split(System.lineSeparator())[0] + .split(" ")[1]; - return url; + return url.split("[?]")[0]; } - private Map initializeQueryString(String url) { + private static Map extractQueryString(String request) { + String url = request + .split(System.lineSeparator())[0] + .split(" ")[1]; + Map map = new HashMap<>(); if (url.contains("?")) { - String[] queryStringArgs = url.split("[?]")[1].split("[&=]"); - for (int i = 0; i < queryStringArgs.length / 2; i++) { - map.put(queryStringArgs[i * 2], queryStringArgs[i * 2 + 1]); - } + String[] queryStringArgs = url + .split("[?]")[1] + .split("&"); + Arrays.stream(queryStringArgs) + .map(param -> param.split("=")) + .filter(parts -> parts.length == 2) + .forEach(parts -> map.put(parts[0], parts[1])); } - return map; } - private Map initializeHeaders(String requestHeader) { - Map map = new HashMap<>(); + private static Map extractHeaders(String requestHeader) { String[] lines = requestHeader.split(System.lineSeparator()); - for (int i = 1; i < lines.length; i++) { - String[] headerArgs = lines[i].split(": "); - map.put(headerArgs[0], headerArgs[1]); - } - - return map; + return Arrays.stream(lines) + .skip(1) + .map(line -> line.split(": ")) + .filter(parts -> parts.length == 2) + .collect(Collectors.toMap(parts -> parts[0], parts -> parts[1])); } public int getContentLength() { - return Integer.parseInt(headers.get("Content-Length")); + return Integer.parseInt(headers.get("content-length")); } public String getHttpMethod() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java index dba6e00eea..f3a3177d02 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java @@ -12,10 +12,10 @@ HttpRequest receiveRequest(InputStream inputStream) throws IOException { BufferedReader bufferedReader = new BufferedReader(inputStreamReader); HttpRequestHeader header = new HttpRequestHeader(receiveRequestHeader(bufferedReader)); - int contentLength = header.getContentLength(); HttpRequestBody body = null; if ("POST".equals(header.getHttpMethod()) || "PUT".equals(header.getHttpMethod())) { + int contentLength = header.getContentLength(); body = new HttpRequestBody(receiveRequestBody(bufferedReader, contentLength)); } From f2d713ab6a7dba4d02306c163a1fba345a83ca64 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 02:00:10 +0900 Subject: [PATCH 36/62] =?UTF-8?q?feat:=20=EA=B0=9D=EC=B2=B4=EC=97=90=20toM?= =?UTF-8?q?ap=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/java/com/techcourse/model/User.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tomcat/src/main/java/com/techcourse/model/User.java b/tomcat/src/main/java/com/techcourse/model/User.java index e8cf4c8e68..d83d4c3ddc 100644 --- a/tomcat/src/main/java/com/techcourse/model/User.java +++ b/tomcat/src/main/java/com/techcourse/model/User.java @@ -1,5 +1,7 @@ package com.techcourse.model; +import java.util.Map; + public class User { private final Long id; @@ -26,6 +28,13 @@ public String getAccount() { return account; } + public Map toMap() { + return Map.of( + "id", id, + "account", account, + "email", email); + } + @Override public String toString() { return "User{" + From 9155b05592913f687150a0c5a541d14b812f5468 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 02:01:27 +0900 Subject: [PATCH 37/62] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=EC=8B=9C=20401=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/techcourse/db/InMemoryUserRepository.java | 12 ++++++++++-- .../apache/coyote/controller/LogInController.java | 14 ++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java index d3fa57feeb..f74cb93c27 100644 --- a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java +++ b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java @@ -1,7 +1,6 @@ package com.techcourse.db; import com.techcourse.model.User; - import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -23,5 +22,14 @@ public static Optional findByAccount(String account) { return Optional.ofNullable(database.get(account)); } - private InMemoryUserRepository() {} + public static Optional findByAccountAndPassword(String account, String password) { + User user = database.get(account); + if (user != null && user.checkPassword(password)) { + return Optional.of(user); + } + return Optional.empty(); + } + + private InMemoryUserRepository() { + } } diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index 392b3b03ec..e6f4dcd728 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -2,6 +2,7 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; +import java.util.Optional; import org.apache.coyote.http11.HttpRequest; import org.apache.coyote.view.ModelAndView; import org.slf4j.Logger; @@ -14,10 +15,15 @@ public class LogInController extends Controller { @Override public ModelAndView process(HttpRequest request) { String account = request.getQueryStringValue("account"); - User user = InMemoryUserRepository.findByAccount(account) - .orElseThrow(IllegalArgumentException::new); - log.info("user : {}", user); + String password = request.getQueryStringValue("password"); + Optional optionalUser = InMemoryUserRepository.findByAccountAndPassword(account, password); - return new ModelAndView("/login", null); + if (optionalUser.isPresent()) { + User user = optionalUser.get(); + log.info("optionalUser : {}", user); + return new ModelAndView("/login", user.toMap()); + } + + return new ModelAndView("/401.html", null); } } From f4aeabd59865e1889d58bb32d6a51bc0ba37b0af Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 02:02:14 +0900 Subject: [PATCH 38/62] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20met?= =?UTF-8?q?hod=20=EB=A5=BC=20post=20=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/apache/coyote/handler/HandlerMapping.java | 2 +- tomcat/src/main/resources/static/login.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index 6d19773ad1..793ea6b04c 100644 --- a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -8,7 +8,7 @@ public class HandlerMapping { private static final Map HANDLER_MAPPER = Map.of( - new RequestMapping("GET", "/login"), new LogInController() + new RequestMapping("POST", "/login"), new LogInController() ); public Controller getController(HttpRequestHeader request) { diff --git a/tomcat/src/main/resources/static/login.html b/tomcat/src/main/resources/static/login.html index f4ed9de875..0b68cc758e 100644 --- a/tomcat/src/main/resources/static/login.html +++ b/tomcat/src/main/resources/static/login.html @@ -20,7 +20,7 @@

로그인

-
+
From 01109c83e670e12f8679fe9c77990c4330aa08a0 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 02:10:52 +0900 Subject: [PATCH 39/62] =?UTF-8?q?refactor:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/apache/coyote/http11/HttpRequestHeader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index fc3e2b3e8b..e21a58e41e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -62,7 +62,7 @@ private static Map extractHeaders(String requestHeader) { } public int getContentLength() { - return Integer.parseInt(headers.get("content-length")); + return Integer.parseInt(headers.get("Content-Length")); } public String getHttpMethod() { From 1fddd40884116eec5be31796868c2ef2f8990c6d Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:30:26 +0900 Subject: [PATCH 40/62] =?UTF-8?q?feat:=20HTTP=20Response=20=EA=B0=9D?= =?UTF-8?q?=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 --- .../apache/coyote/http11/HttpResponse.java | 29 +++++++++++++++++++ .../coyote/http11/HttpResponseStatusLine.java | 16 ++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpResponseStatusLine.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java new file mode 100644 index 0000000000..ce8851d8ee --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java @@ -0,0 +1,29 @@ +package org.apache.coyote.http11; + +import java.util.Map; + +public record HttpResponse( + HttpResponseStatusLine statusLine, + Map headers, + String body) { + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder + .append(statusLine) + .append(System.lineSeparator()); + + headers.forEach((key, value) -> stringBuilder + .append(key) + .append(": ") + .append(value) + .append(System.lineSeparator())); + + stringBuilder + .append(System.lineSeparator()) + .append(body); + return stringBuilder.toString(); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseStatusLine.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseStatusLine.java new file mode 100644 index 0000000000..7a1b181e2e --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseStatusLine.java @@ -0,0 +1,16 @@ +package org.apache.coyote.http11; + +public record HttpResponseStatusLine( + String httpVersion, + int statusCode, + String reasonPhrase) { + + public HttpResponseStatusLine(int statusCode, String reasonPhrase) { + this("HTTP/1.1", statusCode, reasonPhrase); + } + + @Override + public String toString() { + return httpVersion + " " + statusCode + " " + reasonPhrase; + } +} From b77771da160362e91c9ac3eb7daaaea72f2e636e Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:31:00 +0900 Subject: [PATCH 41/62] =?UTF-8?q?style:=20=EA=B0=9C=ED=96=89=20=EB=B0=8F?= =?UTF-8?q?=20=EC=95=88=EC=93=B0=EB=8A=94=20=ED=95=A8=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/apache/coyote/http11/HttpRequest.java | 4 +++- .../java/org/apache/coyote/http11/HttpRequestHeader.java | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index 773ba4d505..a296257aad 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -1,6 +1,8 @@ package org.apache.coyote.http11; -public record HttpRequest(HttpRequestHeader header, HttpRequestBody body) { +public record HttpRequest( + HttpRequestHeader header, + HttpRequestBody body) { public String getQueryStringValue(String key) { return header.getQueryStringValue(key); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index e21a58e41e..700497ff17 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -65,6 +65,10 @@ public int getContentLength() { return Integer.parseInt(headers.get("Content-Length")); } + public String getContentType() { + return headers.get("Content-Type"); + } + public String getHttpMethod() { return this.httpMethod; } @@ -76,8 +80,4 @@ public String getPath() { public String getQueryStringValue(String key) { return this.queryString.get(key); } - - public String getHeader(String key) { - return headers.get(key); - } } From 4f1a5fcd711f018ec59c40a93ab9b67193f485aa Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:31:41 +0900 Subject: [PATCH 42/62] =?UTF-8?q?feat:=20RequestBody=20=EB=82=B4=EC=9A=A9?= =?UTF-8?q?=EC=9D=84=20String=20=EC=9D=B4=20=EC=95=84=EB=8B=88=EB=9D=BC=20?= =?UTF-8?q?Map=20=EC=9C=BC=EB=A1=9C=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/HttpRequestBody.java | 27 ++++++++++++++++++- .../coyote/http11/HttpRequestReceiver.java | 3 ++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java index fa414193c9..5c1f37fb88 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java @@ -1,4 +1,29 @@ package org.apache.coyote.http11; -public record HttpRequestBody(String body) { +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public record HttpRequestBody(Map body) { + + public HttpRequestBody(String payload, String contentType) { + this(parseBody(payload, contentType)); + } + + private static Map parseBody(String payload, String contentType) { + Map body = new HashMap<>(); + if ("application/x-www-form-urlencoded".equals(contentType)) { + String[] payloads = payload.split("&"); + Arrays.stream(payloads) + .map(param -> param.split("=")) + .filter(parts -> parts.length == 2) + .forEach(parts -> body.put(parts[0], parts[1])); + } + + return body; + } + + public String getAttribute(String key) { + return body.get(key); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java index f3a3177d02..2844f238f5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java @@ -16,7 +16,8 @@ HttpRequest receiveRequest(InputStream inputStream) throws IOException { HttpRequestBody body = null; if ("POST".equals(header.getHttpMethod()) || "PUT".equals(header.getHttpMethod())) { int contentLength = header.getContentLength(); - body = new HttpRequestBody(receiveRequestBody(bufferedReader, contentLength)); + String payload = receiveRequestBody(bufferedReader, contentLength); + body = new HttpRequestBody(payload, header.getContentType()); } return new HttpRequest(header, body); From 472a6e67dd44e586f69289a56f7fed3c5473e352 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:32:10 +0900 Subject: [PATCH 43/62] =?UTF-8?q?feat:=20HttpResponse=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EB=82=B4=EC=9A=A9=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/controller/Controller.java | 4 ++-- .../coyote/controller/LogInController.java | 22 ++++++++++++++----- .../apache/coyote/http11/Http11Processor.java | 5 ++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java index 2656301fde..dd5588b036 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java @@ -1,9 +1,9 @@ package org.apache.coyote.controller; import org.apache.coyote.http11.HttpRequest; -import org.apache.coyote.view.ModelAndView; +import org.apache.coyote.http11.HttpResponse; public abstract class Controller { - public abstract ModelAndView process(HttpRequest request); + public abstract HttpResponse process(HttpRequest request); } diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index e6f4dcd728..1a5eaa56c5 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -2,9 +2,11 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; +import java.util.Map; import java.util.Optional; import org.apache.coyote.http11.HttpRequest; -import org.apache.coyote.view.ModelAndView; +import org.apache.coyote.http11.HttpResponse; +import org.apache.coyote.http11.HttpResponseStatusLine; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,17 +15,25 @@ public class LogInController extends Controller { private static final Logger log = LoggerFactory.getLogger(LogInController.class); @Override - public ModelAndView process(HttpRequest request) { - String account = request.getQueryStringValue("account"); - String password = request.getQueryStringValue("password"); + public HttpResponse process(HttpRequest request) { + String account = request.body().getAttribute("account"); + String password = request.body().getAttribute("password"); Optional optionalUser = InMemoryUserRepository.findByAccountAndPassword(account, password); if (optionalUser.isPresent()) { User user = optionalUser.get(); log.info("optionalUser : {}", user); - return new ModelAndView("/login", user.toMap()); + return new HttpResponse( + new HttpResponseStatusLine(302, "Found"), + Map.of("Location", "/index.html"), + null + ); } - return new ModelAndView("/401.html", null); + return new HttpResponse( + new HttpResponseStatusLine(401, "Unauthorized"), + null, + null + ); } } 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 265e274d15..58bde32fef 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -6,7 +6,6 @@ import org.apache.coyote.Processor; import org.apache.coyote.controller.Controller; import org.apache.coyote.handler.HandlerMapping; -import org.apache.coyote.view.ModelAndView; import org.apache.coyote.view.ViewResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,8 +47,8 @@ public void process(final Socket connection) { private String getResponse(HttpRequest request) throws IOException { Controller controller = handlerMapping.getController(request.header()); if (controller != null) { - ModelAndView modelAndView = controller.process(request); - return viewResolver.resolve(modelAndView.getView()); + HttpResponse httpResponse = controller.process(request); + return httpResponse.toString(); } return viewResolver.resolve(request.header()); From 504e1113256e6cac011d532b1fd4877c52e04220 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:36:28 +0900 Subject: [PATCH 44/62] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=ED=8B=80=EB=A6=B0=20=EA=B2=BD=EC=9A=B0=20=EB=A6=AC?= =?UTF-8?q?=EB=8B=A4=EC=9D=B4=EB=A0=89=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/controller/LogInController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index 1a5eaa56c5..c8a70a8236 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -31,8 +31,8 @@ public HttpResponse process(HttpRequest request) { } return new HttpResponse( - new HttpResponseStatusLine(401, "Unauthorized"), - null, + new HttpResponseStatusLine(302, "Found"), + Map.of("Location", "/401.html"), null ); } From bdeb85b95d6f8cea53684efdac1216cc6eef737f Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 10:36:42 +0900 Subject: [PATCH 45/62] =?UTF-8?q?refactor:=20=EA=B5=AC=EA=B5=AC=20?= =?UTF-8?q?=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/techcourse/db/InMemoryUserRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java index f74cb93c27..32ef776dc6 100644 --- a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java +++ b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java @@ -10,7 +10,7 @@ public class InMemoryUserRepository { private static final Map database = new ConcurrentHashMap<>(); static { - final User user = new User(1L, "gugu", "password", "hkkang@woowahan.com"); + final User user = new User(1L, "sancho", "1234", "sancho@woowa.com"); database.put(user.getAccount(), user); } From e41c3d333802dca57d361a04fd5dc30b43882140 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 12:52:39 +0900 Subject: [PATCH 46/62] =?UTF-8?q?refactor:=20=ED=95=99=EC=8A=B5=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A0=95=EC=A0=81=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=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 --- .../src/main/java/cache/com/example/GreetingController.java | 6 +++--- study/src/main/resources/{templates => static}/index.html | 0 .../{templates => static}/resource-versioning.html | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename study/src/main/resources/{templates => static}/index.html (100%) rename study/src/main/resources/{templates => static}/resource-versioning.html (100%) diff --git a/study/src/main/java/cache/com/example/GreetingController.java b/study/src/main/java/cache/com/example/GreetingController.java index c0053cda42..5ec03b4a35 100644 --- a/study/src/main/java/cache/com/example/GreetingController.java +++ b/study/src/main/java/cache/com/example/GreetingController.java @@ -12,7 +12,7 @@ public class GreetingController { @GetMapping("/") public String index() { - return "index"; + return "index.html"; } /** @@ -25,12 +25,12 @@ public String cacheControl(final HttpServletResponse response) { .cachePrivate() .getHeaderValue(); response.addHeader(HttpHeaders.CACHE_CONTROL, cacheControl); - return "index"; + return "index.html"; } @GetMapping("/etag") public String etag() { - return "index"; + return "index.html"; } @GetMapping("/resource-versioning") diff --git a/study/src/main/resources/templates/index.html b/study/src/main/resources/static/index.html similarity index 100% rename from study/src/main/resources/templates/index.html rename to study/src/main/resources/static/index.html diff --git a/study/src/main/resources/templates/resource-versioning.html b/study/src/main/resources/static/resource-versioning.html similarity index 100% rename from study/src/main/resources/templates/resource-versioning.html rename to study/src/main/resources/static/resource-versioning.html From 49e5de39e8a61eff901a9d57a45da59c7d74f848 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 12:53:26 +0900 Subject: [PATCH 47/62] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=A0=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EC=97=90=20no-cache=20=EB=B6=99=EC=9D=B4=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/cachecontrol/CacheWebConfig.java | 1 + .../example/cachecontrol/NoCacheInterceptor.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 study/src/main/java/cache/com/example/cachecontrol/NoCacheInterceptor.java diff --git a/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java b/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java index 305b1f1e1e..6b910b9dfb 100644 --- a/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java +++ b/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java @@ -9,5 +9,6 @@ public class CacheWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(final InterceptorRegistry registry) { + registry.addInterceptor(new NoCacheInterceptor()); } } diff --git a/study/src/main/java/cache/com/example/cachecontrol/NoCacheInterceptor.java b/study/src/main/java/cache/com/example/cachecontrol/NoCacheInterceptor.java new file mode 100644 index 0000000000..74258c0ae2 --- /dev/null +++ b/study/src/main/java/cache/com/example/cachecontrol/NoCacheInterceptor.java @@ -0,0 +1,16 @@ +package cache.com.example.cachecontrol; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.lang.Nullable; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +public class NoCacheInterceptor implements HandlerInterceptor { + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + @Nullable ModelAndView modelAndView) throws Exception { + response.setHeader("Cache-Control", "no-cache, private"); + } +} From aff1c83c46281c06c692a2e1450ba338ff5143bf Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 13:07:47 +0900 Subject: [PATCH 48/62] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/controller/RegisterController.java | 31 +++++++++++++++++++ .../apache/coyote/handler/HandlerMapping.java | 4 ++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java new file mode 100644 index 0000000000..bf7bd08f24 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java @@ -0,0 +1,31 @@ +package org.apache.coyote.controller; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; +import java.util.Map; +import org.apache.coyote.http11.HttpRequest; +import org.apache.coyote.http11.HttpResponse; +import org.apache.coyote.http11.HttpResponseStatusLine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RegisterController extends Controller { + + private static final Logger log = LoggerFactory.getLogger(RegisterController.class); + + @Override + public HttpResponse process(HttpRequest request) { + String account = request.body().getAttribute("account"); + String email = request.body().getAttribute("email"); + String password = request.body().getAttribute("password"); + + InMemoryUserRepository.save(new User(account, password, email)); + log.info("Register success: { account: {}, email: {}, password:{}}", account, email, password); + + return new HttpResponse( + new HttpResponseStatusLine(302, "Found"), + Map.of("Location", "/index.html"), + null + ); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java index 793ea6b04c..329b1c9bbc 100644 --- a/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/handler/HandlerMapping.java @@ -3,12 +3,14 @@ import java.util.Map; import org.apache.coyote.controller.Controller; import org.apache.coyote.controller.LogInController; +import org.apache.coyote.controller.RegisterController; import org.apache.coyote.http11.HttpRequestHeader; public class HandlerMapping { private static final Map HANDLER_MAPPER = Map.of( - new RequestMapping("POST", "/login"), new LogInController() + new RequestMapping("POST", "/login"), new LogInController(), + new RequestMapping("POST", "/register"), new RegisterController() ); public Controller getController(HttpRequestHeader request) { From 9a284309a05a7f0619956df3f8bc50be4532a5e1 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 13:50:31 +0900 Subject: [PATCH 49/62] =?UTF-8?q?fix:=20=EC=9D=B8=EC=BD=94=EB=94=A9=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/http11/HttpRequestReceiver.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java index 2844f238f5..257646afa4 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestReceiver.java @@ -4,11 +4,13 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; public class HttpRequestReceiver { HttpRequest receiveRequest(InputStream inputStream) throws IOException { - InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); HttpRequestHeader header = new HttpRequestHeader(receiveRequestHeader(bufferedReader)); @@ -17,7 +19,8 @@ HttpRequest receiveRequest(InputStream inputStream) throws IOException { if ("POST".equals(header.getHttpMethod()) || "PUT".equals(header.getHttpMethod())) { int contentLength = header.getContentLength(); String payload = receiveRequestBody(bufferedReader, contentLength); - body = new HttpRequestBody(payload, header.getContentType()); + String decodedPayload = URLDecoder.decode(payload, StandardCharsets.UTF_8); + body = new HttpRequestBody(decodedPayload, header.getContentType()); } return new HttpRequest(header, body); From cec39fea1229b08367ddc443bd53ebad60b4128e Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 14:14:33 +0900 Subject: [PATCH 50/62] =?UTF-8?q?feat:=20=EC=84=B8=EC=85=98,=20=EC=84=B8?= =?UTF-8?q?=EC=85=98=20=EB=A9=94=EB=8B=88=EC=A0=80=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/session/Session.java | 16 +++++++++++++ .../apache/coyote/session/SessionManager.java | 23 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/session/Session.java create mode 100644 tomcat/src/main/java/org/apache/coyote/session/SessionManager.java diff --git a/tomcat/src/main/java/org/apache/coyote/session/Session.java b/tomcat/src/main/java/org/apache/coyote/session/Session.java new file mode 100644 index 0000000000..44cc75f7a2 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/session/Session.java @@ -0,0 +1,16 @@ +package org.apache.coyote.session; + +import com.techcourse.model.User; + +public class Session { + + private final User user; + + public Session(User user) { + this.user = user; + } + + public User getUser() { + return user; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/session/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/session/SessionManager.java new file mode 100644 index 0000000000..fc5304811e --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/session/SessionManager.java @@ -0,0 +1,23 @@ +package org.apache.coyote.session; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SessionManager { + + private static final Map sessionStorage = new HashMap<>(); + + private SessionManager() {} + + public static synchronized String add(Session session) { + UUID uuid = UUID.randomUUID(); + sessionStorage.put(uuid.toString(), session); + + return uuid.toString(); + } + + public static Session findSession(String id) { + return sessionStorage.get(id); + } +} From d26989991dcbb087fff69dcab9e0c3e5e40f8798 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 14:30:28 +0900 Subject: [PATCH 51/62] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=8B=9C=20=EC=84=B8?= =?UTF-8?q?=EC=85=98=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/techcourse/db/InMemoryUserRepository.java | 4 ++-- .../java/org/apache/coyote/controller/LogInController.java | 3 +++ .../org/apache/coyote/controller/RegisterController.java | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java index 32ef776dc6..266b98ea09 100644 --- a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java +++ b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java @@ -14,8 +14,8 @@ public class InMemoryUserRepository { database.put(user.getAccount(), user); } - public static void save(User user) { - database.put(user.getAccount(), user); + public static User save(User user) { + return database.put(user.getAccount(), user); } public static Optional findByAccount(String account) { diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index c8a70a8236..fe6bc31c4f 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -7,6 +7,8 @@ import org.apache.coyote.http11.HttpRequest; import org.apache.coyote.http11.HttpResponse; import org.apache.coyote.http11.HttpResponseStatusLine; +import org.apache.coyote.session.Session; +import org.apache.coyote.session.SessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +25,7 @@ public HttpResponse process(HttpRequest request) { if (optionalUser.isPresent()) { User user = optionalUser.get(); log.info("optionalUser : {}", user); + SessionManager.add(new Session(user)); return new HttpResponse( new HttpResponseStatusLine(302, "Found"), Map.of("Location", "/index.html"), diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java index bf7bd08f24..7b5b2361ee 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java @@ -6,6 +6,8 @@ import org.apache.coyote.http11.HttpRequest; import org.apache.coyote.http11.HttpResponse; import org.apache.coyote.http11.HttpResponseStatusLine; +import org.apache.coyote.session.Session; +import org.apache.coyote.session.SessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,8 +21,9 @@ public HttpResponse process(HttpRequest request) { String email = request.body().getAttribute("email"); String password = request.body().getAttribute("password"); - InMemoryUserRepository.save(new User(account, password, email)); + User user = InMemoryUserRepository.save(new User(account, password, email)); log.info("Register success: { account: {}, email: {}, password:{}}", account, email, password); + SessionManager.add(new Session(user)); return new HttpResponse( new HttpResponseStatusLine(302, "Found"), From 4f552bc33f8d7948889ecd8cc501085c459685ad Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 14:34:10 +0900 Subject: [PATCH 52/62] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=8B=9C=20SetCookie=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/controller/LogInController.java | 5 +++-- .../org/apache/coyote/controller/RegisterController.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java index fe6bc31c4f..0476acd97e 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/LogInController.java @@ -25,10 +25,11 @@ public HttpResponse process(HttpRequest request) { if (optionalUser.isPresent()) { User user = optionalUser.get(); log.info("optionalUser : {}", user); - SessionManager.add(new Session(user)); + String sessionId = SessionManager.add(new Session(user)); return new HttpResponse( new HttpResponseStatusLine(302, "Found"), - Map.of("Location", "/index.html"), + Map.of("Location", "/index.html", + "Set-Cookie", "JSESSIONID=" + sessionId), null ); } diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java index 7b5b2361ee..adb58bdb11 100644 --- a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java +++ b/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java @@ -23,11 +23,12 @@ public HttpResponse process(HttpRequest request) { User user = InMemoryUserRepository.save(new User(account, password, email)); log.info("Register success: { account: {}, email: {}, password:{}}", account, email, password); - SessionManager.add(new Session(user)); + String sessionId = SessionManager.add(new Session(user)); return new HttpResponse( new HttpResponseStatusLine(302, "Found"), - Map.of("Location", "/index.html"), + Map.of("Location", "/index.html", + "Set-Cookie", "JSESSIONID=" + sessionId), null ); } From 0fad21816f0afade72d361de82ee698b08c4a1b8 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 15:15:38 +0900 Subject: [PATCH 53/62] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=9C=A0=EC=A0=80=EB=8A=94=20=EB=A6=AC=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EB=A0=89=ED=8A=B8=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/HttpRequestHeader.java | 13 +++++++++++++ .../org/apache/coyote/view/ResponseBuilder.java | 6 ++++++ .../java/org/apache/coyote/view/ViewResolver.java | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index 700497ff17..217dab715b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -69,6 +69,19 @@ public String getContentType() { return headers.get("Content-Type"); } + public Map getCookies() { + String cookie = headers.get("Cookie"); + if (cookie == null) { + return null; + } + + return Arrays.stream(cookie.split(";")) + .map(String::trim) + .map(part -> part.split("=")) + .filter(parts -> parts.length == 2) + .collect(Collectors.toMap(parts -> parts[0], parts -> parts[1])); + } + public String getHttpMethod() { return this.httpMethod; } diff --git a/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java b/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java index ef6ca524b9..1d8e3a222b 100644 --- a/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ResponseBuilder.java @@ -31,4 +31,10 @@ String buildNotFoundResponse() throws IOException { "", responseBody); } + + String buildRedirectResponse(String location) { + return String.join("\r\n", + "HTTP/1.1 302 FOUND ", + "Location: " + location); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java index a61c25f615..e5d3d37293 100644 --- a/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java +++ b/tomcat/src/main/java/org/apache/coyote/view/ViewResolver.java @@ -20,6 +20,12 @@ public String resolve(String view) throws IOException { } public String resolve(HttpRequestHeader request) throws IOException { + if (GET_METHOD.equals(request.getHttpMethod()) + && (request.getPath().startsWith("/login") || request.getPath().startsWith("/register")) + && (request.getCookies() != null && request.getCookies().get("JSESSIONID") != null)) { + return responseBuilder.buildRedirectResponse("/index.html"); + } + if (GET_METHOD.equals(request.getHttpMethod())) { return handleGetRequest(request.getPath()); } From 6319148d881939be84c75eab1b0dba0789a1fdc4 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 16:08:28 +0900 Subject: [PATCH 54/62] =?UTF-8?q?feat:=20=EC=9D=91=EB=8B=B5=20=EC=95=95?= =?UTF-8?q?=EC=B6=95=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/main/resources/application.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index e3503a5fb9..7277616bc7 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -8,3 +8,6 @@ server: threads: min-spare: 2 max: 2 + compression: + enabled: true + min-response-size: 10 \ No newline at end of file From 191c2a7ee2ed6c7ab85e6e79e372fcfc42524b39 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 16:09:06 +0900 Subject: [PATCH 55/62] =?UTF-8?q?feat:=20=ED=8A=B9=EC=A0=95=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=EC=97=90=20=EB=8C=80=ED=95=B4=20etag=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/etag/EtagFilterConfiguration.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java index 41ef7a3d9a..9d6ac80b93 100644 --- a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java +++ b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java @@ -1,12 +1,19 @@ package cache.com.example.etag; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.ShallowEtagHeaderFilter; @Configuration public class EtagFilterConfiguration { -// @Bean -// public FilterRegistrationBean shallowEtagHeaderFilter() { -// return null; -// } + @Bean + public FilterRegistrationBean shallowEtagHeaderFilter() { + FilterRegistrationBean filterRegistrationBean + = new FilterRegistrationBean<>(new ShallowEtagHeaderFilter()); + filterRegistrationBean.addUrlPatterns("/etag/*"); + + return filterRegistrationBean; + } } From 161dd572f785658b7ef2695a20f2d776aac2df63 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 16:49:30 +0900 Subject: [PATCH 56/62] =?UTF-8?q?feat:=20=EC=A0=95=EC=A0=81=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9A=94=EC=B2=AD=EC=8B=9C=20etag=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cache/com/example/etag/EtagFilterConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java index 9d6ac80b93..1023a120c0 100644 --- a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java +++ b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java @@ -13,7 +13,8 @@ public FilterRegistrationBean shallowEtagHeaderFilter() FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(new ShallowEtagHeaderFilter()); filterRegistrationBean.addUrlPatterns("/etag/*"); - + filterRegistrationBean.addUrlPatterns("*.html"); + filterRegistrationBean.addUrlPatterns("*.js"); return filterRegistrationBean; } } From c9b83eba47cce4e7755624b3604f6f085dfd16f2 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 16:50:10 +0900 Subject: [PATCH 57/62] =?UTF-8?q?refactor:=20=EB=A3=A8=ED=8A=B8=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EC=97=90=20=EB=8C=80=ED=95=B4=20no=20cache?= =?UTF-8?q?=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cache/com/example/cachecontrol/CacheWebConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java b/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java index 6b910b9dfb..64fd03cd4a 100644 --- a/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java +++ b/study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java @@ -9,6 +9,7 @@ public class CacheWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(final InterceptorRegistry registry) { - registry.addInterceptor(new NoCacheInterceptor()); + registry.addInterceptor(new NoCacheInterceptor()) + .addPathPatterns("/"); } } From 51427068575318ef9e8e1f28cb8d6faf39e72af1 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 16:50:38 +0900 Subject: [PATCH 58/62] =?UTF-8?q?feat:=20=EC=A0=95=EC=A0=81=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=BA=90=EC=8B=9C=20?= =?UTF-8?q?=EB=A7=8C=EB=A3=8C=20=EC=8B=9C=EA=B0=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cache/com/example/version/CacheBustingWebConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java b/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java index 6da6d2c795..c7addcdab4 100644 --- a/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java +++ b/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java @@ -1,7 +1,9 @@ package cache.com.example.version; +import java.time.Duration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -20,6 +22,7 @@ public CacheBustingWebConfig(ResourceVersion version) { @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler(PREFIX_STATIC_RESOURCES + "/" + version.getVersion() + "/**") - .addResourceLocations("classpath:/static/"); + .addResourceLocations("classpath:/static/") + .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic()); } } From 64792323af4d0ce57cc91e05a45b5389d040b86e Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 17:25:24 +0900 Subject: [PATCH 59/62] =?UTF-8?q?refactor:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cache/com/example/etag/EtagFilterConfiguration.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java index 1023a120c0..f103a934ae 100644 --- a/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java +++ b/study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java @@ -13,8 +13,6 @@ public FilterRegistrationBean shallowEtagHeaderFilter() FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(new ShallowEtagHeaderFilter()); filterRegistrationBean.addUrlPatterns("/etag/*"); - filterRegistrationBean.addUrlPatterns("*.html"); - filterRegistrationBean.addUrlPatterns("*.js"); return filterRegistrationBean; } } From b48b3829f1229e9f9eab8933576285f8e1a1abc0 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 17:25:58 +0900 Subject: [PATCH 60/62] =?UTF-8?q?refactor:=20=EC=8B=9C=EA=B0=84=EC=9D=84?= =?UTF-8?q?=20etag=20=EB=B2=84=EC=A0=84=EC=9C=BC=EB=A1=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cache/com/example/version/CacheBustingWebConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java b/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java index c7addcdab4..7a029a4be6 100644 --- a/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java +++ b/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java @@ -23,6 +23,7 @@ public CacheBustingWebConfig(ResourceVersion version) { public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler(PREFIX_STATIC_RESOURCES + "/" + version.getVersion() + "/**") .addResourceLocations("classpath:/static/") + .setEtagGenerator(resource -> version.getVersion()) .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic()); } } From 41b7cb51e62cd1b2082ffcde941c2200a1e584e3 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 17:26:15 +0900 Subject: [PATCH 61/62] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=ED=99=95=EC=9E=A5=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/main/java/cache/com/example/GreetingController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/study/src/main/java/cache/com/example/GreetingController.java b/study/src/main/java/cache/com/example/GreetingController.java index 5ec03b4a35..ef130677be 100644 --- a/study/src/main/java/cache/com/example/GreetingController.java +++ b/study/src/main/java/cache/com/example/GreetingController.java @@ -35,6 +35,6 @@ public String etag() { @GetMapping("/resource-versioning") public String resourceVersioning() { - return "resource-versioning"; + return "resource-versioning.html"; } } From eb6b28c74c0fc6778ea3f836d4fcb7cb8228887b Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 6 Sep 2024 17:39:55 +0900 Subject: [PATCH 62/62] =?UTF-8?q?chore:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/view/ModelAndView.java | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java diff --git a/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java b/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java deleted file mode 100644 index 4b19eaf522..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/view/ModelAndView.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apache.coyote.view; - -import java.util.Map; - -public class ModelAndView { - - private final String view; - private final Map model; - - public ModelAndView(String view, Map model) { - this.view = view; - this.model = model; - } - - public String getView() { - return view; - } - - public Map getAttributes() { - return this.model; - } -}