From fed02f6f5f4308400e55c160d9495cad010f5bfb Mon Sep 17 00:00:00 2001 From: Gyeongho Yang Date: Thu, 5 Sep 2024 11:11:09 +0900 Subject: [PATCH 01/49] 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/49] 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 f058739f8fbec0ac22f2ce3bde38e38d4353c203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Sun, 8 Sep 2024 16:21:35 +0900 Subject: [PATCH 03/49] =?UTF-8?q?[=ED=86=B0=EC=BA=A3=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=ED=95=98=EA=B8=B0=201,=202=EB=8B=A8=EA=B3=84]=20=EC=95=88?= =?UTF-8?q?=EB=82=98=20(=EA=B9=80=EB=AF=BC=EA=B2=B8)=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=A0=9C=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4.=20(#571)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: 학습 테스트 진행 * feat: `/index.html`에 접근했을 때 static/index.html 파일이 보여지도록 구현 * feat: 자원에 따라 다른 Conent-Type으로 응답을 보내도록 수정 * fix: remove implementation logback-classic on gradle (#501) * fix: 공백 처리 때문에 index.html이 불러와지지 않는 현상 해결 * feat: 로그인 요청 시 쿼리 파라미터를 파싱하는 기능 구현 * fix: add threads min-spare configuration on properties (#502) * feat: 로그인에 성공하거나 실패한 경우 다른 페이지로 리다이렉트하는 * feat: POST 요청으로 회원 가입 시 요청 본문에서 정보를 가져와 사용자 저장하는 기능 구현 * feat: 로그인 시 POST 요청을 보내도록 수정 * feat: 로그인 시 세션 아이디를 쿠키에 등록하는 기능 구현 * feat: 쿠키에 JSESSIONID가 없을 때 Set-Cookie를 발급하는 기능 구현 * feat: 이미 로그인한 회원의 경우 로그인 페이지에 접근 불가하도록 구현 * refactor: 쿠키가 없을 때 일반 페이지에 접근하면 세션 아이디를 주지 않음 * feat: HTTP 활용 학습 테스트 진행 * refactor: 뭉친 코드를 클래스 분리하여 리팩토링 * fix: JSESSIONID를 추가하지 않아 로그인되지 않는 문제 해결 * fix: 세션 아이디가 달라서 로그인 시 로그인 페이지가 접속되는 현상 해결 * refactor: 기존 코드 주석 제거 * style: 주석 제거 및 컨벤션 맞추기 * refactor: 미구현된 파일 제거 * refactor: 필터를 사용하여 ETag를 지정하는 것으로 변경 * refactor: 인터셉터에서 CacheControl을 적용할 수 있도록 수정 * refactor: Content-Length 헤더 이름을 상수화 * refactor: 정적 파일을 한 번에 처리하도록 리팩토링 * fix: Json 파일을 보내는 경우를 고려하여 MediaType 수정 * refactor: 로그인 시 쿠키 세션을 꺼내오는 코드 가독성 개선 * refactor: 요청한 사용자 정보가 없는 경우 401 페이지를 보여주도록 수정 * refactor: 쿠키의 키값을 상수화하여 리팩토링 --------- Co-authored-by: Gyeongho Yang --- .../cache/com/example/GreetingController.java | 12 ++- .../cachecontrol/CacheControlInterceptor.java | 15 +++ .../example/cachecontrol/CacheWebConfig.java | 2 + .../example/etag/EtagFilterConfiguration.java | 15 ++- .../version/CacheBustingWebConfig.java | 9 +- .../com/example/version/ResourceVersion.java | 3 +- study/src/main/resources/application.yml | 2 + study/src/test/java/study/FileTest.java | 24 ++++- study/src/test/java/study/IOStreamTest.java | 25 +++-- .../apache/coyote/http11/Http11Processor.java | 35 +++++-- .../coyote/http11/request/HttpRequest.java | 57 +++++++++++ .../coyote/http11/request/RequestHandler.java | 98 +++++++++++++++++++ .../http11/response/ResponseHandler.java | 96 ++++++++++++++++++ .../apache/coyote/http11/session/Session.java | 43 ++++++++ .../coyote/http11/session/SessionManager.java | 21 ++++ tomcat/src/main/resources/static/login.html | 2 +- 16 files changed, 426 insertions(+), 33 deletions(-) create mode 100644 study/src/main/java/cache/com/example/cachecontrol/CacheControlInterceptor.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/session/Session.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java diff --git a/study/src/main/java/cache/com/example/GreetingController.java b/study/src/main/java/cache/com/example/GreetingController.java index c0053cda42..af2da3176d 100644 --- a/study/src/main/java/cache/com/example/GreetingController.java +++ b/study/src/main/java/cache/com/example/GreetingController.java @@ -2,6 +2,7 @@ import org.springframework.http.CacheControl; import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -11,8 +12,10 @@ public class GreetingController { @GetMapping("/") - public String index() { - return "index"; + public ResponseEntity index() { + return ResponseEntity.ok() + .header("Content-Encoding", "gzip") + .body("index"); } /** @@ -29,8 +32,9 @@ public String cacheControl(final HttpServletResponse response) { } @GetMapping("/etag") - public String etag() { - return "index"; + public ResponseEntity etag() { + return ResponseEntity.ok() + .body("index"); } @GetMapping("/resource-versioning") diff --git a/study/src/main/java/cache/com/example/cachecontrol/CacheControlInterceptor.java b/study/src/main/java/cache/com/example/cachecontrol/CacheControlInterceptor.java new file mode 100644 index 0000000000..fa967b3edb --- /dev/null +++ b/study/src/main/java/cache/com/example/cachecontrol/CacheControlInterceptor.java @@ -0,0 +1,15 @@ +package cache.com.example.cachecontrol; + +import org.springframework.web.servlet.HandlerInterceptor; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public class CacheControlInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + response.addHeader("Cache-Control", "no-cache, private"); + return true; + } +} 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..ad7f9638a0 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,7 @@ public class CacheWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(final InterceptorRegistry registry) { + registry.addInterceptor(new CacheControlInterceptor()) + .addPathPatterns("/"); } } 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..2c58520179 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,17 @@ 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; + } +} \ No newline at end of file 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..a4297c335b 100644 --- a/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java +++ b/study/src/main/java/cache/com/example/version/CacheBustingWebConfig.java @@ -1,9 +1,13 @@ package cache.com.example.version; +import java.util.concurrent.TimeUnit; + 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; +import org.springframework.web.servlet.resource.VersionResourceResolver; @Configuration public class CacheBustingWebConfig implements WebMvcConfigurer { @@ -20,6 +24,9 @@ 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(365, TimeUnit.DAYS).cachePublic()) + .resourceChain(false) + .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**")); } } diff --git a/study/src/main/java/cache/com/example/version/ResourceVersion.java b/study/src/main/java/cache/com/example/version/ResourceVersion.java index 27a2f22813..8c531e3efa 100644 --- a/study/src/main/java/cache/com/example/version/ResourceVersion.java +++ b/study/src/main/java/cache/com/example/version/ResourceVersion.java @@ -2,10 +2,11 @@ import org.springframework.stereotype.Component; -import jakarta.annotation.PostConstruct; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import jakarta.annotation.PostConstruct; + @Component public class ResourceVersion { diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index e3503a5fb9..4a38f2f811 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -8,3 +8,5 @@ server: threads: min-spare: 2 max: 2 + compression: + enabled: true diff --git a/study/src/test/java/study/FileTest.java b/study/src/test/java/study/FileTest.java index e1b6cca042..f8c0359a5e 100644 --- a/study/src/test/java/study/FileTest.java +++ b/study/src/test/java/study/FileTest.java @@ -2,13 +2,23 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDirFactory; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import javax.swing.filechooser.FileSystemView; + /** * 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다. * File 클래스를 사용해서 파일을 읽어오고, 사용자에게 전달한다. @@ -28,7 +38,10 @@ class FileTest { final String fileName = "nextstep.txt"; // todo - final String actual = ""; + URL url = getClass().getClassLoader().getResource(fileName); + File file = new File(url.getPath()); + + final String actual = file.getAbsolutePath(); assertThat(actual).endsWith(fileName); } @@ -40,15 +53,16 @@ class FileTest { * File, Files 클래스를 사용하여 파일의 내용을 읽어보자. */ @Test - void 파일의_내용을_읽는다() { + void 파일의_내용을_읽는다() throws IOException { final String fileName = "nextstep.txt"; // todo - final Path path = null; + final URL url = getClass().getClassLoader().getResource(fileName); + final File file = new File(url.getPath()); + final Path path = file.toPath(); // todo - final List actual = Collections.emptyList(); - + final List actual = Files.readAllLines(path); assertThat(actual).containsOnly("nextstep"); } } diff --git a/study/src/test/java/study/IOStreamTest.java b/study/src/test/java/study/IOStreamTest.java index 47a79356b6..f0a9602dac 100644 --- a/study/src/test/java/study/IOStreamTest.java +++ b/study/src/test/java/study/IOStreamTest.java @@ -53,6 +53,7 @@ class OutputStream_학습_테스트 { * todo * OutputStream 객체의 write 메서드를 사용해서 테스트를 통과시킨다 */ + outputStream.write(bytes); final String actual = outputStream.toString(); @@ -78,6 +79,7 @@ class OutputStream_학습_테스트 { * flush를 사용해서 테스트를 통과시킨다. * ByteArrayOutputStream과 어떤 차이가 있을까? */ + outputStream.flush(); verify(outputStream, atLeastOnce()).flush(); outputStream.close(); @@ -97,6 +99,8 @@ class OutputStream_학습_테스트 { * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. */ + outputStream.close(); + verify(outputStream, atLeastOnce()).close(); } } @@ -128,7 +132,7 @@ class InputStream_학습_테스트 { * todo * inputStream에서 바이트로 반환한 값을 문자열로 어떻게 바꿀까? */ - final String actual = ""; + final String actual = new String(inputStream.readAllBytes()); assertThat(actual).isEqualTo("🤩"); assertThat(inputStream.read()).isEqualTo(-1); @@ -148,6 +152,7 @@ class InputStream_학습_테스트 { * try-with-resources를 사용한다. * java 9 이상에서는 변수를 try-with-resources로 처리할 수 있다. */ + inputStream.close(); verify(inputStream, atLeastOnce()).close(); } @@ -169,12 +174,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,7 +202,7 @@ class InputStreamReader_학습_테스트 { * 필터인 BufferedReader를 사용하면 readLine 메서드를 사용해서 문자열(String)을 한 줄 씩 읽어올 수 있다. */ @Test - void BufferedReader를_사용하여_문자열을_읽어온다() { + void BufferedReader를_사용하여_문자열을_읽어온다() throws IOException { final String emoji = String.join("\r\n", "😀😃😄😁😆😅😂🤣🥲☺️😊", "😇🙂🙃😉😌😍🥰😘😗😙😚", @@ -206,7 +211,15 @@ class InputStreamReader_학습_테스트 { final InputStream inputStream = new ByteArrayInputStream(emoji.getBytes()); final StringBuilder actual = new StringBuilder(); - + try ( + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + ) { + String line; + while((line = bufferedReader.readLine()) != null) { + actual.append(line + "\r\n"); + } + } assertThat(actual).hasToString(emoji); } } 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..390db0c886 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,18 +1,38 @@ package org.apache.coyote.http11; + +import com.techcourse.db.InMemoryUserRepository; import com.techcourse.exception.UncheckedServletException; +import com.techcourse.model.User; + import org.apache.coyote.Processor; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.request.RequestHandler; +import org.apache.coyote.http11.session.SessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; +import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.net.Socket; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; + private static final Map httpRequestHeader = new HashMap<>(); + private static final String sessionId = "JSESSIONID=sessionId"; public Http11Processor(final Socket connection) { this.connection = connection; @@ -29,18 +49,13 @@ public void process(final Socket connection) { try (final var inputStream = connection.getInputStream(); final var outputStream = connection.getOutputStream()) { - final var responseBody = "Hello world!"; + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + HttpRequest httpRequest = new HttpRequest(reader); - 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); + RequestHandler requestHandler = new RequestHandler(httpRequest, outputStream); + requestHandler.handleRequest(); - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { + } catch (IOException e) { log.error(e.getMessage(), e); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java new file mode 100644 index 0000000000..aaf2d5f417 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -0,0 +1,57 @@ +package org.apache.coyote.http11.request; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class HttpRequest { + + private static final String CONTENT_LENGTH = "Content-Length"; + + private final String method; + private final String path; + private final Map headers = new HashMap<>(); + private final String body; + + public HttpRequest(BufferedReader reader) throws IOException { + String initialLine = reader.readLine(); + this.method = initialLine.split(" ")[0]; + this.path = initialLine.split(" ")[1]; + String line; + while ((line = reader.readLine()) != null && !line.isEmpty()) { + String[] header = line.split(":"); + headers.put(header[0].trim(), header[1].trim()); + } + this.body = parseBody(reader); + } + + private String parseBody(BufferedReader reader) throws IOException { + if(headers.get(CONTENT_LENGTH) == null) { + return null; + } + int contentLength = Integer.parseInt(headers.get(CONTENT_LENGTH)); + if(contentLength > 0) { + char[] body = new char[contentLength]; + reader.read(body, 0, contentLength); + return new String(body); + } + return null; + } + + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getCookie() { + return headers.get("Cookie"); + } + + public String getBody() { + return body; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java new file mode 100644 index 0000000000..3bd3462836 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java @@ -0,0 +1,98 @@ +package org.apache.coyote.http11.request; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.coyote.http11.response.ResponseHandler; +import org.apache.coyote.http11.session.Session; +import org.apache.coyote.http11.session.SessionManager; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; + +public class RequestHandler { + + private final HttpRequest httpRequest; + private final OutputStream outputStream; + + public RequestHandler(HttpRequest httpRequest, OutputStream outputStream) { + this.httpRequest = httpRequest; + this.outputStream = outputStream; + } + + public void handleRequest() throws IOException { + String httpMethod = httpRequest.getMethod(); + String urlPath = httpRequest.getPath(); + + if(urlPath.endsWith("html") || urlPath.endsWith("css") || urlPath.endsWith("js")) { + ResponseHandler.printFileResource("static" + urlPath, outputStream); + } else if (urlPath.startsWith("/login")) { + handleLoginRequest(httpMethod, urlPath); + } else if (urlPath.startsWith("/register")) { + handleRegisterRequest(httpMethod, urlPath); + } else { + sendHelloWorldResponse(); + } + } + + private void handleLoginRequest(String httpMethod, String urlPath) { + if (urlPath.equals("/login") && httpMethod.equals("GET")) { + Session session = new Session(httpRequest); + SessionManager.findUserBySession(session) + .ifPresentOrElse( + user -> ResponseHandler.redirect("/index.html", outputStream), + () -> ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream)); + } else if (httpMethod.equals("POST")) { + login(); + } + } + + private void login() { + String body = httpRequest.getBody(); + if (body != null) { + String account = body.split("&")[0].split("=")[1]; + String password = body.split("&")[1].split("=")[1]; + InMemoryUserRepository.findByAccount(account) + .ifPresentOrElse( + user -> loginUser(user, password), + () -> ResponseHandler.redirect("/401.html", outputStream) + ); + } + ResponseHandler.redirect("/401.html", outputStream); + } + + private void loginUser(User user, String password) { + if (user.checkPassword(password)) { + Session session = SessionManager.createSession(user); + ResponseHandler.redirectWithSetCookie("/index.html", session.getId(), outputStream); + } + } + + private void handleRegisterRequest(String httpMethod, String urlPath) { + if (httpMethod.equals("GET")) { + ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream); + return; + } + String body = httpRequest.getBody(); + if (body != null) { + String account = body.split("&")[0].split("=")[1]; + String mail = body.split("&")[1].split("=")[1]; + String password = body.split("&")[2].split("=")[1]; + User user = new User(account, mail, password); + InMemoryUserRepository.save(user); + ResponseHandler.redirect("/index.html", outputStream); + } + } + + private void sendHelloWorldResponse() throws IOException { + String responseBody = "Hello world!"; + String response = String.join("\r\n", + "HTTP/1.1 200 OK", + "Content-Type: text/html;charset=utf-8", + "Content-Length: " + responseBody.getBytes().length, + "", + responseBody); + outputStream.write(response.getBytes()); + outputStream.flush(); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java new file mode 100644 index 0000000000..f286e2861e --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java @@ -0,0 +1,96 @@ +package org.apache.coyote.http11.response; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.techcourse.exception.UncheckedServletException; + +public class ResponseHandler { + + private static final Logger log = LoggerFactory.getLogger(ResponseHandler.class); + + public static void printFileResource(String fileName, OutputStream outputStream) { + final URL url = ResponseHandler.class.getClassLoader().getResource(fileName); + if (url == null) { + sendNotFoundResponse(outputStream); + return; + } + try { + File file = new File(url.getPath()); + String contentType = determineContentType(fileName); + String responseBody = new String(Files.readAllBytes(file.toPath())); + String response = String.join("\r\n", + "HTTP/1.1 200 OK", + "Content-Type: " + contentType + ";charset=utf-8", + "Content-Length: " + responseBody.getBytes().length, + "", + responseBody); + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static String determineContentType(String fileName) { + if (fileName.endsWith("css")) { + return "text/css"; + } + if (fileName.endsWith("js")) { + return "application/javascript"; + } + if(fileName.endsWith("html")) { + return "text/html"; + } + return "application/json"; + } + + private static void sendNotFoundResponse(OutputStream outputStream) { + try { + String response = "HTTP/1.1 404 Not Found \r\n" + + "Content-Length: 0 \r\n" + + "\r\n"; + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void redirect(String path, OutputStream outputStream) { + try { + String contentType = "text/html"; + var response = "HTTP/1.1 302 Found \r\n" + + "Location: http://localhost:8080" + path + "\r\n" + + String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + + "Content-Length: 0"; + + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException | UncheckedServletException e) { + log.error(e.getMessage(), e); + } + } + + public static void redirectWithSetCookie(String path, String sessionId, OutputStream outputStream) { + try { + String contentType = "text/html"; + var response = "HTTP/1.1 302 Found \r\n" + + "Set-Cookie: JSESSIONID=" + sessionId + " \r\n" + + "Location: http://localhost:8080" + path + " \r\n" + + String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + + "Content-Length: 0"; + + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException | UncheckedServletException e) { + log.error(e.getMessage(), e); + } + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java new file mode 100644 index 0000000000..ebce4c6da0 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -0,0 +1,43 @@ +package org.apache.coyote.http11.session; + +import java.util.Arrays; +import java.util.Objects; +import java.util.UUID; + +import org.apache.coyote.http11.request.HttpRequest; + +public class Session { + public static final String SESSION_HEADER_KEY = "JSESSIONID"; + private final String id; + + public Session() { + this.id = UUID.randomUUID().toString(); + } + + public Session(HttpRequest httpRequest) { + this.id = Arrays.asList(httpRequest.getCookie().split("; ")) + .stream() + .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) + .findAny() + .orElseGet(null); + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Session session = (Session)o; + return Objects.equals(id, session.id); + } + + @Override + public int hashCode() { + return Objects.hashCode(id); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java new file mode 100644 index 0000000000..040a07fa0b --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java @@ -0,0 +1,21 @@ +package org.apache.coyote.http11.session; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import com.techcourse.model.User; + +public final class SessionManager { + private static final Map sessions = new HashMap<>(); + + public static Session createSession(User user) { + Session session = new Session(); + sessions.put(session, user); + return session; + } + + public static Optional findUserBySession(Session session) { + return Optional.ofNullable(sessions.get(session)); + } +} diff --git a/tomcat/src/main/resources/static/login.html b/tomcat/src/main/resources/static/login.html index f4ed9de875..bc933357f2 100644 --- a/tomcat/src/main/resources/static/login.html +++ b/tomcat/src/main/resources/static/login.html @@ -20,7 +20,7 @@

로그인

-
+
From dad03dc8fb15077a78e9e9661a0ce8be73f3e8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 16:43:03 +0900 Subject: [PATCH 04/49] =?UTF-8?q?refactor:=20Method,=20Body,=20Path=20?= =?UTF-8?q?=EB=A5=BC=20VO=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/request/Body.java | 24 +++++++++++ .../apache/coyote/http11/request/Headers.java | 23 ++++++++++ .../coyote/http11/request/HttpRequest.java | 42 ++++++------------- .../apache/coyote/http11/request/Method.java | 9 ++++ .../apache/coyote/http11/request/Path.java | 9 ++++ 5 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Body.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Method.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/Path.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Body.java new file mode 100644 index 0000000000..d64f1e3067 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Body.java @@ -0,0 +1,24 @@ +package org.apache.coyote.http11.request; + +import java.io.BufferedReader; +import java.io.IOException; + +public class Body { + private static final String CONTENT_LENGTH = "Content-Length"; + + private final String value; + + public Body(Headers headers, BufferedReader reader) throws IOException { + this.value = parseBody(headers, reader); + } + + private String parseBody(Headers headers, BufferedReader reader) throws IOException { + int contentLength = Integer.parseInt(headers.getValue(CONTENT_LENGTH)); + if(contentLength > 0) { + char[] body = new char[contentLength]; + reader.read(body, 0, contentLength); + return new String(body); + } + return null; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java new file mode 100644 index 0000000000..83fc97f339 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java @@ -0,0 +1,23 @@ +package org.apache.coyote.http11.request; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class Headers { + private final Map headers; + + public Headers(BufferedReader reader) throws IOException { + this.headers = new HashMap<>(); + String line; + while ((line = reader.readLine()) != null && !line.isEmpty()) { + String[] header = line.split(":"); + headers.put(header[0].trim(), header[1].trim()); + } + } + + public String getValue(String key) { + return headers.get(key); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index aaf2d5f417..b7cd1dc5c5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -7,51 +7,33 @@ public class HttpRequest { - private static final String CONTENT_LENGTH = "Content-Length"; - private final String method; - private final String path; - private final Map headers = new HashMap<>(); - private final String body; + private final Method method; + private final Path path; + private final Headers headers; + private final Body body; public HttpRequest(BufferedReader reader) throws IOException { String initialLine = reader.readLine(); - this.method = initialLine.split(" ")[0]; - this.path = initialLine.split(" ")[1]; - String line; - while ((line = reader.readLine()) != null && !line.isEmpty()) { - String[] header = line.split(":"); - headers.put(header[0].trim(), header[1].trim()); - } - this.body = parseBody(reader); + this.method = new Method(initialLine); + this.path = new Path(initialLine); + this.headers = new Headers(reader); + this.body = new Body(headers, reader); } - private String parseBody(BufferedReader reader) throws IOException { - if(headers.get(CONTENT_LENGTH) == null) { - return null; - } - int contentLength = Integer.parseInt(headers.get(CONTENT_LENGTH)); - if(contentLength > 0) { - char[] body = new char[contentLength]; - reader.read(body, 0, contentLength); - return new String(body); - } - return null; - } - - public String getMethod() { + public Method getMethod() { return method; } - public String getPath() { + public Path getPath() { return path; } public String getCookie() { - return headers.get("Cookie"); + return headers.getValue("Cookie"); } - public String getBody() { + public Body getBody() { return body; } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java new file mode 100644 index 0000000000..25b2bdd690 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.request; + +public class Method { + private final String value; + + public Method(String initialLine) { + this.value = initialLine.split(" ")[0]; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java new file mode 100644 index 0000000000..91ae59b500 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.request; + +public class Path { + private final String value; + + public Path(String initialLine) { + this.value = initialLine.split(" ")[1]; + } +} From b918e81a0da4eda500ffabf6426ae0cd82d40ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 17:05:18 +0900 Subject: [PATCH 05/49] =?UTF-8?q?refactor:=20HttpResponse=EC=99=80=20?= =?UTF-8?q?=ED=95=98=EC=9C=84=20=EC=9A=94=EC=86=8C=EB=93=A4=EC=9D=84=20VO?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/{request => common}/Body.java | 2 +- .../http11/{request => common}/Headers.java | 6 ++++- .../http11/common/VersionOfProtocol.java | 9 ++++++++ .../coyote/http11/request/HttpRequest.java | 7 +++--- .../coyote/http11/response/HttpResponse.java | 23 +++++++++++++++++++ .../coyote/http11/response/StatusCode.java | 9 ++++++++ .../coyote/http11/response/StatusMessage.java | 9 ++++++++ 7 files changed, 59 insertions(+), 6 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/{request => common}/Body.java (93%) rename tomcat/src/main/java/org/apache/coyote/http11/{request => common}/Headers.java (81%) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java similarity index 93% rename from tomcat/src/main/java/org/apache/coyote/http11/request/Body.java rename to tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index d64f1e3067..1a273f0822 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.request; +package org.apache.coyote.http11.common; import java.io.BufferedReader; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java similarity index 81% rename from tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java rename to tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 83fc97f339..83be28f5b7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.request; +package org.apache.coyote.http11.common; import java.io.BufferedReader; import java.io.IOException; @@ -8,6 +8,10 @@ public class Headers { private final Map headers; + public Headers(Map headers) { + this.headers = headers; + } + public Headers(BufferedReader reader) throws IOException { this.headers = new HashMap<>(); String line; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java new file mode 100644 index 0000000000..81605a86a0 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.common; + +public class VersionOfProtocol { + private final String value; + + public VersionOfProtocol(String initialLine) { + this.value = initialLine.split(" ")[0]; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index b7cd1dc5c5..a5971a293f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -2,12 +2,11 @@ import java.io.BufferedReader; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class HttpRequest { +import org.apache.coyote.http11.common.Body; +import org.apache.coyote.http11.common.Headers; +public class HttpRequest { private final Method method; private final Path path; private final Headers headers; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java new file mode 100644 index 0000000000..8ac3a90cb6 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -0,0 +1,23 @@ +package org.apache.coyote.http11.response; + +import org.apache.coyote.http11.common.Headers; +import org.apache.coyote.http11.common.VersionOfProtocol; + +public class HttpResponse { + private final VersionOfProtocol versionOfProtocol; + private final StatusCode statusCode; + private final StatusMessage statusMessage; + private final Headers headers; + + public HttpResponse( + VersionOfProtocol versionOfProtocol, + StatusCode statusCode, + StatusMessage statusMessage, + Headers headers + ) { + this.versionOfProtocol = versionOfProtocol; + this.statusCode = statusCode; + this.statusMessage = statusMessage; + this.headers = headers; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java new file mode 100644 index 0000000000..ea49d6ccd9 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.response; + +public class StatusCode { + private final int value; + + public StatusCode(String initialLine) { + this.value = Integer.parseInt(initialLine.split(" ")[1]); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java new file mode 100644 index 0000000000..66340c0d4c --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java @@ -0,0 +1,9 @@ +package org.apache.coyote.http11.response; + +public class StatusMessage { + private final String value; + + public StatusMessage(String initialLine) { + this.value = initialLine.split(" ")[2]; + } +} From 810f9ded021a5a6ea935f34053ab8beb81b91b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 17:41:09 +0900 Subject: [PATCH 06/49] =?UTF-8?q?refactor:=20HttpResponse=EB=A5=BC=20?= =?UTF-8?q?=ED=99=9C=EC=9A=A9=ED=95=B4=20=EC=9D=91=EB=8B=B5=EC=9D=84=20?= =?UTF-8?q?=EB=B3=B4=EB=82=B4=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/Body.java | 10 ++-- .../apache/coyote/http11/common/Headers.java | 4 ++ .../http11/common/VersionOfProtocol.java | 7 ++- .../coyote/http11/response/HttpResponse.java | 44 +++++++++++++---- .../http11/response/ResponseHandler.java | 47 ++++++++----------- .../coyote/http11/response/StatusCode.java | 7 ++- .../coyote/http11/response/StatusMessage.java | 7 ++- 7 files changed, 75 insertions(+), 51 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 1a273f0822..107fbcf973 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -8,11 +8,15 @@ public class Body { private final String value; - public Body(Headers headers, BufferedReader reader) throws IOException { - this.value = parseBody(headers, reader); + public Body(String value) { + this.value = value; } - private String parseBody(Headers headers, BufferedReader reader) throws IOException { + public static Body request(Headers headers, BufferedReader reader) throws IOException { + return new Body(parseBody(headers, reader)); + } + + private static String parseBody(Headers headers, BufferedReader reader) throws IOException { int contentLength = Integer.parseInt(headers.getValue(CONTENT_LENGTH)); if(contentLength > 0) { char[] body = new char[contentLength]; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 83be28f5b7..bb9781213d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -24,4 +24,8 @@ public Headers(BufferedReader reader) throws IOException { public String getValue(String key) { return headers.get(key); } + + public Map getHeaders() { + return headers; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 81605a86a0..5a1729885b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -1,9 +1,8 @@ package org.apache.coyote.http11.common; -public class VersionOfProtocol { - private final String value; +public record VersionOfProtocol(String value) { - public VersionOfProtocol(String initialLine) { - this.value = initialLine.split(" ")[0]; + public static VersionOfProtocol request(String initialLine) { + return new VersionOfProtocol(initialLine.split(" ")[0]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 8ac3a90cb6..d88edc00c5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,5 +1,8 @@ package org.apache.coyote.http11.response; +import java.util.Map; + +import org.apache.coyote.http11.common.Body; import org.apache.coyote.http11.common.Headers; import org.apache.coyote.http11.common.VersionOfProtocol; @@ -8,16 +11,41 @@ public class HttpResponse { private final StatusCode statusCode; private final StatusMessage statusMessage; private final Headers headers; + private Body body; public HttpResponse( - VersionOfProtocol versionOfProtocol, - StatusCode statusCode, - StatusMessage statusMessage, - Headers headers + String versionOfProtocol, + int statusCode, + String statusMessage, + Map headers ) { - this.versionOfProtocol = versionOfProtocol; - this.statusCode = statusCode; - this.statusMessage = statusMessage; - this.headers = headers; + this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); + this.statusCode = new StatusCode(statusCode); + this.statusMessage = new StatusMessage(statusMessage); + this.headers = new Headers(headers); + } + + public HttpResponse( + String versionOfProtocol, + int statusCode, + String statusMessage, + Map headers, + String body + ) { + this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); + this.statusCode = new StatusCode(statusCode); + this.statusMessage = new StatusMessage(statusMessage); + this.headers = new Headers(headers); + this.body = new Body(body); + } + + public String toPlainText() { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value())); + headers.getHeaders().forEach((key, value) -> { + sb.append(String.format("%s: %s\r\n", key, value)); + }); + sb.append("\r\n"); + return sb.toString(); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java index f286e2861e..0e807e457a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java @@ -5,6 +5,7 @@ import java.io.OutputStream; import java.net.URL; import java.nio.file.Files; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,26 +17,28 @@ public class ResponseHandler { private static final Logger log = LoggerFactory.getLogger(ResponseHandler.class); public static void printFileResource(String fileName, OutputStream outputStream) { - final URL url = ResponseHandler.class.getClassLoader().getResource(fileName); - if (url == null) { - sendNotFoundResponse(outputStream); - return; - } + URL url = ResponseHandler.class.getClassLoader().getResource(fileName); try { - File file = new File(url.getPath()); - String contentType = determineContentType(fileName); - String responseBody = new String(Files.readAllBytes(file.toPath())); - String response = String.join("\r\n", - "HTTP/1.1 200 OK", - "Content-Type: " + contentType + ";charset=utf-8", - "Content-Length: " + responseBody.getBytes().length, - "", - responseBody); - outputStream.write(response.getBytes()); + HttpResponse httpResponse = generateHttpResponse(url); + outputStream.write(httpResponse.toPlainText().getBytes()); outputStream.flush(); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); + } + } + + private static HttpResponse generateHttpResponse(URL url) throws IOException { + if (url == null) { + return new HttpResponse( + "HTTP/1.1", 404, "Not Found", Map.of("Content-Length", "0")); } + File file = new File(url.getPath()); + String contentType = determineContentType(fileName); + String responseBody = new String(Files.readAllBytes(file.toPath())); + return new HttpResponse("HTTP/1.1", 200, "OK", + Map.of("Content-Type", contentType + ";charset=utf-8", + "Content-Length", String.valueOf(responseBody.getBytes().length)), + responseBody); } private static String determineContentType(String fileName) { @@ -51,18 +54,6 @@ private static String determineContentType(String fileName) { return "application/json"; } - private static void sendNotFoundResponse(OutputStream outputStream) { - try { - String response = "HTTP/1.1 404 Not Found \r\n" + - "Content-Length: 0 \r\n" + - "\r\n"; - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - } - public static void redirect(String path, OutputStream outputStream) { try { String contentType = "text/html"; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java index ea49d6ccd9..e4ec0f1855 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java @@ -1,9 +1,8 @@ package org.apache.coyote.http11.response; -public class StatusCode { - private final int value; +public record StatusCode(int value) { - public StatusCode(String initialLine) { - this.value = Integer.parseInt(initialLine.split(" ")[1]); + public static StatusCode request(String initialLine) { + return new StatusCode(Integer.parseInt(initialLine.split(" ")[1])); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java index 66340c0d4c..bd92afaa79 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java @@ -1,9 +1,8 @@ package org.apache.coyote.http11.response; -public class StatusMessage { - private final String value; +public record StatusMessage(String value) { - public StatusMessage(String initialLine) { - this.value = initialLine.split(" ")[2]; + public static StatusMessage request(String initialLine) { + return new StatusMessage(initialLine.split(" ")[2]); } } From e1071c200c6f531c75cf96e20d4f35001c4b5173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 17:49:51 +0900 Subject: [PATCH 07/49] =?UTF-8?q?refactor:=20Content-Type=EC=9D=84=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=9C=84?= =?UTF-8?q?=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/common/ContentType.java | 28 ++++++++++ .../http11/response/ResponseHandler.java | 51 ++++++++++--------- 2 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java new file mode 100644 index 0000000000..9ded1cec0f --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java @@ -0,0 +1,28 @@ +package org.apache.coyote.http11.common; + +public enum ContentType { + APPLICATION_JSON("application/json"), + TEXT_CSS("text/css"), + TEXT_HTML("text/html"), + APPLICATION_JAVASCRIPT("text/javascript"), + ; + + private final String value; + + ContentType(String value) { + this.value = value; + } + + public static ContentType fromPath(String path) { + if (path.endsWith("css")) { + return ContentType.TEXT_CSS; + } + if (path.endsWith("js")) { + return ContentType.APPLICATION_JSON; + } + if (path.endsWith("html")) { + return ContentType.TEXT_HTML; + } + return ContentType.APPLICATION_JSON; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java index 0e807e457a..04f89063d1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java @@ -7,6 +7,7 @@ import java.nio.file.Files; import java.util.Map; +import org.apache.coyote.http11.common.ContentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +24,7 @@ public static void printFileResource(String fileName, OutputStream outputStream) outputStream.write(httpResponse.toPlainText().getBytes()); outputStream.flush(); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } } @@ -33,7 +34,7 @@ private static HttpResponse generateHttpResponse(URL url) throws IOException { "HTTP/1.1", 404, "Not Found", Map.of("Content-Length", "0")); } File file = new File(url.getPath()); - String contentType = determineContentType(fileName); + ContentType contentType = ContentType.fromPath(url.getPath()); String responseBody = new String(Files.readAllBytes(file.toPath())); return new HttpResponse("HTTP/1.1", 200, "OK", Map.of("Content-Type", contentType + ";charset=utf-8", @@ -48,40 +49,40 @@ private static String determineContentType(String fileName) { if (fileName.endsWith("js")) { return "application/javascript"; } - if(fileName.endsWith("html")) { + if (fileName.endsWith("html")) { return "text/html"; } return "application/json"; } public static void redirect(String path, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Location: http://localhost:8080" + path + "\r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; + try { + String contentType = "text/html"; + var response = "HTTP/1.1 302 Found \r\n" + + "Location: http://localhost:8080" + path + "\r\n" + + String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + + "Content-Length: 0"; - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException | UncheckedServletException e) { + log.error(e.getMessage(), e); } } public static void redirectWithSetCookie(String path, String sessionId, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Set-Cookie: JSESSIONID=" + sessionId + " \r\n" + - "Location: http://localhost:8080" + path + " \r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; + try { + String contentType = "text/html"; + var response = "HTTP/1.1 302 Found \r\n" + + "Set-Cookie: JSESSIONID=" + sessionId + " \r\n" + + "Location: http://localhost:8080" + path + " \r\n" + + String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + + "Content-Length: 0"; - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); - } + outputStream.write(response.getBytes()); + outputStream.flush(); + } catch (IOException | UncheckedServletException e) { + log.error(e.getMessage(), e); + } } } From f480e0edf851d290e28e95c6541138194dbf09c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 17:52:20 +0900 Subject: [PATCH 08/49] =?UTF-8?q?refactor:=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EB=B3=B8=EB=AC=B8=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=B6=80=EB=B6=84=EC=9D=84=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=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 --- .../org/apache/coyote/http11/common/Body.java | 10 +++++++++- .../http11/response/ResponseHandler.java | 20 ++++--------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 107fbcf973..19ed50b3c2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -18,11 +18,19 @@ public static Body request(Headers headers, BufferedReader reader) throws IOExce private static String parseBody(Headers headers, BufferedReader reader) throws IOException { int contentLength = Integer.parseInt(headers.getValue(CONTENT_LENGTH)); - if(contentLength > 0) { + if (contentLength > 0) { char[] body = new char[contentLength]; reader.read(body, 0, contentLength); return new String(body); } return null; } + + public int getContentLength() { + return this.value.getBytes().length; + } + + public String getValue() { + return value; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java index 04f89063d1..9afca67d8c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java @@ -7,6 +7,7 @@ import java.nio.file.Files; import java.util.Map; +import org.apache.coyote.http11.common.Body; import org.apache.coyote.http11.common.ContentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,24 +36,11 @@ private static HttpResponse generateHttpResponse(URL url) throws IOException { } File file = new File(url.getPath()); ContentType contentType = ContentType.fromPath(url.getPath()); - String responseBody = new String(Files.readAllBytes(file.toPath())); + Body body = new Body(new String(Files.readAllBytes(file.toPath()))); return new HttpResponse("HTTP/1.1", 200, "OK", Map.of("Content-Type", contentType + ";charset=utf-8", - "Content-Length", String.valueOf(responseBody.getBytes().length)), - responseBody); - } - - private static String determineContentType(String fileName) { - if (fileName.endsWith("css")) { - return "text/css"; - } - if (fileName.endsWith("js")) { - return "application/javascript"; - } - if (fileName.endsWith("html")) { - return "text/html"; - } - return "application/json"; + "Content-Length", String.valueOf(body.getContentLength())), + body.getValue()); } public static void redirect(String path, OutputStream outputStream) { From 001bebdb9d57af82663d580667a0f3b5a77281b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 17:57:25 +0900 Subject: [PATCH 09/49] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=EC=99=80=20=EC=9A=94=EC=B2=AD=20HTTP=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=9A=A9=20=EC=A0=95=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=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/Http11Processor.java | 73 ++++++++----------- .../org/apache/coyote/http11/common/Body.java | 11 +-- .../apache/coyote/http11/common/Headers.java | 5 +- .../coyote/http11/request/HttpRequest.java | 8 +- .../apache/coyote/http11/request/Method.java | 7 +- .../apache/coyote/http11/request/Path.java | 7 +- .../http11/response/ResponseHandler.java | 2 +- 7 files changed, 45 insertions(+), 68 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 390db0c886..d244bf65c5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,62 +1,49 @@ package org.apache.coyote.http11; - -import com.techcourse.db.InMemoryUserRepository; -import com.techcourse.exception.UncheckedServletException; -import com.techcourse.model.User; - -import org.apache.coyote.Processor; -import org.apache.coyote.http11.request.HttpRequest; -import org.apache.coyote.http11.request.RequestHandler; -import org.apache.coyote.http11.session.SessionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStream; import java.net.Socket; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.Optional; + +import org.apache.coyote.Processor; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.request.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { - private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); + private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); - private final Socket connection; - private static final Map httpRequestHeader = new HashMap<>(); - private static final String sessionId = "JSESSIONID=sessionId"; + private final Socket connection; + private static final Map httpRequestHeader = new HashMap<>(); + private static final String sessionId = "JSESSIONID=sessionId"; - public Http11Processor(final Socket connection) { - this.connection = connection; - } + public Http11Processor(final Socket connection) { + this.connection = connection; + } - @Override - public void run() { - log.info("connect host: {}, port: {}", connection.getInetAddress(), connection.getPort()); - process(connection); - } + @Override + public void run() { + log.info("connect host: {}, port: {}", connection.getInetAddress(), connection.getPort()); + process(connection); + } - @Override - public void process(final Socket connection) { - try (final var inputStream = connection.getInputStream(); - final var outputStream = connection.getOutputStream()) { + @Override + public void process(final Socket connection) { + try (final var inputStream = connection.getInputStream(); + final var outputStream = connection.getOutputStream()) { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - HttpRequest httpRequest = new HttpRequest(reader); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + HttpRequest httpRequest = new HttpRequest(reader); - RequestHandler requestHandler = new RequestHandler(httpRequest, outputStream); - requestHandler.handleRequest(); + RequestHandler requestHandler = new RequestHandler(httpRequest, outputStream); + requestHandler.handleRequest(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 19ed50b3c2..756e9a3c3e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -3,15 +3,9 @@ import java.io.BufferedReader; import java.io.IOException; -public class Body { +public record Body(String value) { private static final String CONTENT_LENGTH = "Content-Length"; - private final String value; - - public Body(String value) { - this.value = value; - } - public static Body request(Headers headers, BufferedReader reader) throws IOException { return new Body(parseBody(headers, reader)); } @@ -30,7 +24,4 @@ public int getContentLength() { return this.value.getBytes().length; } - public String getValue() { - return value; - } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index bb9781213d..b1e3075bc6 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -12,13 +12,14 @@ public Headers(Map headers) { this.headers = headers; } - public Headers(BufferedReader reader) throws IOException { - this.headers = new HashMap<>(); + public static Headers request(BufferedReader reader) throws IOException { + HashMap headers = new HashMap<>(); String line; while ((line = reader.readLine()) != null && !line.isEmpty()) { String[] header = line.split(":"); headers.put(header[0].trim(), header[1].trim()); } + return new Headers(headers); } public String getValue(String key) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index a5971a293f..6b34996532 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -14,10 +14,10 @@ public class HttpRequest { public HttpRequest(BufferedReader reader) throws IOException { String initialLine = reader.readLine(); - this.method = new Method(initialLine); - this.path = new Path(initialLine); - this.headers = new Headers(reader); - this.body = new Body(headers, reader); + this.method = Method.request(initialLine); + this.path = Path.request(initialLine); + this.headers = Headers.request(reader); + this.body = Body.request(headers, reader); } public Method getMethod() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index 25b2bdd690..7fad1e0104 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -1,9 +1,8 @@ package org.apache.coyote.http11.request; -public class Method { - private final String value; +public record Method(String value) { - public Method(String initialLine) { - this.value = initialLine.split(" ")[0]; + public static Method request(String initialLine) { + return new Method(initialLine.split(" ")[0]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 91ae59b500..c5f3412782 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -1,9 +1,8 @@ package org.apache.coyote.http11.request; -public class Path { - private final String value; +public record Path(String value) { - public Path(String initialLine) { - this.value = initialLine.split(" ")[1]; + public static Path request(String initialLine) { + return new Path(initialLine.split(" ")[1]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java index 9afca67d8c..c71fc43c20 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java @@ -40,7 +40,7 @@ private static HttpResponse generateHttpResponse(URL url) throws IOException { return new HttpResponse("HTTP/1.1", 200, "OK", Map.of("Content-Type", contentType + ";charset=utf-8", "Content-Length", String.valueOf(body.getContentLength())), - body.getValue()); + body.value()); } public static void redirect(String path, OutputStream outputStream) { From 44c993c4f0e8ef5e1e97f602562eeda98f3a9d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Tue, 10 Sep 2024 18:00:19 +0900 Subject: [PATCH 10/49] =?UTF-8?q?refactor:=20initialLine=EC=9D=84=20reques?= =?UTF-8?q?tLine=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/common/VersionOfProtocol.java | 4 ++-- .../http11/controller/AbstractController.java | 20 +++++++++++++++++++ .../coyote/http11/controller/Controller.java | 8 ++++++++ .../coyote/http11/request/HttpRequest.java | 6 +++--- .../apache/coyote/http11/request/Method.java | 4 ++-- .../apache/coyote/http11/request/Path.java | 4 ++-- .../coyote/http11/response/StatusCode.java | 4 ++-- .../coyote/http11/response/StatusMessage.java | 4 ++-- 8 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 5a1729885b..6978e88030 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -2,7 +2,7 @@ public record VersionOfProtocol(String value) { - public static VersionOfProtocol request(String initialLine) { - return new VersionOfProtocol(initialLine.split(" ")[0]); + public static VersionOfProtocol request(String requestLine) { + return new VersionOfProtocol(requestLine.split(" ")[0]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java new file mode 100644 index 0000000000..776a83ad8b --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java @@ -0,0 +1,20 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public abstract class AbstractController implements Controller { + + @Override + public void service(HttpRequest request, HttpResponse response) throws Exception { + + } + + protected void doPost(HttpRequest request, HttpResponse response) throws Exception { + + } + + protected void doGet(HttpRequest request, HttpResponse response) throws Exception { + + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java new file mode 100644 index 0000000000..d8b43ed933 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java @@ -0,0 +1,8 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public interface Controller { + void service(HttpRequest request, HttpResponse response) throws Exception; +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 6b34996532..c52ddc066c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -13,9 +13,9 @@ public class HttpRequest { private final Body body; public HttpRequest(BufferedReader reader) throws IOException { - String initialLine = reader.readLine(); - this.method = Method.request(initialLine); - this.path = Path.request(initialLine); + String requestLine = reader.readLine(); + this.method = Method.request(requestLine); + this.path = Path.request(requestLine); this.headers = Headers.request(reader); this.body = Body.request(headers, reader); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index 7fad1e0104..7e38900583 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -2,7 +2,7 @@ public record Method(String value) { - public static Method request(String initialLine) { - return new Method(initialLine.split(" ")[0]); + public static Method request(String requestLine) { + return new Method(requestLine.split(" ")[0]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index c5f3412782..586a71154a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -2,7 +2,7 @@ public record Path(String value) { - public static Path request(String initialLine) { - return new Path(initialLine.split(" ")[1]); + public static Path request(String requestLine) { + return new Path(requestLine.split(" ")[1]); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java index e4ec0f1855..9edb5429ad 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java @@ -2,7 +2,7 @@ public record StatusCode(int value) { - public static StatusCode request(String initialLine) { - return new StatusCode(Integer.parseInt(initialLine.split(" ")[1])); + public static StatusCode request(String requestLine) { + return new StatusCode(Integer.parseInt(requestLine.split(" ")[1])); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java index bd92afaa79..12d392ab74 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java @@ -2,7 +2,7 @@ public record StatusMessage(String value) { - public static StatusMessage request(String initialLine) { - return new StatusMessage(initialLine.split(" ")[2]); + public static StatusMessage request(String requestLine) { + return new StatusMessage(requestLine.split(" ")[2]); } } From 70888603bf30cf63e83f0fb9b3da453b369530c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:22:01 +0900 Subject: [PATCH 11/49] =?UTF-8?q?refactor:=20=EC=84=9C=EB=B8=94=EB=A6=BF?= =?UTF-8?q?=20=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=EC=84=9C=20=EC=9A=94=EC=B2=AD=EC=9D=84=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=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 --- .../org/apache/coyote/http11/Http11Processor.java | 15 +++++++-------- .../coyote/http11/servlet/ServletContainer.java | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.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 d244bf65c5..aaa02e4415 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -4,12 +4,12 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; -import java.util.HashMap; -import java.util.Map; import org.apache.coyote.Processor; import org.apache.coyote.http11.request.HttpRequest; -import org.apache.coyote.http11.request.RequestHandler; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.ResponsePrinter; +import org.apache.coyote.http11.servlet.ServletContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,8 +18,6 @@ public class Http11Processor implements Runnable, Processor { private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; - private static final Map httpRequestHeader = new HashMap<>(); - private static final String sessionId = "JSESSIONID=sessionId"; public Http11Processor(final Socket connection) { this.connection = connection; @@ -37,11 +35,12 @@ public void process(final Socket connection) { final var outputStream = connection.getOutputStream()) { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - HttpRequest httpRequest = new HttpRequest(reader); + HttpRequest request = new HttpRequest(reader); + HttpResponse response = new HttpResponse(); - RequestHandler requestHandler = new RequestHandler(httpRequest, outputStream); - requestHandler.handleRequest(); + new ServletContainer().invoke(request, response); + new ResponsePrinter(outputStream).print(response); } catch (IOException e) { log.error(e.getMessage(), e); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java new file mode 100644 index 0000000000..8e2c605c49 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -0,0 +1,15 @@ +package org.apache.coyote.http11.servlet; + +import java.io.IOException; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public class ServletContainer { + + public void invoke(HttpRequest request, HttpResponse response) throws IOException { + Servlet servlet = new Servlet(); + + servlet.doDispatch(request, response); + } +} From d56668ca1eb8741ce27fa88d54f523cfaf796101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:22:45 +0900 Subject: [PATCH 12/49] =?UTF-8?q?refactor:=20=EB=8F=99=EC=A0=81=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80=ED=95=B4=20=EB=B6=84?= =?UTF-8?q?=EA=B8=B0=ED=95=98=EB=8A=94=20HandlerMapping=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/HandlerMapping.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java new file mode 100644 index 0000000000..488ae89a5a --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java @@ -0,0 +1,21 @@ +package org.apache.coyote.http11.controller; + +import java.util.Map; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.request.Path; + +public class HandlerMapping { + private final Map controllers; + + public HandlerMapping() { + this.controllers = Map.of( + new Path("/login"), new LoginController(), + new Path("/register"), new RegisterController()); + } + + public Controller getController(HttpRequest request) { + Path path = request.getPath(); + return controllers.getOrDefault(path, new StaticController()); + } +} From 85ac473f2aed9447b20e1b415123796f33534412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:23:14 +0900 Subject: [PATCH 13/49] =?UTF-8?q?refactor:=20Servlet=EC=9D=B4=20=EC=A0=81?= =?UTF-8?q?=EC=A0=88=ED=95=9C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= =?UTF-8?q?=EB=A5=BC=20=EA=BA=BC=EB=82=B4=EC=96=B4=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/servlet/Servlet.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java new file mode 100644 index 0000000000..42dc6297b0 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java @@ -0,0 +1,23 @@ +package org.apache.coyote.http11.servlet; + +import java.io.IOException; + +import org.apache.coyote.http11.controller.Controller; +import org.apache.coyote.http11.controller.HandlerMapping; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public class Servlet { + + private final HandlerMapping handlerMapping; + + public Servlet() { + this.handlerMapping = new HandlerMapping(); + } + + public void doDispatch(HttpRequest request, HttpResponse response) throws IOException { + Controller controller = handlerMapping.getController(request); + + controller.service(request, response); + } +} From 6cf4dd3928fe9ea25ca92220777efb842323c9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:24:16 +0900 Subject: [PATCH 14/49] =?UTF-8?q?refactor:=20HttpResponse=20=EB=B9=88=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=9B=84=20=EA=B0=92?= =?UTF-8?q?=EC=9D=84=20=EB=8C=80=EC=9E=85=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=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 --- .../coyote/http11/response/HttpResponse.java | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index d88edc00c5..56e7256fc3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,18 +1,27 @@ package org.apache.coyote.http11.response; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; import java.util.Map; import org.apache.coyote.http11.common.Body; +import org.apache.coyote.http11.common.ContentType; import org.apache.coyote.http11.common.Headers; import org.apache.coyote.http11.common.VersionOfProtocol; public class HttpResponse { - private final VersionOfProtocol versionOfProtocol; - private final StatusCode statusCode; - private final StatusMessage statusMessage; - private final Headers headers; + private VersionOfProtocol versionOfProtocol; + private StatusCode statusCode; + private StatusMessage statusMessage; + private Headers headers; private Body body; + public HttpResponse() { + this.headers = new Headers(); + } + public HttpResponse( String versionOfProtocol, int statusCode, @@ -42,10 +51,43 @@ public HttpResponse( public String toPlainText() { StringBuilder sb = new StringBuilder(); sb.append(String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value())); - headers.getHeaders().forEach((key, value) -> { + headers.headers().forEach((key, value) -> { sb.append(String.format("%s: %s\r\n", key, value)); }); sb.append("\r\n"); return sb.toString(); } + + public void setVersionOfProtocol(String versionOfProtocol) { + this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); + } + + public void setStatusCode(int statusCode) { + this.statusCode = new StatusCode(statusCode); + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = new StatusMessage(statusMessage); + } + + public void setHeaders(Map headers) { + this.headers = new Headers(headers); + } + + public void setBody(String filename) throws IOException { + try { + URL url = HttpResponse.class.getClassLoader().getResource(filename); + File file = new File(url.getPath()); + this.body = new Body(new String(Files.readAllBytes(file.toPath()))); + + ContentType contentType = ContentType.fromPath(url.getPath()); + this.headers.add("Content-Type", contentType.getValue() + ";charset=utf-8"); + this.headers.add("Content-Length", String.valueOf(body.getContentLength())); + } catch (NullPointerException e) { + this.body = new Body("Hello, World!"); + + this.headers.add("Content-Type", "text/plain; charset=utf-8"); + this.headers.add("Content-Length", "0"); + } + } } From 2fdc682f153d347171647aa2be23bacc49071c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:25:22 +0900 Subject: [PATCH 15/49] =?UTF-8?q?refactor:=20=EC=9D=91=EB=8B=B5=EC=9D=84?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20=EC=97=AD=ED=95=A0?= =?UTF-8?q?=EC=9D=84=20=ED=95=98=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=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 --- .../coyote/http11/request/RequestHandler.java | 98 ------------------- .../http11/response/ResponseHandler.java | 76 -------------- .../http11/response/ResponsePrinter.java | 23 +++++ 3 files changed, 23 insertions(+), 174 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java deleted file mode 100644 index 3bd3462836..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.apache.coyote.http11.request; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.coyote.http11.response.ResponseHandler; -import org.apache.coyote.http11.session.Session; -import org.apache.coyote.http11.session.SessionManager; - -import com.techcourse.db.InMemoryUserRepository; -import com.techcourse.model.User; - -public class RequestHandler { - - private final HttpRequest httpRequest; - private final OutputStream outputStream; - - public RequestHandler(HttpRequest httpRequest, OutputStream outputStream) { - this.httpRequest = httpRequest; - this.outputStream = outputStream; - } - - public void handleRequest() throws IOException { - String httpMethod = httpRequest.getMethod(); - String urlPath = httpRequest.getPath(); - - if(urlPath.endsWith("html") || urlPath.endsWith("css") || urlPath.endsWith("js")) { - ResponseHandler.printFileResource("static" + urlPath, outputStream); - } else if (urlPath.startsWith("/login")) { - handleLoginRequest(httpMethod, urlPath); - } else if (urlPath.startsWith("/register")) { - handleRegisterRequest(httpMethod, urlPath); - } else { - sendHelloWorldResponse(); - } - } - - private void handleLoginRequest(String httpMethod, String urlPath) { - if (urlPath.equals("/login") && httpMethod.equals("GET")) { - Session session = new Session(httpRequest); - SessionManager.findUserBySession(session) - .ifPresentOrElse( - user -> ResponseHandler.redirect("/index.html", outputStream), - () -> ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream)); - } else if (httpMethod.equals("POST")) { - login(); - } - } - - private void login() { - String body = httpRequest.getBody(); - if (body != null) { - String account = body.split("&")[0].split("=")[1]; - String password = body.split("&")[1].split("=")[1]; - InMemoryUserRepository.findByAccount(account) - .ifPresentOrElse( - user -> loginUser(user, password), - () -> ResponseHandler.redirect("/401.html", outputStream) - ); - } - ResponseHandler.redirect("/401.html", outputStream); - } - - private void loginUser(User user, String password) { - if (user.checkPassword(password)) { - Session session = SessionManager.createSession(user); - ResponseHandler.redirectWithSetCookie("/index.html", session.getId(), outputStream); - } - } - - private void handleRegisterRequest(String httpMethod, String urlPath) { - if (httpMethod.equals("GET")) { - ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream); - return; - } - String body = httpRequest.getBody(); - if (body != null) { - String account = body.split("&")[0].split("=")[1]; - String mail = body.split("&")[1].split("=")[1]; - String password = body.split("&")[2].split("=")[1]; - User user = new User(account, mail, password); - InMemoryUserRepository.save(user); - ResponseHandler.redirect("/index.html", outputStream); - } - } - - private void sendHelloWorldResponse() throws IOException { - String responseBody = "Hello world!"; - String response = String.join("\r\n", - "HTTP/1.1 200 OK", - "Content-Type: text/html;charset=utf-8", - "Content-Length: " + responseBody.getBytes().length, - "", - responseBody); - outputStream.write(response.getBytes()); - outputStream.flush(); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java deleted file mode 100644 index c71fc43c20..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.apache.coyote.http11.response; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import java.nio.file.Files; -import java.util.Map; - -import org.apache.coyote.http11.common.Body; -import org.apache.coyote.http11.common.ContentType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.techcourse.exception.UncheckedServletException; - -public class ResponseHandler { - - private static final Logger log = LoggerFactory.getLogger(ResponseHandler.class); - - public static void printFileResource(String fileName, OutputStream outputStream) { - URL url = ResponseHandler.class.getClassLoader().getResource(fileName); - try { - HttpResponse httpResponse = generateHttpResponse(url); - outputStream.write(httpResponse.toPlainText().getBytes()); - outputStream.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private static HttpResponse generateHttpResponse(URL url) throws IOException { - if (url == null) { - return new HttpResponse( - "HTTP/1.1", 404, "Not Found", Map.of("Content-Length", "0")); - } - File file = new File(url.getPath()); - ContentType contentType = ContentType.fromPath(url.getPath()); - Body body = new Body(new String(Files.readAllBytes(file.toPath()))); - return new HttpResponse("HTTP/1.1", 200, "OK", - Map.of("Content-Type", contentType + ";charset=utf-8", - "Content-Length", String.valueOf(body.getContentLength())), - body.value()); - } - - public static void redirect(String path, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Location: http://localhost:8080" + path + "\r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; - - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); - } - } - - public static void redirectWithSetCookie(String path, String sessionId, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Set-Cookie: JSESSIONID=" + sessionId + " \r\n" + - "Location: http://localhost:8080" + path + " \r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; - - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); - } - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java new file mode 100644 index 0000000000..990bacac9c --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java @@ -0,0 +1,23 @@ +package org.apache.coyote.http11.response; + +import java.io.IOException; +import java.io.OutputStream; + +public class ResponsePrinter { + + private final OutputStream outputStream; + + public ResponsePrinter(OutputStream outputStream) { + this.outputStream = outputStream; + } + + public void print(HttpResponse response) throws IOException { + String plainText = response.toPlainText(); + try { + outputStream.write(plainText.getBytes()); + outputStream.flush(); + } catch (IOException exception) { + exception.printStackTrace(); + } + } +} From da3030316711befd016352525ced58456db3f231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:25:41 +0900 Subject: [PATCH 16/49] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EC=9D=84=20=EB=8B=B4=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/LoginController.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java new file mode 100644 index 0000000000..0c932bbe79 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java @@ -0,0 +1,59 @@ +package org.apache.coyote.http11.controller; + +import java.io.IOException; +import java.util.Map; +import java.util.Optional; + +import org.apache.coyote.http11.common.Body; +import org.apache.coyote.http11.common.Properties; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.session.Session; +import org.apache.coyote.http11.session.SessionManager; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; + +public class LoginController extends AbstractController { + + @Override + protected void doPost(HttpRequest request, HttpResponse response) { + Body body = request.getBody(); + Properties properties = body.parseProperty(); + + String account = properties.get("account"); + String password = properties.get("password"); + Optional user = InMemoryUserRepository.findByAccount(account); + if (user.isPresent() && user.get().checkPassword(password)) { + Session session = SessionManager.createSession(user.get()); + + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(302); + response.setStatusMessage("Found"); + response.setHeaders(Map.of( + "Set-Cookie", "JSESSIONID=" + session.getId(), + "Location", "http://localhost:8080/401.html" + )); + } + } + + @Override + protected void doGet(HttpRequest request, HttpResponse response) throws IOException { + Session session = new Session(request); + Optional userBySession = SessionManager.findUserBySession(session); + + response.setVersionOfProtocol("HTTP/1.1"); + if (userBySession.isPresent()) { + response.setStatusCode(302); + response.setStatusMessage("Found"); + response.setHeaders(Map.of( + "Location", "http://localhost:8080" + "index.html" + )); + } else { + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(200); + response.setStatusMessage("OK"); + response.setBody("static" + request.getPath().value() + ".html"); + } + } +} From 05d9229aa53891407d6ae627fb657e2b6ff8f68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:25:49 +0900 Subject: [PATCH 17/49] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EC=9D=84=20=EB=8B=B4=EB=8B=B9=ED=95=98=EB=8A=94=20Con?= =?UTF-8?q?troller=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/RegisterController.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java new file mode 100644 index 0000000000..9abbd716ad --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java @@ -0,0 +1,40 @@ +package org.apache.coyote.http11.controller; + +import java.io.IOException; +import java.util.Map; + +import org.apache.coyote.http11.common.Body; +import org.apache.coyote.http11.common.Properties; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; + +public class RegisterController extends AbstractController { + @Override + protected void doPost(HttpRequest request, HttpResponse response) { + Body body = request.getBody(); + Properties properties = body.parseProperty(); + + String account = properties.get("account"); + String mail = properties.get("mail"); + String password = properties.get("password"); + + User user = new User(account, mail, password); + InMemoryUserRepository.save(user); + + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(302); + response.setStatusMessage("Found"); + response.setHeaders(Map.of("Location", "http://localhost:8080/index.html")); + } + + @Override + protected void doGet(HttpRequest request, HttpResponse response) throws IOException { + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(200); + response.setStatusMessage("OK"); + response.setBody("static" + request.getPath().value() + ".html"); + } +} From 0f19b106b3c6a19dd94dd2a7241e1e1e253ecd1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:26:08 +0900 Subject: [PATCH 18/49] =?UTF-8?q?feat:=20=EC=A0=95=EC=A0=81=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B2=98=EB=A6=AC=EB=A5=BC=20=EB=8B=B4=EB=8B=B9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20Controller=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/StaticController.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java new file mode 100644 index 0000000000..537ebfc76c --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java @@ -0,0 +1,20 @@ +package org.apache.coyote.http11.controller; + +import java.io.IOException; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public class StaticController extends AbstractController { + @Override + protected void doPost(HttpRequest request, HttpResponse response) { + } + + @Override + protected void doGet(HttpRequest request, HttpResponse response) throws IOException { + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(200); + response.setStatusMessage("OK"); + response.setBody("static" + request.getPath().value()); + } +} From 62572ca563ec42049819383f1c7f5996f92683c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:26:43 +0900 Subject: [PATCH 19/49] =?UTF-8?q?refactor:=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EB=A5=BC=20=EA=B5=AC=ED=98=84=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=97=90=EA=B2=8C=20=EC=9C=84?= =?UTF-8?q?=EC=9E=84=ED=95=98=EC=97=AC=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/AbstractController.java | 20 +++++++++++-------- .../coyote/http11/controller/Controller.java | 4 +++- .../apache/coyote/http11/request/Method.java | 8 ++++++++ .../apache/coyote/http11/request/Path.java | 17 ++++++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java index 776a83ad8b..4284e52717 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java @@ -1,20 +1,24 @@ package org.apache.coyote.http11.controller; +import java.io.IOException; + import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.request.Method; import org.apache.coyote.http11.response.HttpResponse; public abstract class AbstractController implements Controller { @Override - public void service(HttpRequest request, HttpResponse response) throws Exception { - - } - - protected void doPost(HttpRequest request, HttpResponse response) throws Exception { - + public void service(HttpRequest request, HttpResponse response) throws IOException { + Method method = request.getMethod(); + if (method.isGet()) { + doGet(request, response); + } else if (method.isPost()) { + doPost(request, response); + } } - protected void doGet(HttpRequest request, HttpResponse response) throws Exception { + protected abstract void doPost(HttpRequest request, HttpResponse response); - } + protected abstract void doGet(HttpRequest request, HttpResponse response) throws IOException; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java index d8b43ed933..ee762c8d91 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java @@ -1,8 +1,10 @@ package org.apache.coyote.http11.controller; +import java.io.IOException; + import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; public interface Controller { - void service(HttpRequest request, HttpResponse response) throws Exception; + void service(HttpRequest request, HttpResponse response) throws IOException; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index 7e38900583..4a97fb8af0 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -5,4 +5,12 @@ public record Method(String value) { public static Method request(String requestLine) { return new Method(requestLine.split(" ")[0]); } + + public boolean isGet() { + return value.startsWith("GET"); + } + + public boolean isPost() { + return value.startsWith("POST"); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 586a71154a..60bb5ebc30 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -1,8 +1,25 @@ package org.apache.coyote.http11.request; +import java.util.Objects; + public record Path(String value) { public static Path request(String requestLine) { return new Path(requestLine.split(" ")[1]); } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Path path = (Path)o; + return Objects.equals(value, path.value); + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } } From 4f78f6792b0b2b34655ed8e5183357f2282ca6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 14:27:19 +0900 Subject: [PATCH 20/49] =?UTF-8?q?refactor:=20Body=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=EC=9D=84=20=ED=8C=8C=EC=8B=B1=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20Properties=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=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/common/Body.java | 7 ++++++ .../coyote/http11/common/ContentType.java | 4 ++++ .../apache/coyote/http11/common/Headers.java | 15 ++++++------- .../coyote/http11/common/Properties.java | 22 +++++++++++++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 756e9a3c3e..e40ce1c29b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -2,6 +2,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.Arrays; public record Body(String value) { private static final String CONTENT_LENGTH = "Content-Length"; @@ -24,4 +25,10 @@ public int getContentLength() { return this.value.getBytes().length; } + public Properties parseProperty() { + Properties properties = new Properties(); + Arrays.asList(value.split("&")) + .forEach(properties::add); + return properties; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java index 9ded1cec0f..f2e2b3b323 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java @@ -25,4 +25,8 @@ public static ContentType fromPath(String path) { } return ContentType.APPLICATION_JSON; } + + public String getValue() { + return value; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index b1e3075bc6..dde5612ae7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -5,11 +5,10 @@ import java.util.HashMap; import java.util.Map; -public class Headers { - private final Map headers; +public record Headers(Map headers) { - public Headers(Map headers) { - this.headers = headers; + public Headers() { + this(new HashMap<>()); } public static Headers request(BufferedReader reader) throws IOException { @@ -22,11 +21,11 @@ public static Headers request(BufferedReader reader) throws IOException { return new Headers(headers); } - public String getValue(String key) { - return headers.get(key); + public void add(String key, String value) { + headers.put(key, value); } - public Map getHeaders() { - return headers; + public String getValue(String key) { + return headers.get(key); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java new file mode 100644 index 0000000000..4307e77b7d --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java @@ -0,0 +1,22 @@ +package org.apache.coyote.http11.common; + +import java.util.HashMap; +import java.util.Map; + +public class Properties { + private final Map properties; + + public Properties() { + this.properties = new HashMap<>(); + } + + public void add(String rawProperty) { + String key = rawProperty.split("=")[0]; + String value = rawProperty.split("=")[1]; + this.properties.put(key, value); + } + + public String get(String key) { + return properties.get(key); + } +} From 7228258b3733ad06e63e62ba4b0a2ad25c8f1f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 15:05:45 +0900 Subject: [PATCH 21/49] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EA=B0=80=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/Body.java | 13 +++++++++---- .../http11/controller/LoginController.java | 18 +++++++++--------- .../coyote/http11/request/HttpRequest.java | 9 +++++++++ .../coyote/http11/response/HttpResponse.java | 9 +++++++-- .../apache/coyote/http11/session/Session.java | 8 +++----- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index e40ce1c29b..f48c0da101 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -12,10 +12,15 @@ public static Body request(Headers headers, BufferedReader reader) throws IOExce } private static String parseBody(Headers headers, BufferedReader reader) throws IOException { - int contentLength = Integer.parseInt(headers.getValue(CONTENT_LENGTH)); - if (contentLength > 0) { - char[] body = new char[contentLength]; - reader.read(body, 0, contentLength); + String contentLength = headers.getValue(CONTENT_LENGTH); + if (contentLength == null) { + return null; + } + + int length = Integer.parseInt(contentLength); + if (length > 0) { + char[] body = new char[length]; + reader.read(body, 0, length); return new String(body); } return null; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java index 0c932bbe79..bbac81af2a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java @@ -39,21 +39,21 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { - Session session = new Session(request); - Optional userBySession = SessionManager.findUserBySession(session); + Session session = request.getSession(); - response.setVersionOfProtocol("HTTP/1.1"); - if (userBySession.isPresent()) { + if (session == null || SessionManager.findUserBySession(session).isEmpty()) { + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(200); + response.setStatusMessage("OK"); + response.setBody("static" + request.getPath().value() + ".html"); + + } else { + response.setVersionOfProtocol("HTTP/1.1"); response.setStatusCode(302); response.setStatusMessage("Found"); response.setHeaders(Map.of( "Location", "http://localhost:8080" + "index.html" )); - } else { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(200); - response.setStatusMessage("OK"); - response.setBody("static" + request.getPath().value() + ".html"); } } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index c52ddc066c..852ea6f897 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -5,6 +5,7 @@ import org.apache.coyote.http11.common.Body; import org.apache.coyote.http11.common.Headers; +import org.apache.coyote.http11.session.Session; public class HttpRequest { private final Method method; @@ -35,4 +36,12 @@ public String getCookie() { public Body getBody() { return body; } + + public Session getSession() { + String cookie = headers.getValue("Cookie"); + if (cookie == null) { + return null; + } + return new Session(cookie); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 56e7256fc3..2c8ac6cde3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.IOException; import java.net.URL; +import java.nio.file.AccessDeniedException; import java.nio.file.Files; import java.util.Map; @@ -55,6 +56,10 @@ public String toPlainText() { sb.append(String.format("%s: %s\r\n", key, value)); }); sb.append("\r\n"); + if (body != null) { + sb.append(body.value()); + sb.append("\r\n"); + } return sb.toString(); } @@ -83,11 +88,11 @@ public void setBody(String filename) throws IOException { ContentType contentType = ContentType.fromPath(url.getPath()); this.headers.add("Content-Type", contentType.getValue() + ";charset=utf-8"); this.headers.add("Content-Length", String.valueOf(body.getContentLength())); - } catch (NullPointerException e) { + } catch (AccessDeniedException | NullPointerException exception) { this.body = new Body("Hello, World!"); this.headers.add("Content-Type", "text/plain; charset=utf-8"); - this.headers.add("Content-Length", "0"); + this.headers.add("Content-Length", String.valueOf(body.getContentLength())); } } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index ebce4c6da0..ba368a1ef1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -4,18 +4,16 @@ import java.util.Objects; import java.util.UUID; -import org.apache.coyote.http11.request.HttpRequest; - public class Session { public static final String SESSION_HEADER_KEY = "JSESSIONID"; private final String id; public Session() { - this.id = UUID.randomUUID().toString(); + this.id = UUID.randomUUID().toString(); } - public Session(HttpRequest httpRequest) { - this.id = Arrays.asList(httpRequest.getCookie().split("; ")) + public Session(String cookies) { + this.id = Arrays.asList(cookies.split("; ")) .stream() .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) .findAny() From e437b2cc40f052d08c8dd7397c5d529c6b88d55b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 15:17:31 +0900 Subject: [PATCH 22/49] =?UTF-8?q?fix:=20=EC=84=B8=EC=85=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EA=B0=80=20=EC=A1=B0=ED=9A=8C=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=ED=98=84=EC=83=81=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/controller/LoginController.java | 2 +- .../java/org/apache/coyote/http11/session/Session.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java index bbac81af2a..e762539fb0 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java @@ -32,7 +32,7 @@ protected void doPost(HttpRequest request, HttpResponse response) { response.setStatusMessage("Found"); response.setHeaders(Map.of( "Set-Cookie", "JSESSIONID=" + session.getId(), - "Location", "http://localhost:8080/401.html" + "Location", "http://localhost:8080/index.html" )); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index ba368a1ef1..7bea1e7434 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -13,11 +13,16 @@ public Session() { } public Session(String cookies) { - this.id = Arrays.asList(cookies.split("; ")) + String session = Arrays.asList(cookies.split("; ")) .stream() .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) .findAny() .orElseGet(null); + if (session != null) { + this.id = session.substring(SESSION_HEADER_KEY.length() + 1); + } else { + this.id = null; + } } public String getId() { From e6ec7d1dde6dc3db08f2ec4fa55d250cba0202c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 15:22:02 +0900 Subject: [PATCH 23/49] =?UTF-8?q?fix:=20=EC=8B=A4=ED=8C=A8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/LoginController.java | 2 +- .../coyote/http11/response/HttpResponse.java | 6 +- .../coyote/http11/Http11ProcessorTest.java | 99 ++++++++++--------- 3 files changed, 54 insertions(+), 53 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java index e762539fb0..96487acda2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java @@ -52,7 +52,7 @@ protected void doGet(HttpRequest request, HttpResponse response) throws IOExcept response.setStatusCode(302); response.setStatusMessage("Found"); response.setHeaders(Map.of( - "Location", "http://localhost:8080" + "index.html" + "Location", "http://localhost:8080/index.html" )); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 2c8ac6cde3..6a423dda94 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -53,12 +53,12 @@ public String toPlainText() { StringBuilder sb = new StringBuilder(); sb.append(String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value())); headers.headers().forEach((key, value) -> { - sb.append(String.format("%s: %s\r\n", key, value)); + sb.append(String.format("%s: %s \r\n", key, value)); }); sb.append("\r\n"); if (body != null) { sb.append(body.value()); - sb.append("\r\n"); + // sb.append("\r\n"); } return sb.toString(); } @@ -91,7 +91,7 @@ public void setBody(String filename) throws IOException { } catch (AccessDeniedException | NullPointerException exception) { this.body = new Body("Hello, World!"); - this.headers.add("Content-Type", "text/plain; charset=utf-8"); + this.headers.add("Content-Type", "text/html;charset=utf-8"); this.headers.add("Content-Length", String.valueOf(body.getContentLength())); } } 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..74ae4353d8 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -1,61 +1,62 @@ package org.apache.coyote.http11; -import org.junit.jupiter.api.Test; -import support.StubSocket; +import static org.assertj.core.api.Assertions.*; 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 { - @Test - void process() { - // given - final var socket = new StubSocket(); - final var 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 - void index() throws IOException { - // given - final String httpRequest= String.join("\r\n", - "GET /index.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 - final URL resource = getClass().getClassLoader().getResource("static/index.html"); - 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"+ - new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - - assertThat(socket.output()).isEqualTo(expected); - } + @Test + void process() { + // given + final var socket = new StubSocket(); + final var processor = new Http11Processor(socket); + + // when + processor.process(socket); + + // then + var expected = String.join("\r\n", + "HTTP/1.1 200 OK ", + "Content-Length: 13 ", + "Content-Type: text/html;charset=utf-8 ", + "", + "Hello, World!"); + + assertThat(socket.output()).isEqualTo(expected); + } + + @Test + void index() throws IOException { + // given + final String httpRequest = String.join("\r\n", + "GET /index.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 + final URL resource = getClass().getClassLoader().getResource("static/index.html"); + 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" + + new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + + assertThat(socket.output()).isEqualTo(expected); + } } From 4da748d5fadd16b16a967f16f46d95bc5f5b2535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 17:30:50 +0900 Subject: [PATCH 24/49] =?UTF-8?q?feat:=20Executors=EB=A1=9C=20Thread=20Poo?= =?UTF-8?q?l=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/catalina/connector/Connector.java | 13 +++++++++---- .../apache/coyote/http11/response/HttpResponse.java | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/catalina/connector/Connector.java b/tomcat/src/main/java/org/apache/catalina/connector/Connector.java index 3b2c4dda7c..4a0afb46b3 100644 --- a/tomcat/src/main/java/org/apache/catalina/connector/Connector.java +++ b/tomcat/src/main/java/org/apache/catalina/connector/Connector.java @@ -8,24 +8,29 @@ import java.io.UncheckedIOException; import java.net.ServerSocket; import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class Connector implements Runnable { private static final Logger log = LoggerFactory.getLogger(Connector.class); private static final int DEFAULT_PORT = 8080; - private static final int DEFAULT_ACCEPT_COUNT = 100; + private static final int DEFAULT_ACCEPT_COUNT = 100; + private static final int DEFAULT_THREAD_COUNT = 250; private final ServerSocket serverSocket; private boolean stopped; + private final ExecutorService executorService; public Connector() { - this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT); + this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT, DEFAULT_THREAD_COUNT); } - public Connector(final int port, final int acceptCount) { + public Connector(final int port, final int acceptCount, final int maxThreads) { this.serverSocket = createServerSocket(port, acceptCount); this.stopped = false; + this.executorService = Executors.newFixedThreadPool(maxThreads); } private ServerSocket createServerSocket(final int port, final int acceptCount) { @@ -67,7 +72,7 @@ private void process(final Socket connection) { return; } var processor = new Http11Processor(connection); - new Thread(processor).start(); + this.executorService.execute(processor); } public void stop() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 6a423dda94..b9b33a3dd5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -58,7 +58,6 @@ public String toPlainText() { sb.append("\r\n"); if (body != null) { sb.append(body.value()); - // sb.append("\r\n"); } return sb.toString(); } From 20e4d687eeace15a5d7091cb52760088cd6c768d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 18:31:52 +0900 Subject: [PATCH 25/49] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=EC=9D=98?= =?UTF-8?q?=20Controller=EB=A1=9C=20=EB=AA=85=EB=AA=85=ED=95=9C=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=9D=B4=EB=A6=84=EC=9D=84=20Ser?= =?UTF-8?q?vlet=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/common/Properties.java | 6 +++-- ...ctController.java => AbstractServlet.java} | 2 +- .../http11/controller/HandlerMapping.java | 21 ----------------- ...LoginController.java => LoginServlet.java} | 2 +- ...erController.java => RegisterServlet.java} | 2 +- .../{Controller.java => Servlet.java} | 2 +- ...aticController.java => StaticServlet.java} | 2 +- .../apache/coyote/http11/servlet/Servlet.java | 23 ------------------- .../http11/servlet/ServletContainer.java | 18 +++++++++++++-- .../apache/coyote/http11/session/Session.java | 3 +++ 10 files changed, 28 insertions(+), 53 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/controller/{AbstractController.java => AbstractServlet.java} (91%) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java rename tomcat/src/main/java/org/apache/coyote/http11/controller/{LoginController.java => LoginServlet.java} (96%) rename tomcat/src/main/java/org/apache/coyote/http11/controller/{RegisterController.java => RegisterServlet.java} (95%) rename tomcat/src/main/java/org/apache/coyote/http11/controller/{Controller.java => Servlet.java} (89%) rename tomcat/src/main/java/org/apache/coyote/http11/controller/{StaticController.java => StaticServlet.java} (90%) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java index 4307e77b7d..abb663a92e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java @@ -4,6 +4,8 @@ import java.util.Map; public class Properties { + public static final String DELIMITER = "="; + private final Map properties; public Properties() { @@ -11,8 +13,8 @@ public Properties() { } public void add(String rawProperty) { - String key = rawProperty.split("=")[0]; - String value = rawProperty.split("=")[1]; + String key = rawProperty.split(DELIMITER)[0]; + String value = rawProperty.split(DELIMITER)[1]; this.properties.put(key, value); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java similarity index 91% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java rename to tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java index 4284e52717..37edeb1b2a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java @@ -6,7 +6,7 @@ import org.apache.coyote.http11.request.Method; import org.apache.coyote.http11.response.HttpResponse; -public abstract class AbstractController implements Controller { +public abstract class AbstractServlet implements Servlet { @Override public void service(HttpRequest request, HttpResponse response) throws IOException { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java deleted file mode 100644 index 488ae89a5a..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/HandlerMapping.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.apache.coyote.http11.controller; - -import java.util.Map; - -import org.apache.coyote.http11.request.HttpRequest; -import org.apache.coyote.http11.request.Path; - -public class HandlerMapping { - private final Map controllers; - - public HandlerMapping() { - this.controllers = Map.of( - new Path("/login"), new LoginController(), - new Path("/register"), new RegisterController()); - } - - public Controller getController(HttpRequest request) { - Path path = request.getPath(); - return controllers.getOrDefault(path, new StaticController()); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java similarity index 96% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java rename to tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java index 96487acda2..d3e1f55594 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java @@ -14,7 +14,7 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; -public class LoginController extends AbstractController { +public class LoginServlet extends AbstractServlet { @Override protected void doPost(HttpRequest request, HttpResponse response) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java similarity index 95% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java rename to tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java index 9abbd716ad..4d38bef995 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java @@ -11,7 +11,7 @@ import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; -public class RegisterController extends AbstractController { +public class RegisterServlet extends AbstractServlet { @Override protected void doPost(HttpRequest request, HttpResponse response) { Body body = request.getBody(); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java similarity index 89% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java rename to tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java index ee762c8d91..96f3fa5ea1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java @@ -5,6 +5,6 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; -public interface Controller { +public interface Servlet { void service(HttpRequest request, HttpResponse response) throws IOException; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java similarity index 90% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java rename to tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java index 537ebfc76c..e0d4716e91 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java @@ -5,7 +5,7 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; -public class StaticController extends AbstractController { +public class StaticServlet extends AbstractServlet { @Override protected void doPost(HttpRequest request, HttpResponse response) { } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java deleted file mode 100644 index 42dc6297b0..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.apache.coyote.http11.servlet; - -import java.io.IOException; - -import org.apache.coyote.http11.controller.Controller; -import org.apache.coyote.http11.controller.HandlerMapping; -import org.apache.coyote.http11.request.HttpRequest; -import org.apache.coyote.http11.response.HttpResponse; - -public class Servlet { - - private final HandlerMapping handlerMapping; - - public Servlet() { - this.handlerMapping = new HandlerMapping(); - } - - public void doDispatch(HttpRequest request, HttpResponse response) throws IOException { - Controller controller = handlerMapping.getController(request); - - controller.service(request, response); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java index 8e2c605c49..c839a0d0b8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -1,15 +1,29 @@ package org.apache.coyote.http11.servlet; import java.io.IOException; +import java.util.Map; +import org.apache.coyote.http11.controller.LoginServlet; +import org.apache.coyote.http11.controller.RegisterServlet; +import org.apache.coyote.http11.controller.Servlet; +import org.apache.coyote.http11.controller.StaticServlet; import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.request.Path; import org.apache.coyote.http11.response.HttpResponse; public class ServletContainer { + private final Map servlets; + + public ServletContainer() { + this.servlets = Map.of( + new Path("/login"), new LoginServlet(), + new Path("/register"), new RegisterServlet()); + } + public void invoke(HttpRequest request, HttpResponse response) throws IOException { - Servlet servlet = new Servlet(); + Servlet servlet = servlets.getOrDefault(request.getPath(), new StaticServlet()); - servlet.doDispatch(request, response); + servlet.service(request, response); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index 7bea1e7434..aa311cde13 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -1,11 +1,14 @@ package org.apache.coyote.http11.session; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.UUID; public class Session { public static final String SESSION_HEADER_KEY = "JSESSIONID"; + private final String id; public Session() { From 690657d5960c65ac5308f5537ea9cc7489c2cfaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Thu, 12 Sep 2024 20:49:09 +0900 Subject: [PATCH 26/49] =?UTF-8?q?test:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B0=8F=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=84=9C?= =?UTF-8?q?=EB=B8=94=EB=A6=BF=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/techcourse/model/User.java | 22 +++++-- .../http11/common/VersionOfProtocol.java | 17 +++++ .../coyote/http11/response/HttpResponse.java | 46 ++++++------- .../AbstractServlet.java | 2 +- .../{controller => servlet}/LoginServlet.java | 2 +- .../RegisterServlet.java | 2 +- .../{controller => servlet}/Servlet.java | 2 +- .../http11/servlet/ServletContainer.java | 4 -- .../StaticServlet.java | 2 +- .../apache/coyote/http11/session/Session.java | 2 - .../http11/servlet/LoginServletTest.java | 57 ++++++++++++++++ .../http11/servlet/RegisterServletTest.java | 66 +++++++++++++++++++ 12 files changed, 180 insertions(+), 44 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/{controller => servlet}/AbstractServlet.java (93%) rename tomcat/src/main/java/org/apache/coyote/http11/{controller => servlet}/LoginServlet.java (97%) rename tomcat/src/main/java/org/apache/coyote/http11/{controller => servlet}/RegisterServlet.java (96%) rename tomcat/src/main/java/org/apache/coyote/http11/{controller => servlet}/Servlet.java (84%) rename tomcat/src/main/java/org/apache/coyote/http11/{controller => servlet}/StaticServlet.java (92%) create mode 100644 tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java create mode 100644 tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java diff --git a/tomcat/src/main/java/com/techcourse/model/User.java b/tomcat/src/main/java/com/techcourse/model/User.java index e8cf4c8e68..62b7519edb 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.Objects; + public class User { private final Long id; @@ -27,12 +29,18 @@ public String getAccount() { } @Override - public String toString() { - return "User{" + - "id=" + id + - ", account='" + account + '\'' + - ", email='" + email + '\'' + - ", password='" + password + '\'' + - '}'; + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + User user = (User)o; + return Objects.equals(account, user.account) && Objects.equals(password, user.password) + && Objects.equals(email, user.email); + } + + @Override + public int hashCode() { + return Objects.hash(account, password, email); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 6978e88030..c2e01bd680 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -1,8 +1,25 @@ package org.apache.coyote.http11.common; +import java.util.Objects; + public record VersionOfProtocol(String value) { public static VersionOfProtocol request(String requestLine) { return new VersionOfProtocol(requestLine.split(" ")[0]); } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + VersionOfProtocol that = (VersionOfProtocol)o; + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index b9b33a3dd5..35461ab56f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -23,32 +23,6 @@ public HttpResponse() { this.headers = new Headers(); } - public HttpResponse( - String versionOfProtocol, - int statusCode, - String statusMessage, - Map headers - ) { - this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); - this.statusCode = new StatusCode(statusCode); - this.statusMessage = new StatusMessage(statusMessage); - this.headers = new Headers(headers); - } - - public HttpResponse( - String versionOfProtocol, - int statusCode, - String statusMessage, - Map headers, - String body - ) { - this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); - this.statusCode = new StatusCode(statusCode); - this.statusMessage = new StatusMessage(statusMessage); - this.headers = new Headers(headers); - this.body = new Body(body); - } - public String toPlainText() { StringBuilder sb = new StringBuilder(); sb.append(String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value())); @@ -94,4 +68,24 @@ public void setBody(String filename) throws IOException { this.headers.add("Content-Length", String.valueOf(body.getContentLength())); } } + + public VersionOfProtocol getVersionOfProtocol() { + return versionOfProtocol; + } + + public StatusCode getStatusCode() { + return statusCode; + } + + public StatusMessage getStatusMessage() { + return statusMessage; + } + + public Headers getHeaders() { + return headers; + } + + public Body getBody() { + return body; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java similarity index 93% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java index 37edeb1b2a..f4a08ed785 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.controller; +package org.apache.coyote.http11.servlet; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java similarity index 97% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index d3e1f55594..de945c4e2b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.controller; +package org.apache.coyote.http11.servlet; import java.io.IOException; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java similarity index 96% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java index 4d38bef995..96065e786a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.controller; +package org.apache.coyote.http11.servlet; import java.io.IOException; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java similarity index 84% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java index 96f3fa5ea1..4b0918f149 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/Servlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/Servlet.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.controller; +package org.apache.coyote.http11.servlet; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java index c839a0d0b8..a86cd35960 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -3,10 +3,6 @@ import java.io.IOException; import java.util.Map; -import org.apache.coyote.http11.controller.LoginServlet; -import org.apache.coyote.http11.controller.RegisterServlet; -import org.apache.coyote.http11.controller.Servlet; -import org.apache.coyote.http11.controller.StaticServlet; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.request.Path; import org.apache.coyote.http11.response.HttpResponse; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java similarity index 92% rename from tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java index e0d4716e91..a6ead6cded 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/StaticServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.controller; +package org.apache.coyote.http11.servlet; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index aa311cde13..8bb52f426e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -1,8 +1,6 @@ package org.apache.coyote.http11.session; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; import java.util.UUID; diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java new file mode 100644 index 0000000000..0f36d55771 --- /dev/null +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java @@ -0,0 +1,57 @@ +package org.apache.coyote.http11.servlet; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.apache.coyote.http11.common.VersionOfProtocol; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.StatusCode; +import org.apache.coyote.http11.response.StatusMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class LoginServletTest { + + @DisplayName("로그인 POST 요청에 성공한다.") + @Test + void loginSuccess() throws IOException { + String requestData = "POST /login HTTP/1.1\r\n" + + "Content-Length: 30\r\n\r\n" + + "account=gugu&password=password"; + + BufferedReader reader = new BufferedReader(new StringReader(requestData)); + HttpRequest request = new HttpRequest(reader); + HttpResponse response = new HttpResponse(); + + LoginServlet loginServlet = new LoginServlet(); + loginServlet.doPost(request, response); + + assertThat(new VersionOfProtocol("HTTP/1.1")).isEqualTo(response.getVersionOfProtocol()); + assertThat(new StatusCode(302)).isEqualTo(response.getStatusCode()); + assertThat(new StatusMessage("Found")).isEqualTo(response.getStatusMessage()); + assertThat(response.getHeaders().getValue("Set-Cookie")).isNotNull(); + assertThat("http://localhost:8080/index.html").isEqualTo(response.getHeaders().getValue("Location")); + } + + @DisplayName("로그인 페이지 조회에 성공한다.") + @Test + void loginPageSuccess() throws IOException { + String requestData = "GET /login HTTP/1.1\r\n"; + + BufferedReader reader = new BufferedReader(new StringReader(requestData)); + HttpRequest request = new HttpRequest(reader); + HttpResponse response = new HttpResponse(); + + LoginServlet loginServlet = new LoginServlet(); + loginServlet.doGet(request, response); + + assertThat(new VersionOfProtocol("HTTP/1.1")).isEqualTo(response.getVersionOfProtocol()); + assertThat(new StatusCode(200)).isEqualTo(response.getStatusCode()); + assertThat(new StatusMessage("OK")).isEqualTo(response.getStatusMessage()); + } +} \ No newline at end of file diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java new file mode 100644 index 0000000000..941218c395 --- /dev/null +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java @@ -0,0 +1,66 @@ +package org.apache.coyote.http11.servlet; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.apache.coyote.http11.common.VersionOfProtocol; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.StatusCode; +import org.apache.coyote.http11.response.StatusMessage; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.techcourse.db.InMemoryUserRepository; +import com.techcourse.model.User; + +class RegisterServletTest { + + @DisplayName("회원가입에 성공한다.") + @Test + void registerSuccess() throws IOException { + String requestData = "POST /login HTTP/1.1\r\n" + + "Content-Length: 60\r\n\r\n" + + "account=testAccount&mail=test@mail.com&password=testPassword"; + BufferedReader reader = new BufferedReader(new StringReader(requestData)); + + HttpRequest request = new HttpRequest(reader); + HttpResponse response = new HttpResponse(); + + RegisterServlet servlet = new RegisterServlet(); + servlet.doPost(request, response); + + User expectedUser = new User("testAccount", "test@mail.com", "testPassword"); + User savedUser = InMemoryUserRepository.findByAccount("testAccount").orElse(null); + assertThat(savedUser).isNotNull(); + assertThat(expectedUser).isEqualTo(savedUser); + + assertThat(response.getVersionOfProtocol()).isEqualTo(new VersionOfProtocol("HTTP/1.1")); + assertThat(response.getStatusCode()).isEqualTo(new StatusCode(302)); + assertThat(response.getStatusMessage()).isEqualTo(new StatusMessage("Found")); + + assertThat(response.getHeaders().getValue("Location")).isNotNull(); + assertThat(response.getHeaders().getValue("Location")).isEqualTo("http://localhost:8080/index.html"); + } + + @DisplayName("회원가입 페이지를 조회에 성공한다.") + @Test + void registerFailure() throws IOException { + String requestData = "GET /register HTTP/1.1\r\n"; + BufferedReader reader = new BufferedReader(new StringReader(requestData)); + + HttpRequest request = new HttpRequest(reader); + HttpResponse response = new HttpResponse(); + + RegisterServlet servlet = new RegisterServlet(); + servlet.doGet(request, response); + + assertThat(response.getVersionOfProtocol()).isEqualTo(new VersionOfProtocol("HTTP/1.1")); + assertThat(response.getStatusCode()).isEqualTo(new StatusCode(200)); + assertThat(response.getStatusMessage()).isEqualTo(new StatusMessage("OK")); + } +} \ No newline at end of file From 485dd698c896b2a06e2570d009b9bc9c6df6fe05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:15:37 +0900 Subject: [PATCH 27/49] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EA=B0=92=EC=9D=84=20=EC=83=81=EC=88=98?= =?UTF-8?q?=ED=99=94=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 --- .../org/apache/coyote/http11/common/Body.java | 7 ++++--- .../coyote/http11/common/ContentType.java | 2 +- .../coyote/http11/common/HTTP_DELIMITER.java | 18 ++++++++++++++++++ .../apache/coyote/http11/common/HeaderKey.java | 17 +++++++++++++++++ .../apache/coyote/http11/common/Headers.java | 5 ++--- 5 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index f48c0da101..61081e0cf1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -1,12 +1,13 @@ package org.apache.coyote.http11.common; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HeaderKey.*; + import java.io.BufferedReader; import java.io.IOException; import java.util.Arrays; public record Body(String value) { - private static final String CONTENT_LENGTH = "Content-Length"; - public static Body request(Headers headers, BufferedReader reader) throws IOException { return new Body(parseBody(headers, reader)); } @@ -32,7 +33,7 @@ public int getContentLength() { public Properties parseProperty() { Properties properties = new Properties(); - Arrays.asList(value.split("&")) + Arrays.asList(value.split(BODY_PROPERTY_DELIMITER.getValue())) .forEach(properties::add); return properties; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java index f2e2b3b323..f7ddcab14d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java @@ -4,7 +4,7 @@ public enum ContentType { APPLICATION_JSON("application/json"), TEXT_CSS("text/css"), TEXT_HTML("text/html"), - APPLICATION_JAVASCRIPT("text/javascript"), + TEXT_JAVASCRIPT("text/javascript"), ; private final String value; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java b/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java new file mode 100644 index 0000000000..836e23a6a4 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java @@ -0,0 +1,18 @@ +package org.apache.coyote.http11.common; + +public enum HTTP_DELIMITER { + REQUEST_LINE_DELIMITER(" "), + BODY_PROPERTY_DELIMITER("&"), + BODY_KEY_VALUE_DELIMITER("=") + ; + + private final String value; + + HTTP_DELIMITER(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java b/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java new file mode 100644 index 0000000000..bcfd2dc2e5 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java @@ -0,0 +1,17 @@ +package org.apache.coyote.http11.common; + +public enum HeaderKey { + CONTENT_LENGTH("Content-Length"), + CONTENT_TYPE("Content-Type") + ; + + private final String value; + + HeaderKey(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index dde5612ae7..3b0134463a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -6,7 +6,6 @@ import java.util.Map; public record Headers(Map headers) { - public Headers() { this(new HashMap<>()); } @@ -25,7 +24,7 @@ public void add(String key, String value) { headers.put(key, value); } - public String getValue(String key) { - return headers.get(key); + public String getValue(HeaderKey headerKey) { + return headers.get(headerKey.getValue()); } } From 47487839d9d7261b98b388e2252a5445362a8cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:15:55 +0900 Subject: [PATCH 28/49] =?UTF-8?q?style:=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=81=EB=8B=A8=20=EA=B0=9C=ED=96=89=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EB=A7=9E=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/Http11Processor.java | 1 - .../http11/common/VersionOfProtocol.java | 1 - .../apache/coyote/http11/request/Method.java | 1 - .../apache/coyote/http11/request/Path.java | 1 - .../coyote/http11/request/RequestHandler.java | 98 ------------------- .../http11/response/ResponseHandler.java | 96 ------------------ .../http11/response/ResponsePrinter.java | 1 - .../coyote/http11/response/StatusCode.java | 1 - .../coyote/http11/response/StatusMessage.java | 1 - .../http11/servlet/AbstractServlet.java | 1 - .../coyote/http11/servlet/LoginServlet.java | 1 - .../http11/servlet/ServletContainer.java | 1 - tomcat/src/main/resources/static/index.html | 4 +- tomcat/src/main/resources/static/login.html | 2 +- .../src/main/resources/static/register.html | 2 +- 15 files changed, 4 insertions(+), 208 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.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 aaa02e4415..55de1ef37b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { - private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index c2e01bd680..744f4101a3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -3,7 +3,6 @@ import java.util.Objects; public record VersionOfProtocol(String value) { - public static VersionOfProtocol request(String requestLine) { return new VersionOfProtocol(requestLine.split(" ")[0]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index 4a97fb8af0..f832f20017 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -1,7 +1,6 @@ package org.apache.coyote.http11.request; public record Method(String value) { - public static Method request(String requestLine) { return new Method(requestLine.split(" ")[0]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 60bb5ebc30..9aee82b7ae 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -3,7 +3,6 @@ import java.util.Objects; public record Path(String value) { - public static Path request(String requestLine) { return new Path(requestLine.split(" ")[1]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java deleted file mode 100644 index 3bd3462836..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.apache.coyote.http11.request; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.coyote.http11.response.ResponseHandler; -import org.apache.coyote.http11.session.Session; -import org.apache.coyote.http11.session.SessionManager; - -import com.techcourse.db.InMemoryUserRepository; -import com.techcourse.model.User; - -public class RequestHandler { - - private final HttpRequest httpRequest; - private final OutputStream outputStream; - - public RequestHandler(HttpRequest httpRequest, OutputStream outputStream) { - this.httpRequest = httpRequest; - this.outputStream = outputStream; - } - - public void handleRequest() throws IOException { - String httpMethod = httpRequest.getMethod(); - String urlPath = httpRequest.getPath(); - - if(urlPath.endsWith("html") || urlPath.endsWith("css") || urlPath.endsWith("js")) { - ResponseHandler.printFileResource("static" + urlPath, outputStream); - } else if (urlPath.startsWith("/login")) { - handleLoginRequest(httpMethod, urlPath); - } else if (urlPath.startsWith("/register")) { - handleRegisterRequest(httpMethod, urlPath); - } else { - sendHelloWorldResponse(); - } - } - - private void handleLoginRequest(String httpMethod, String urlPath) { - if (urlPath.equals("/login") && httpMethod.equals("GET")) { - Session session = new Session(httpRequest); - SessionManager.findUserBySession(session) - .ifPresentOrElse( - user -> ResponseHandler.redirect("/index.html", outputStream), - () -> ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream)); - } else if (httpMethod.equals("POST")) { - login(); - } - } - - private void login() { - String body = httpRequest.getBody(); - if (body != null) { - String account = body.split("&")[0].split("=")[1]; - String password = body.split("&")[1].split("=")[1]; - InMemoryUserRepository.findByAccount(account) - .ifPresentOrElse( - user -> loginUser(user, password), - () -> ResponseHandler.redirect("/401.html", outputStream) - ); - } - ResponseHandler.redirect("/401.html", outputStream); - } - - private void loginUser(User user, String password) { - if (user.checkPassword(password)) { - Session session = SessionManager.createSession(user); - ResponseHandler.redirectWithSetCookie("/index.html", session.getId(), outputStream); - } - } - - private void handleRegisterRequest(String httpMethod, String urlPath) { - if (httpMethod.equals("GET")) { - ResponseHandler.printFileResource("static" + urlPath + ".html", outputStream); - return; - } - String body = httpRequest.getBody(); - if (body != null) { - String account = body.split("&")[0].split("=")[1]; - String mail = body.split("&")[1].split("=")[1]; - String password = body.split("&")[2].split("=")[1]; - User user = new User(account, mail, password); - InMemoryUserRepository.save(user); - ResponseHandler.redirect("/index.html", outputStream); - } - } - - private void sendHelloWorldResponse() throws IOException { - String responseBody = "Hello world!"; - String response = String.join("\r\n", - "HTTP/1.1 200 OK", - "Content-Type: text/html;charset=utf-8", - "Content-Length: " + responseBody.getBytes().length, - "", - responseBody); - outputStream.write(response.getBytes()); - outputStream.flush(); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java deleted file mode 100644 index f286e2861e..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apache.coyote.http11.response; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import java.nio.file.Files; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.techcourse.exception.UncheckedServletException; - -public class ResponseHandler { - - private static final Logger log = LoggerFactory.getLogger(ResponseHandler.class); - - public static void printFileResource(String fileName, OutputStream outputStream) { - final URL url = ResponseHandler.class.getClassLoader().getResource(fileName); - if (url == null) { - sendNotFoundResponse(outputStream); - return; - } - try { - File file = new File(url.getPath()); - String contentType = determineContentType(fileName); - String responseBody = new String(Files.readAllBytes(file.toPath())); - String response = String.join("\r\n", - "HTTP/1.1 200 OK", - "Content-Type: " + contentType + ";charset=utf-8", - "Content-Length: " + responseBody.getBytes().length, - "", - responseBody); - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private static String determineContentType(String fileName) { - if (fileName.endsWith("css")) { - return "text/css"; - } - if (fileName.endsWith("js")) { - return "application/javascript"; - } - if(fileName.endsWith("html")) { - return "text/html"; - } - return "application/json"; - } - - private static void sendNotFoundResponse(OutputStream outputStream) { - try { - String response = "HTTP/1.1 404 Not Found \r\n" + - "Content-Length: 0 \r\n" + - "\r\n"; - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void redirect(String path, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Location: http://localhost:8080" + path + "\r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; - - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); - } - } - - public static void redirectWithSetCookie(String path, String sessionId, OutputStream outputStream) { - try { - String contentType = "text/html"; - var response = "HTTP/1.1 302 Found \r\n" + - "Set-Cookie: JSESSIONID=" + sessionId + " \r\n" + - "Location: http://localhost:8080" + path + " \r\n" + - String.format("Content-Type: %s;charset=utf-8 \r\n", contentType) + - "Content-Length: 0"; - - outputStream.write(response.getBytes()); - outputStream.flush(); - } catch (IOException | UncheckedServletException e) { - log.error(e.getMessage(), e); - } - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java index 990bacac9c..45e16ba635 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponsePrinter.java @@ -4,7 +4,6 @@ import java.io.OutputStream; public class ResponsePrinter { - private final OutputStream outputStream; public ResponsePrinter(OutputStream outputStream) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java index 9edb5429ad..cfe115a55f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java @@ -1,7 +1,6 @@ package org.apache.coyote.http11.response; public record StatusCode(int value) { - public static StatusCode request(String requestLine) { return new StatusCode(Integer.parseInt(requestLine.split(" ")[1])); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java index 12d392ab74..4db6668bbe 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java @@ -1,7 +1,6 @@ package org.apache.coyote.http11.response; public record StatusMessage(String value) { - public static StatusMessage request(String requestLine) { return new StatusMessage(requestLine.split(" ")[2]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java index f4a08ed785..3cfa45912a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java @@ -7,7 +7,6 @@ import org.apache.coyote.http11.response.HttpResponse; public abstract class AbstractServlet implements Servlet { - @Override public void service(HttpRequest request, HttpResponse response) throws IOException { Method method = request.getMethod(); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index de945c4e2b..87684a3d6b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -15,7 +15,6 @@ import com.techcourse.model.User; public class LoginServlet extends AbstractServlet { - @Override protected void doPost(HttpRequest request, HttpResponse response) { Body body = request.getBody(); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java index a86cd35960..537c8c5c71 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -8,7 +8,6 @@ import org.apache.coyote.http11.response.HttpResponse; public class ServletContainer { - private final Map servlets; public ServletContainer() { diff --git a/tomcat/src/main/resources/static/index.html b/tomcat/src/main/resources/static/index.html index 18ac924d4e..24728ab9cc 100644 --- a/tomcat/src/main/resources/static/index.html +++ b/tomcat/src/main/resources/static/index.html @@ -61,7 +61,7 @@

대시보드

-
+
Bar Chart
@@ -70,7 +70,7 @@

대시보드

-
+
Pie Chart
diff --git a/tomcat/src/main/resources/static/login.html b/tomcat/src/main/resources/static/login.html index bc933357f2..d29c079679 100644 --- a/tomcat/src/main/resources/static/login.html +++ b/tomcat/src/main/resources/static/login.html @@ -18,7 +18,7 @@
-

로그인

+

로그인

diff --git a/tomcat/src/main/resources/static/register.html b/tomcat/src/main/resources/static/register.html index d87de0214c..b05742ef60 100644 --- a/tomcat/src/main/resources/static/register.html +++ b/tomcat/src/main/resources/static/register.html @@ -18,7 +18,7 @@
-

회원 가입

+

회원 가입

From 159a3969ff155282ebaa74d42cb1eb0f402dae7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:17:23 +0900 Subject: [PATCH 29/49] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B2=98=EB=A6=AC=20=EC=8B=9C=20.=20?= =?UTF-8?q?=EC=9D=84=20=EB=B6=99=EC=97=AC=20=ED=99=95=EC=9E=A5=EC=9E=90=20?= =?UTF-8?q?=ED=8C=90=EB=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/http11/common/ContentType.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java index f7ddcab14d..5b208eeea9 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/ContentType.java @@ -14,13 +14,13 @@ public enum ContentType { } public static ContentType fromPath(String path) { - if (path.endsWith("css")) { + if (path.endsWith(".css")) { return ContentType.TEXT_CSS; } - if (path.endsWith("js")) { + if (path.endsWith(".js")) { return ContentType.APPLICATION_JSON; } - if (path.endsWith("html")) { + if (path.endsWith(".html")) { return ContentType.TEXT_HTML; } return ContentType.APPLICATION_JSON; From 8b2e8748b79497b39d26fbc9f26e6be55cf6a2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:22:01 +0900 Subject: [PATCH 30/49] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=ED=82=A4=EB=A5=BC=20=EC=83=81=EC=88=98?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/HeaderKey.java | 5 ++++- .../org/apache/coyote/http11/common/Headers.java | 2 +- .../coyote/http11/common/VersionOfProtocol.java | 4 ---- .../apache/coyote/http11/request/HttpRequest.java | 13 +++++++------ .../coyote/http11/servlet/LoginServletTest.java | 6 ++++-- .../coyote/http11/servlet/RegisterServletTest.java | 6 ++++-- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java b/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java index bcfd2dc2e5..14230e0b91 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/HeaderKey.java @@ -2,7 +2,10 @@ public enum HeaderKey { CONTENT_LENGTH("Content-Length"), - CONTENT_TYPE("Content-Type") + CONTENT_TYPE("Content-Type"), + COOKIE("Cookie"), + SET_COOKIE("Set-Cookie"), + LOCATION("Location") ; private final String value; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 3b0134463a..9d027eda6d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -10,7 +10,7 @@ public Headers() { this(new HashMap<>()); } - public static Headers request(BufferedReader reader) throws IOException { + public static Headers parseRequestHeader(BufferedReader reader) throws IOException { HashMap headers = new HashMap<>(); String line; while ((line = reader.readLine()) != null && !line.isEmpty()) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 744f4101a3..587142f532 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -3,10 +3,6 @@ import java.util.Objects; public record VersionOfProtocol(String value) { - public static VersionOfProtocol request(String requestLine) { - return new VersionOfProtocol(requestLine.split(" ")[0]); - } - @Override public boolean equals(Object o) { if (this == o) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 852ea6f897..2ad0f09a31 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -1,12 +1,17 @@ package org.apache.coyote.http11.request; +import static org.apache.coyote.http11.common.HeaderKey.*; + import java.io.BufferedReader; import java.io.IOException; import org.apache.coyote.http11.common.Body; +import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.Headers; import org.apache.coyote.http11.session.Session; +import jakarta.servlet.http.Cookie; + public class HttpRequest { private final Method method; private final Path path; @@ -17,7 +22,7 @@ public HttpRequest(BufferedReader reader) throws IOException { String requestLine = reader.readLine(); this.method = Method.request(requestLine); this.path = Path.request(requestLine); - this.headers = Headers.request(reader); + this.headers = Headers.parseRequestHeader(reader); this.body = Body.request(headers, reader); } @@ -29,16 +34,12 @@ public Path getPath() { return path; } - public String getCookie() { - return headers.getValue("Cookie"); - } - public Body getBody() { return body; } public Session getSession() { - String cookie = headers.getValue("Cookie"); + String cookie = headers.getValue(COOKIE); if (cookie == null) { return null; } diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java index 0f36d55771..2e1bbc6ae2 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java @@ -1,5 +1,6 @@ package org.apache.coyote.http11.servlet; +import static org.apache.coyote.http11.common.HeaderKey.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; @@ -7,6 +8,7 @@ import java.io.IOException; import java.io.StringReader; +import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; @@ -34,8 +36,8 @@ void loginSuccess() throws IOException { assertThat(new VersionOfProtocol("HTTP/1.1")).isEqualTo(response.getVersionOfProtocol()); assertThat(new StatusCode(302)).isEqualTo(response.getStatusCode()); assertThat(new StatusMessage("Found")).isEqualTo(response.getStatusMessage()); - assertThat(response.getHeaders().getValue("Set-Cookie")).isNotNull(); - assertThat("http://localhost:8080/index.html").isEqualTo(response.getHeaders().getValue("Location")); + assertThat(response.getHeaders().getValue(SET_COOKIE)).isNotNull(); + assertThat("http://localhost:8080/index.html").isEqualTo(response.getHeaders().getValue(LOCATION)); } @DisplayName("로그인 페이지 조회에 성공한다.") diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java index 941218c395..aa51747a10 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java @@ -1,5 +1,6 @@ package org.apache.coyote.http11.servlet; +import static org.apache.coyote.http11.common.HeaderKey.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; @@ -7,6 +8,7 @@ import java.io.IOException; import java.io.StringReader; +import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; @@ -43,8 +45,8 @@ void registerSuccess() throws IOException { assertThat(response.getStatusCode()).isEqualTo(new StatusCode(302)); assertThat(response.getStatusMessage()).isEqualTo(new StatusMessage("Found")); - assertThat(response.getHeaders().getValue("Location")).isNotNull(); - assertThat(response.getHeaders().getValue("Location")).isEqualTo("http://localhost:8080/index.html"); + assertThat(response.getHeaders().getValue(LOCATION)).isNotNull(); + assertThat(response.getHeaders().getValue(LOCATION)).isEqualTo("http://localhost:8080/index.html"); } @DisplayName("회원가입 페이지를 조회에 성공한다.") From 903c610c25f3d71df3895fe533713360627bbf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:23:56 +0900 Subject: [PATCH 31/49] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EC=9D=98=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EC=9D=84=20=EC=A7=81=EA=B4=80=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/apache/coyote/http11/common/Body.java | 2 +- .../org/apache/coyote/http11/request/HttpRequest.java | 9 +++------ .../java/org/apache/coyote/http11/request/Method.java | 2 +- .../main/java/org/apache/coyote/http11/request/Path.java | 2 +- .../org/apache/coyote/http11/response/StatusCode.java | 3 --- .../org/apache/coyote/http11/response/StatusMessage.java | 3 --- 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 61081e0cf1..ae11df8e4d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -8,7 +8,7 @@ import java.util.Arrays; public record Body(String value) { - public static Body request(Headers headers, BufferedReader reader) throws IOException { + public static Body parseRequestBody(Headers headers, BufferedReader reader) throws IOException { return new Body(parseBody(headers, reader)); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 2ad0f09a31..bf54ec4783 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -6,12 +6,9 @@ import java.io.IOException; import org.apache.coyote.http11.common.Body; -import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.Headers; import org.apache.coyote.http11.session.Session; -import jakarta.servlet.http.Cookie; - public class HttpRequest { private final Method method; private final Path path; @@ -20,10 +17,10 @@ public class HttpRequest { public HttpRequest(BufferedReader reader) throws IOException { String requestLine = reader.readLine(); - this.method = Method.request(requestLine); - this.path = Path.request(requestLine); + this.method = Method.parseRequestMethod(requestLine); + this.path = Path.parseRequestPath(requestLine); this.headers = Headers.parseRequestHeader(reader); - this.body = Body.request(headers, reader); + this.body = Body.parseRequestBody(headers, reader); } public Method getMethod() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index f832f20017..d8ea9adde3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -1,7 +1,7 @@ package org.apache.coyote.http11.request; public record Method(String value) { - public static Method request(String requestLine) { + public static Method parseRequestMethod(String requestLine) { return new Method(requestLine.split(" ")[0]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 9aee82b7ae..1bbde6dfe8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -3,7 +3,7 @@ import java.util.Objects; public record Path(String value) { - public static Path request(String requestLine) { + public static Path parseRequestPath(String requestLine) { return new Path(requestLine.split(" ")[1]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java index cfe115a55f..32c8b29c9d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusCode.java @@ -1,7 +1,4 @@ package org.apache.coyote.http11.response; public record StatusCode(int value) { - public static StatusCode request(String requestLine) { - return new StatusCode(Integer.parseInt(requestLine.split(" ")[1])); - } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java index 4db6668bbe..e7b3e30b60 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/StatusMessage.java @@ -1,7 +1,4 @@ package org.apache.coyote.http11.response; public record StatusMessage(String value) { - public static StatusMessage request(String requestLine) { - return new StatusMessage(requestLine.split(" ")[2]); - } } From efb92a09624b364358d04c88c621447eb60dea64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:35:26 +0900 Subject: [PATCH 32/49] =?UTF-8?q?refactor:=20HTTP=20=ED=8C=8C=EC=8B=B1?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20Delimter=20=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=84=EB=B6=80=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/HTTP_DELIMITER.java | 4 +++- .../java/org/apache/coyote/http11/common/Headers.java | 4 +++- .../java/org/apache/coyote/http11/common/Properties.java | 9 ++++++--- .../apache/coyote/http11/common/VersionOfProtocol.java | 6 ++++-- .../java/org/apache/coyote/http11/request/Method.java | 4 +++- .../main/java/org/apache/coyote/http11/request/Path.java | 6 +++++- .../java/org/apache/coyote/http11/session/Session.java | 4 +++- 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java b/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java index 836e23a6a4..5bd4dc6aa3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java @@ -3,7 +3,9 @@ public enum HTTP_DELIMITER { REQUEST_LINE_DELIMITER(" "), BODY_PROPERTY_DELIMITER("&"), - BODY_KEY_VALUE_DELIMITER("=") + BODY_KEY_VALUE_DELIMITER("="), + SESSION_DELIMITER("; "), + HEADER_KEY_VALUE_DELIMITER(":") ; private final String value; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 9d027eda6d..8506293473 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -1,5 +1,7 @@ package org.apache.coyote.http11.common; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; + import java.io.BufferedReader; import java.io.IOException; import java.util.HashMap; @@ -14,7 +16,7 @@ public static Headers parseRequestHeader(BufferedReader reader) throws IOExcepti HashMap headers = new HashMap<>(); String line; while ((line = reader.readLine()) != null && !line.isEmpty()) { - String[] header = line.split(":"); + String[] header = line.split(HEADER_KEY_VALUE_DELIMITER.getValue()); headers.put(header[0].trim(), header[1].trim()); } return new Headers(headers); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java index abb663a92e..87c550e6e8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java @@ -1,10 +1,13 @@ package org.apache.coyote.http11.common; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; + import java.util.HashMap; import java.util.Map; public class Properties { - public static final String DELIMITER = "="; + private static final int KEY_INDEX_OF_PROPERTY = 0; + private static final int VALUE_INDEX_OF_PROPERTY = 1; private final Map properties; @@ -13,8 +16,8 @@ public Properties() { } public void add(String rawProperty) { - String key = rawProperty.split(DELIMITER)[0]; - String value = rawProperty.split(DELIMITER)[1]; + String key = rawProperty.split(BODY_KEY_VALUE_DELIMITER.getValue())[KEY_INDEX_OF_PROPERTY]; + String value = rawProperty.split(BODY_KEY_VALUE_DELIMITER.getValue())[VALUE_INDEX_OF_PROPERTY]; this.properties.put(key, value); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 587142f532..028ee332bd 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -5,10 +5,12 @@ public record VersionOfProtocol(String value) { @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } VersionOfProtocol that = (VersionOfProtocol)o; return Objects.equals(value, that.value); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index d8ea9adde3..6e7b8b466e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -1,8 +1,10 @@ package org.apache.coyote.http11.request; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; + public record Method(String value) { public static Method parseRequestMethod(String requestLine) { - return new Method(requestLine.split(" ")[0]); + return new Method(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[0]); } public boolean isGet() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 1bbde6dfe8..cfe7748cbc 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -1,10 +1,14 @@ package org.apache.coyote.http11.request; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; + import java.util.Objects; public record Path(String value) { + private static final int INDEX_OF_PATH = 1; + public static Path parseRequestPath(String requestLine) { - return new Path(requestLine.split(" ")[1]); + return new Path(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_PATH]); } @Override diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index 8bb52f426e..19704a1de8 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -1,5 +1,7 @@ package org.apache.coyote.http11.session; +import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; + import java.util.Arrays; import java.util.Objects; import java.util.UUID; @@ -14,7 +16,7 @@ public Session() { } public Session(String cookies) { - String session = Arrays.asList(cookies.split("; ")) + String session = Arrays.asList(cookies.split(SESSION_DELIMITER.getValue())) .stream() .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) .findAny() From 55e7ee64cf1ab398ef5baa18686671c1cfc6646f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 10:42:47 +0900 Subject: [PATCH 33/49] =?UTF-8?q?refactor:=20=EC=84=B8=EC=85=98=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=B6=94=EC=B6=9C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EB=A5=BC=20=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/session/Session.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index 19704a1de8..c848bc1762 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -16,11 +16,7 @@ public Session() { } public Session(String cookies) { - String session = Arrays.asList(cookies.split(SESSION_DELIMITER.getValue())) - .stream() - .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) - .findAny() - .orElseGet(null); + String session = getSession(cookies); if (session != null) { this.id = session.substring(SESSION_HEADER_KEY.length() + 1); } else { @@ -28,6 +24,15 @@ public Session(String cookies) { } } + private static String getSession(String cookies) { + String session = Arrays.asList(cookies.split(SESSION_DELIMITER.getValue())) + .stream() + .filter(cookie -> cookie.startsWith(SESSION_HEADER_KEY)) + .findAny() + .orElseGet(null); + return session; + } + public String getId() { return id; } From cd74cff0777da25e1d46e9fa3b99034c3b84f631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:05:48 +0900 Subject: [PATCH 34/49] =?UTF-8?q?refactor:=20RequestLine=EA=B3=BC=20Respon?= =?UTF-8?q?seLine=EC=9C=BC=EB=A1=9C=20=EA=B0=9D=EC=B2=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/Body.java | 4 +- .../apache/coyote/http11/common/Headers.java | 10 ++++- ...HTTP_DELIMITER.java => HttpDelimiter.java} | 4 +- .../coyote/http11/common/Properties.java | 2 +- .../http11/common/VersionOfProtocol.java | 8 ++++ .../coyote/http11/request/HttpRequest.java | 15 ++++--- .../apache/coyote/http11/request/Method.java | 6 ++- .../apache/coyote/http11/request/Path.java | 2 +- .../coyote/http11/request/RequestLine.java | 7 +++ .../coyote/http11/response/HttpResponse.java | 28 +++++------- .../coyote/http11/response/ResponseLine.java | 44 +++++++++++++++++++ .../apache/coyote/http11/session/Session.java | 2 +- .../http11/servlet/RegisterServletTest.java | 2 - 13 files changed, 100 insertions(+), 34 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/common/{HTTP_DELIMITER.java => HttpDelimiter.java} (83%) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/request/RequestLine.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index ae11df8e4d..dbaa2238e1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.common; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; import static org.apache.coyote.http11.common.HeaderKey.*; import java.io.BufferedReader; @@ -8,7 +8,7 @@ import java.util.Arrays; public record Body(String value) { - public static Body parseRequestBody(Headers headers, BufferedReader reader) throws IOException { + public static Body request(Headers headers, BufferedReader reader) throws IOException { return new Body(parseBody(headers, reader)); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 8506293473..3d9e779eff 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.common; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; import java.io.BufferedReader; import java.io.IOException; @@ -29,4 +29,12 @@ public void add(String key, String value) { public String getValue(HeaderKey headerKey) { return headers.get(headerKey.getValue()); } + + public String generatePlainText() { + StringBuilder sb = new StringBuilder(); + headers().forEach((key, value) -> { + sb.append(String.format("%s: %s \r\n", key, value)); + }); + return sb.toString(); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java b/tomcat/src/main/java/org/apache/coyote/http11/common/HttpDelimiter.java similarity index 83% rename from tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java rename to tomcat/src/main/java/org/apache/coyote/http11/common/HttpDelimiter.java index 5bd4dc6aa3..77c0a4fba2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/HTTP_DELIMITER.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/HttpDelimiter.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.common; -public enum HTTP_DELIMITER { +public enum HttpDelimiter { REQUEST_LINE_DELIMITER(" "), BODY_PROPERTY_DELIMITER("&"), BODY_KEY_VALUE_DELIMITER("="), @@ -10,7 +10,7 @@ public enum HTTP_DELIMITER { private final String value; - HTTP_DELIMITER(String value) { + HttpDelimiter(String value) { this.value = value; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java index 87c550e6e8..157ce936de 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Properties.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.common; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; import java.util.HashMap; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 028ee332bd..88157095c0 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -1,8 +1,16 @@ package org.apache.coyote.http11.common; +import static org.apache.coyote.http11.common.HttpDelimiter.*; + import java.util.Objects; public record VersionOfProtocol(String value) { + private static final int INDEX_OF_VERSION_OF_PROTOCOL = 2; + + public static VersionOfProtocol parseReqeustVersionOfProtocol(String requestLine) { + return new VersionOfProtocol(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_VERSION_OF_PROTOCOL]); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index bf54ec4783..f8e7a046da 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -7,28 +7,31 @@ import org.apache.coyote.http11.common.Body; import org.apache.coyote.http11.common.Headers; +import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.session.Session; public class HttpRequest { - private final Method method; - private final Path path; + private final RequestLine requestLine; private final Headers headers; private final Body body; public HttpRequest(BufferedReader reader) throws IOException { String requestLine = reader.readLine(); - this.method = Method.parseRequestMethod(requestLine); - this.path = Path.parseRequestPath(requestLine); + this.requestLine = new RequestLine( + Method.parseRequestMethod(requestLine), + Path.parseRequestPath(requestLine), + VersionOfProtocol.parseReqeustVersionOfProtocol(requestLine) + ); this.headers = Headers.parseRequestHeader(reader); this.body = Body.parseRequestBody(headers, reader); } public Method getMethod() { - return method; + return requestLine.method(); } public Path getPath() { - return path; + return requestLine.path(); } public Body getBody() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index 6e7b8b466e..a4ca3eb7b5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -1,10 +1,12 @@ package org.apache.coyote.http11.request; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; public record Method(String value) { + private static final int INDEX_OF_METHOD = 0; + public static Method parseRequestMethod(String requestLine) { - return new Method(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[0]); + return new Method(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_METHOD]); } public boolean isGet() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index cfe7748cbc..132f1d7de6 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.request; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; import java.util.Objects; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/RequestLine.java b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestLine.java new file mode 100644 index 0000000000..173a5eded2 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/RequestLine.java @@ -0,0 +1,7 @@ +package org.apache.coyote.http11.request; + +import org.apache.coyote.http11.common.VersionOfProtocol; + +public record RequestLine(Method method, Path path, VersionOfProtocol versionOfProtocol) { + +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 35461ab56f..f7cfa36f39 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -13,9 +13,7 @@ import org.apache.coyote.http11.common.VersionOfProtocol; public class HttpResponse { - private VersionOfProtocol versionOfProtocol; - private StatusCode statusCode; - private StatusMessage statusMessage; + private ResponseLine responseLine; private Headers headers; private Body body; @@ -25,10 +23,8 @@ public HttpResponse() { public String toPlainText() { StringBuilder sb = new StringBuilder(); - sb.append(String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value())); - headers.headers().forEach((key, value) -> { - sb.append(String.format("%s: %s \r\n", key, value)); - }); + sb.append(responseLine.generatePlainText()); + sb.append(headers.generatePlainText()); sb.append("\r\n"); if (body != null) { sb.append(body.value()); @@ -36,16 +32,16 @@ public String toPlainText() { return sb.toString(); } - public void setVersionOfProtocol(String versionOfProtocol) { - this.versionOfProtocol = new VersionOfProtocol(versionOfProtocol); + public void setVersionOfProtocol(String value) { + this.responseLine.setVersionOfProtocol(new VersionOfProtocol(value)); } - public void setStatusCode(int statusCode) { - this.statusCode = new StatusCode(statusCode); + public void setStatusCode(int value) { + this.responseLine.setStatusCode(new StatusCode(value)); } - public void setStatusMessage(String statusMessage) { - this.statusMessage = new StatusMessage(statusMessage); + public void setStatusMessage(String value) { + this.responseLine.setStatusMessage(new StatusMessage(value)); } public void setHeaders(Map headers) { @@ -70,15 +66,15 @@ public void setBody(String filename) throws IOException { } public VersionOfProtocol getVersionOfProtocol() { - return versionOfProtocol; + return responseLine.getVersionOfProtocol(); } public StatusCode getStatusCode() { - return statusCode; + return responseLine.getStatusCode(); } public StatusMessage getStatusMessage() { - return statusMessage; + return responseLine.getStatusMessage(); } public Headers getHeaders() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java new file mode 100644 index 0000000000..818d4cfbff --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java @@ -0,0 +1,44 @@ +package org.apache.coyote.http11.response; + +import org.apache.coyote.http11.common.VersionOfProtocol; + +public class ResponseLine { + private VersionOfProtocol versionOfProtocol; + private StatusCode statusCode; + private StatusMessage statusMessage; + + public ResponseLine(VersionOfProtocol versionOfProtocol, StatusCode statusCode, StatusMessage statusMessage) { + this.versionOfProtocol = versionOfProtocol; + this.statusCode = statusCode; + this.statusMessage = statusMessage; + } + + public VersionOfProtocol getVersionOfProtocol() { + return versionOfProtocol; + } + + public StatusCode getStatusCode() { + return statusCode; + } + + public StatusMessage getStatusMessage() { + return statusMessage; + } + + + public void setVersionOfProtocol(VersionOfProtocol versionOfProtocol) { + this.versionOfProtocol = versionOfProtocol; + } + + public void setStatusCode(StatusCode statusCode) { + this.statusCode = statusCode; + } + + public void setStatusMessage(StatusMessage statusMessage) { + this.statusMessage = statusMessage; + } + + public String generatePlainText() { + return String.format("%s %d %s \r\n", versionOfProtocol.value(), statusCode.value(), statusMessage.value()); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index c848bc1762..e59a403363 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -1,6 +1,6 @@ package org.apache.coyote.http11.session; -import static org.apache.coyote.http11.common.HTTP_DELIMITER.*; +import static org.apache.coyote.http11.common.HttpDelimiter.*; import java.util.Arrays; import java.util.Objects; diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java index aa51747a10..b782f17b71 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java @@ -2,13 +2,11 @@ import static org.apache.coyote.http11.common.HeaderKey.*; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; -import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; From 493a502c6b64ab6a80d5223ce644a227650b519f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:08:24 +0900 Subject: [PATCH 35/49] =?UTF-8?q?refactor:=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=ED=82=A4=EB=A5=BC=20=EC=83=81=EC=88=98=ED=99=94=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8F=84=EB=A1=9D=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/org/apache/coyote/http11/common/Headers.java | 4 ++-- .../apache/coyote/http11/response/HttpResponse.java | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java index 3d9e779eff..1b4757c685 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Headers.java @@ -22,8 +22,8 @@ public static Headers parseRequestHeader(BufferedReader reader) throws IOExcepti return new Headers(headers); } - public void add(String key, String value) { - headers.put(key, value); + public void add(HeaderKey key, String value) { + headers.put(key.getValue(), value); } public String getValue(HeaderKey headerKey) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index f7cfa36f39..8664000f4a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,5 +1,8 @@ package org.apache.coyote.http11.response; +import static org.apache.coyote.http11.common.ContentType.*; +import static org.apache.coyote.http11.common.HeaderKey.*; + import java.io.File; import java.io.IOException; import java.net.URL; @@ -55,13 +58,13 @@ public void setBody(String filename) throws IOException { this.body = new Body(new String(Files.readAllBytes(file.toPath()))); ContentType contentType = ContentType.fromPath(url.getPath()); - this.headers.add("Content-Type", contentType.getValue() + ";charset=utf-8"); - this.headers.add("Content-Length", String.valueOf(body.getContentLength())); + this.headers.add(CONTENT_TYPE, contentType.getValue() + ";charset=utf-8"); + this.headers.add(CONTENT_LENGTH, String.valueOf(body.getContentLength())); } catch (AccessDeniedException | NullPointerException exception) { this.body = new Body("Hello, World!"); - this.headers.add("Content-Type", "text/html;charset=utf-8"); - this.headers.add("Content-Length", String.valueOf(body.getContentLength())); + this.headers.add(CONTENT_TYPE, TEXT_HTML.getValue() + ";charset=utf-8"); + this.headers.add(CONTENT_LENGTH, String.valueOf(body.getContentLength())); } } From b2f4f1b31d707d7c5e27decac4f83d4e8b68621f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:19:41 +0900 Subject: [PATCH 36/49] =?UTF-8?q?fix:=20=EC=9D=B8=EB=8D=B1=EC=8A=A4=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EA=B0=80=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=98=84=EC=83=81=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/response/HttpResponse.java | 9 +++----- .../coyote/http11/servlet/IndexServlet.java | 21 +++++++++++++++++++ .../http11/servlet/ServletContainer.java | 1 + 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 8664000f4a..3a5e01e057 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -1,6 +1,5 @@ package org.apache.coyote.http11.response; -import static org.apache.coyote.http11.common.ContentType.*; import static org.apache.coyote.http11.common.HeaderKey.*; import java.io.File; @@ -61,10 +60,8 @@ public void setBody(String filename) throws IOException { this.headers.add(CONTENT_TYPE, contentType.getValue() + ";charset=utf-8"); this.headers.add(CONTENT_LENGTH, String.valueOf(body.getContentLength())); } catch (AccessDeniedException | NullPointerException exception) { - this.body = new Body("Hello, World!"); - - this.headers.add(CONTENT_TYPE, TEXT_HTML.getValue() + ";charset=utf-8"); - this.headers.add(CONTENT_LENGTH, String.valueOf(body.getContentLength())); + setStatusCode(404); + setStatusMessage("NOT FOUND"); } } @@ -87,4 +84,4 @@ public Headers getHeaders() { public Body getBody() { return body; } -} +} \ No newline at end of file diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java new file mode 100644 index 0000000000..67fb022635 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java @@ -0,0 +1,21 @@ +package org.apache.coyote.http11.servlet; + +import java.io.IOException; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public class IndexServlet extends AbstractServlet { + @Override + protected void doPost(HttpRequest request, HttpResponse response) { + + } + + @Override + protected void doGet(HttpRequest request, HttpResponse response) throws IOException { + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(200); + response.setStatusMessage("OK"); + response.setBody("static/index.html"); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java index 537c8c5c71..1df3fa5f76 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -12,6 +12,7 @@ public class ServletContainer { public ServletContainer() { this.servlets = Map.of( + new Path("/"), new IndexServlet(), new Path("/login"), new LoginServlet(), new Path("/register"), new RegisterServlet()); } From b5aeb32d76b8fa68dcae5853cbd2e82a32779fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:22:25 +0900 Subject: [PATCH 37/49] =?UTF-8?q?refactor:=20GET,=20POST=20=EC=9D=B4?= =?UTF-8?q?=EC=99=B8=EC=9D=98=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=9D=B4=20=EC=98=A8=EB=8B=A4=EB=A9=B4=20405=EB=A5=BC?= =?UTF-8?q?=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/servlet/AbstractServlet.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java index 3cfa45912a..9425bea20c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java @@ -1,6 +1,7 @@ package org.apache.coyote.http11.servlet; import java.io.IOException; +import java.util.Map; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.request.Method; @@ -15,6 +16,10 @@ public void service(HttpRequest request, HttpResponse response) throws IOExcepti } else if (method.isPost()) { doPost(request, response); } + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(405); + response.setStatusMessage("Method Not Allowed"); + response.setHeaders(Map.of("Allow", "GET, POST")); } protected abstract void doPost(HttpRequest request, HttpResponse response); From a9c8aae90837ff02a9c4ce4bb96fe7c978bb4a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:26:06 +0900 Subject: [PATCH 38/49] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=8D=BC?= =?UTF-8?q?=ED=8B=B0=EB=A5=BC=20HttpRequest=EC=97=90=EC=84=9C=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=20=EA=BA=BC=EB=82=B4=EC=98=A4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=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/http11/request/HttpRequest.java | 6 ++++++ .../java/org/apache/coyote/http11/servlet/LoginServlet.java | 6 ++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index f8e7a046da..b79e379712 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -7,6 +7,7 @@ import org.apache.coyote.http11.common.Body; import org.apache.coyote.http11.common.Headers; +import org.apache.coyote.http11.common.Properties; import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.session.Session; @@ -45,4 +46,9 @@ public Session getSession() { } return new Session(cookie); } + + public String getProperty(String key) { + Properties properties = body.parseProperty(); + return properties.get(key); + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index 87684a3d6b..5dbee10a8f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -17,11 +17,9 @@ public class LoginServlet extends AbstractServlet { @Override protected void doPost(HttpRequest request, HttpResponse response) { - Body body = request.getBody(); - Properties properties = body.parseProperty(); + String account = request.getProperty("account"); + String password = request.getProperty("password"); - String account = properties.get("account"); - String password = properties.get("password"); Optional user = InMemoryUserRepository.findByAccount(account); if (user.isPresent() && user.get().checkPassword(password)) { Session session = SessionManager.createSession(user.get()); From 282d61d490d5459cca98d4aabd59ce152ea520f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 11:57:32 +0900 Subject: [PATCH 39/49] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EC=9D=B4=20=EC=8B=A4=ED=8C=A8=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?401=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A5=BC=20=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/servlet/LoginServlet.java | 9 +++++++-- .../apache/coyote/http11/servlet/LoginServletTest.java | 2 -- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index 5dbee10a8f..5d0e6509f7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -4,8 +4,6 @@ import java.util.Map; import java.util.Optional; -import org.apache.coyote.http11.common.Body; -import org.apache.coyote.http11.common.Properties; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; import org.apache.coyote.http11.session.Session; @@ -31,7 +29,14 @@ protected void doPost(HttpRequest request, HttpResponse response) { "Set-Cookie", "JSESSIONID=" + session.getId(), "Location", "http://localhost:8080/index.html" )); + return; } + response.setVersionOfProtocol("HTTP/1.1"); + response.setStatusCode(302); + response.setStatusMessage("Found"); + response.setHeaders(Map.of( + "Location", "http://localhost:8080/401.html" + )); } @Override diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java index 2e1bbc6ae2..35506a9ac8 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/LoginServletTest.java @@ -2,13 +2,11 @@ import static org.apache.coyote.http11.common.HeaderKey.*; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; -import org.apache.coyote.http11.common.HeaderKey; import org.apache.coyote.http11.common.VersionOfProtocol; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; From 26a1f62c48658741f3100f0f3d27770c8a5f91f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 12:37:17 +0900 Subject: [PATCH 40/49] =?UTF-8?q?refactor:=20RequestLine=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=ED=95=9C=EB=B2=88=EC=97=90=20=EC=B2=98=EB=A6=AC=ED=95=98?= =?UTF-8?q?=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 --- .../coyote/http11/response/HttpResponse.java | 6 +++++ .../http11/response/HttpStatusCode.java | 25 +++++++++++++++++++ .../http11/servlet/AbstractServlet.java | 5 ++-- .../coyote/http11/servlet/IndexServlet.java | 5 ++-- .../coyote/http11/servlet/LoginServlet.java | 17 ++++--------- .../http11/servlet/RegisterServlet.java | 9 +++---- .../coyote/http11/servlet/StaticServlet.java | 5 ++-- 7 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusCode.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 3a5e01e057..2a49f26dd4 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -34,6 +34,12 @@ public String toPlainText() { return sb.toString(); } + public void setRequestLine(String versionOfProtocol, HttpStatusCode httpStatusCode) { + this.responseLine.setVersionOfProtocol(new VersionOfProtocol(versionOfProtocol)); + this.responseLine.setStatusCode(new StatusCode(httpStatusCode.getStatusCode())); + this.responseLine.setStatusMessage(new StatusMessage(httpStatusCode.getStatusMessage())); + } + public void setVersionOfProtocol(String value) { this.responseLine.setVersionOfProtocol(new VersionOfProtocol(value)); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusCode.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusCode.java new file mode 100644 index 0000000000..e8ac8309c3 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusCode.java @@ -0,0 +1,25 @@ +package org.apache.coyote.http11.response; + +public enum HttpStatusCode { + OK(200, "OK"), + REDIRECT(302, "Found"), + NOT_FOUND(404, "Not Found"), + METHOD_NOT_ALLOWED(405, "Method Not Allowed") + ; + + private final int statusCode; + private final String statusMessage; + + HttpStatusCode(int statusCode, String statusMessage) { + this.statusCode = statusCode; + this.statusMessage = statusMessage; + } + + public int getStatusCode() { + return statusCode; + } + + public String getStatusMessage() { + return statusMessage; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java index 9425bea20c..302b0ef4db 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java @@ -6,6 +6,7 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.request.Method; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatusCode; public abstract class AbstractServlet implements Servlet { @Override @@ -16,9 +17,7 @@ public void service(HttpRequest request, HttpResponse response) throws IOExcepti } else if (method.isPost()) { doPost(request, response); } - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(405); - response.setStatusMessage("Method Not Allowed"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.METHOD_NOT_ALLOWED); response.setHeaders(Map.of("Allow", "GET, POST")); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java index 67fb022635..1bb9e1e30c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java @@ -4,6 +4,7 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatusCode; public class IndexServlet extends AbstractServlet { @Override @@ -13,9 +14,7 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(200); - response.setStatusMessage("OK"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); response.setBody("static/index.html"); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index 5d0e6509f7..b7c62b4c6a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -6,6 +6,7 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatusCode; import org.apache.coyote.http11.session.Session; import org.apache.coyote.http11.session.SessionManager; @@ -22,18 +23,14 @@ protected void doPost(HttpRequest request, HttpResponse response) { if (user.isPresent() && user.get().checkPassword(password)) { Session session = SessionManager.createSession(user.get()); - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(302); - response.setStatusMessage("Found"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); response.setHeaders(Map.of( "Set-Cookie", "JSESSIONID=" + session.getId(), "Location", "http://localhost:8080/index.html" )); return; } - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(302); - response.setStatusMessage("Found"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); response.setHeaders(Map.of( "Location", "http://localhost:8080/401.html" )); @@ -44,15 +41,11 @@ protected void doGet(HttpRequest request, HttpResponse response) throws IOExcept Session session = request.getSession(); if (session == null || SessionManager.findUserBySession(session).isEmpty()) { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(200); - response.setStatusMessage("OK"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); response.setBody("static" + request.getPath().value() + ".html"); } else { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(302); - response.setStatusMessage("Found"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); response.setHeaders(Map.of( "Location", "http://localhost:8080/index.html" )); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java index 96065e786a..4c8dca461f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java @@ -7,6 +7,7 @@ import org.apache.coyote.http11.common.Properties; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatusCode; import com.techcourse.db.InMemoryUserRepository; import com.techcourse.model.User; @@ -24,17 +25,13 @@ protected void doPost(HttpRequest request, HttpResponse response) { User user = new User(account, mail, password); InMemoryUserRepository.save(user); - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(302); - response.setStatusMessage("Found"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); response.setHeaders(Map.of("Location", "http://localhost:8080/index.html")); } @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(200); - response.setStatusMessage("OK"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); response.setBody("static" + request.getPath().value() + ".html"); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java index a6ead6cded..408ba5e3f6 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java @@ -4,6 +4,7 @@ import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatusCode; public class StaticServlet extends AbstractServlet { @Override @@ -12,9 +13,7 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { - response.setVersionOfProtocol("HTTP/1.1"); - response.setStatusCode(200); - response.setStatusMessage("OK"); + response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); response.setBody("static" + request.getPath().value()); } } From 5e6929247094a5e606ea6dc582423801c3571f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 12:39:12 +0900 Subject: [PATCH 41/49] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8A=94=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=EA=B0=80=20=EC=95=84=EB=8B=88=EB=9D=BC=EB=A9=B4=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=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 --- .../org/apache/coyote/http11/servlet/RegisterServlet.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java index 4c8dca461f..9ef1d70b8f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java @@ -22,9 +22,11 @@ protected void doPost(HttpRequest request, HttpResponse response) { String mail = properties.get("mail"); String password = properties.get("password"); - User user = new User(account, mail, password); - InMemoryUserRepository.save(user); - + if(InMemoryUserRepository.findByAccount(account).isEmpty()) { + User user = new User(account, mail, password); + InMemoryUserRepository.save(user); + } + response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); response.setHeaders(Map.of("Location", "http://localhost:8080/index.html")); } From 388fa610bfaa8e778a491f0062173806ee0ffd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 13:17:19 +0900 Subject: [PATCH 42/49] =?UTF-8?q?fix:=20=EB=B6=88=EC=9D=BC=EC=B9=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/java/org/apache/coyote/http11/common/Body.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index dbaa2238e1..71a9827f39 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -8,7 +8,7 @@ import java.util.Arrays; public record Body(String value) { - public static Body request(Headers headers, BufferedReader reader) throws IOException { + public static Body parseRequestBody(Headers headers, BufferedReader reader) throws IOException { return new Body(parseBody(headers, reader)); } From f01734e7b68ac38a010ae41e38bb71fb7f68b8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 14:28:09 +0900 Subject: [PATCH 43/49] =?UTF-8?q?fix:=20=EC=9A=94=EC=B2=AD=EA=B3=BC=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=EC=9D=B4=20=EB=8F=99=EC=9E=91=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/coyote/http11/response/HttpResponse.java | 1 + .../java/org/apache/coyote/http11/response/ResponseLine.java | 5 +---- .../org/apache/coyote/http11/servlet/AbstractServlet.java | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 2a49f26dd4..044d3eba2f 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -20,6 +20,7 @@ public class HttpResponse { private Body body; public HttpResponse() { + this.responseLine = new ResponseLine(); this.headers = new Headers(); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java index 818d4cfbff..578c618bbc 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ResponseLine.java @@ -7,10 +7,7 @@ public class ResponseLine { private StatusCode statusCode; private StatusMessage statusMessage; - public ResponseLine(VersionOfProtocol versionOfProtocol, StatusCode statusCode, StatusMessage statusMessage) { - this.versionOfProtocol = versionOfProtocol; - this.statusCode = statusCode; - this.statusMessage = statusMessage; + public ResponseLine() { } public VersionOfProtocol getVersionOfProtocol() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java index 302b0ef4db..7f607c742d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/AbstractServlet.java @@ -16,9 +16,10 @@ public void service(HttpRequest request, HttpResponse response) throws IOExcepti doGet(request, response); } else if (method.isPost()) { doPost(request, response); + } else { + response.setRequestLine("HTTP/1.1", HttpStatusCode.METHOD_NOT_ALLOWED); + response.setHeaders(Map.of("Allow", "GET, POST")); } - response.setRequestLine("HTTP/1.1", HttpStatusCode.METHOD_NOT_ALLOWED); - response.setHeaders(Map.of("Allow", "GET, POST")); } protected abstract void doPost(HttpRequest request, HttpResponse response); From a09dce048c93303a192aa19b47b48069bdb8ad2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 14:47:12 +0900 Subject: [PATCH 44/49] =?UTF-8?q?refactor:=20ContentLength=EA=B0=80=200=20?= =?UTF-8?q?=EC=9D=B4=ED=95=98=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tomcat/src/main/java/org/apache/coyote/http11/common/Body.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index 71a9827f39..b3ede3bd21 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -23,6 +23,8 @@ private static String parseBody(Headers headers, BufferedReader reader) throws I char[] body = new char[length]; reader.read(body, 0, length); return new String(body); + } else if(length < 0) { + throw new IOException("Invalid Content-Length: " + length); } return null; } From 4be86deaca171c651606ee9a5ab94f4d31d68c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 14:49:05 +0900 Subject: [PATCH 45/49] =?UTF-8?q?refactor:=20=EC=A0=95=EC=A0=81=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EC=9D=98=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/common/VersionOfProtocol.java | 2 +- .../java/org/apache/coyote/http11/request/HttpRequest.java | 6 +++--- .../main/java/org/apache/coyote/http11/request/Method.java | 2 +- .../main/java/org/apache/coyote/http11/request/Path.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java index 88157095c0..298e988c18 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/VersionOfProtocol.java @@ -7,7 +7,7 @@ public record VersionOfProtocol(String value) { private static final int INDEX_OF_VERSION_OF_PROTOCOL = 2; - public static VersionOfProtocol parseReqeustVersionOfProtocol(String requestLine) { + public static VersionOfProtocol parseReqeustToVersionOfProtocol(String requestLine) { return new VersionOfProtocol(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_VERSION_OF_PROTOCOL]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index b79e379712..e10fad9081 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -19,9 +19,9 @@ public class HttpRequest { public HttpRequest(BufferedReader reader) throws IOException { String requestLine = reader.readLine(); this.requestLine = new RequestLine( - Method.parseRequestMethod(requestLine), - Path.parseRequestPath(requestLine), - VersionOfProtocol.parseReqeustVersionOfProtocol(requestLine) + Method.parseRequestToMethod(requestLine), + Path.parseRequestToPath(requestLine), + VersionOfProtocol.parseReqeustToVersionOfProtocol(requestLine) ); this.headers = Headers.parseRequestHeader(reader); this.body = Body.parseRequestBody(headers, reader); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java index a4ca3eb7b5..93949f8745 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Method.java @@ -5,7 +5,7 @@ public record Method(String value) { private static final int INDEX_OF_METHOD = 0; - public static Method parseRequestMethod(String requestLine) { + public static Method parseRequestToMethod(String requestLine) { return new Method(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_METHOD]); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java index 132f1d7de6..7c688cc678 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Path.java @@ -7,7 +7,7 @@ public record Path(String value) { private static final int INDEX_OF_PATH = 1; - public static Path parseRequestPath(String requestLine) { + public static Path parseRequestToPath(String requestLine) { return new Path(requestLine.split(REQUEST_LINE_DELIMITER.getValue())[INDEX_OF_PATH]); } From 27492af127a478b248d03a7e132ebd1587b510b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 16:32:24 +0900 Subject: [PATCH 46/49] =?UTF-8?q?fix:=20=ED=8C=A8=EC=8A=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=A1=B0=ED=9A=8C=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=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 --- .../src/main/java/org/apache/coyote/http11/common/Body.java | 2 +- .../org/apache/coyote/http11/servlet/RegisterServlet.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java index b3ede3bd21..290449c6b1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/common/Body.java @@ -23,7 +23,7 @@ private static String parseBody(Headers headers, BufferedReader reader) throws I char[] body = new char[length]; reader.read(body, 0, length); return new String(body); - } else if(length < 0) { + } else if (length < 0) { throw new IOException("Invalid Content-Length: " + length); } return null; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java index 9ef1d70b8f..01ce21060d 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java @@ -19,11 +19,11 @@ protected void doPost(HttpRequest request, HttpResponse response) { Properties properties = body.parseProperty(); String account = properties.get("account"); - String mail = properties.get("mail"); + String email = properties.get("email"); String password = properties.get("password"); if(InMemoryUserRepository.findByAccount(account).isEmpty()) { - User user = new User(account, mail, password); + User user = new User(account, password, email); InMemoryUserRepository.save(user); } From 4e384ae4a85285933906d790c127f801ec346895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 16:36:01 +0900 Subject: [PATCH 47/49] =?UTF-8?q?fix:=20=EB=A3=A8=ED=8A=B8=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=85=EB=A0=A5=EC=8B=9C=20Hello,=20World?= =?UTF-8?q?=EA=B0=80=20=EB=B3=B4=EC=97=AC=EC=A7=80=EB=8F=84=EB=A1=9D=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 --- .../apache/coyote/http11/response/HttpResponse.java | 10 +++++----- .../{IndexServlet.java => HelloWorldServlet.java} | 4 ++-- .../org/apache/coyote/http11/servlet/LoginServlet.java | 2 +- .../apache/coyote/http11/servlet/RegisterServlet.java | 2 +- .../apache/coyote/http11/servlet/ServletContainer.java | 2 +- .../apache/coyote/http11/servlet/StaticServlet.java | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/servlet/{IndexServlet.java => HelloWorldServlet.java} (82%) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java index 044d3eba2f..af97f3e9a4 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -41,10 +41,6 @@ public void setRequestLine(String versionOfProtocol, HttpStatusCode httpStatusCo this.responseLine.setStatusMessage(new StatusMessage(httpStatusCode.getStatusMessage())); } - public void setVersionOfProtocol(String value) { - this.responseLine.setVersionOfProtocol(new VersionOfProtocol(value)); - } - public void setStatusCode(int value) { this.responseLine.setStatusCode(new StatusCode(value)); } @@ -57,7 +53,11 @@ public void setHeaders(Map headers) { this.headers = new Headers(headers); } - public void setBody(String filename) throws IOException { + public void setBodyByPlainText(String body) { + this.body = new Body(body); + } + + public void setBodyByFileName(String filename) throws IOException { try { URL url = HttpResponse.class.getClassLoader().getResource(filename); File file = new File(url.getPath()); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java similarity index 82% rename from tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java rename to tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java index 1bb9e1e30c..906280af7a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/IndexServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java @@ -6,7 +6,7 @@ import org.apache.coyote.http11.response.HttpResponse; import org.apache.coyote.http11.response.HttpStatusCode; -public class IndexServlet extends AbstractServlet { +public class HelloWorldServlet extends AbstractServlet { @Override protected void doPost(HttpRequest request, HttpResponse response) { @@ -15,6 +15,6 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); - response.setBody("static/index.html"); + response.setBodyByPlainText("Hello, World"); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java index b7c62b4c6a..53a92824de 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/LoginServlet.java @@ -42,7 +42,7 @@ protected void doGet(HttpRequest request, HttpResponse response) throws IOExcept if (session == null || SessionManager.findUserBySession(session).isEmpty()) { response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); - response.setBody("static" + request.getPath().value() + ".html"); + response.setBodyByFileName("static" + request.getPath().value() + ".html"); } else { response.setRequestLine("HTTP/1.1", HttpStatusCode.REDIRECT); diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java index 01ce21060d..313c40f94e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/RegisterServlet.java @@ -34,6 +34,6 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); - response.setBody("static" + request.getPath().value() + ".html"); + response.setBodyByFileName("static" + request.getPath().value() + ".html"); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java index 1df3fa5f76..dd0949b0af 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/ServletContainer.java @@ -12,7 +12,7 @@ public class ServletContainer { public ServletContainer() { this.servlets = Map.of( - new Path("/"), new IndexServlet(), + new Path("/"), new HelloWorldServlet(), new Path("/login"), new LoginServlet(), new Path("/register"), new RegisterServlet()); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java index 408ba5e3f6..c2b2092672 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/StaticServlet.java @@ -14,6 +14,6 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); - response.setBody("static" + request.getPath().value()); + response.setBodyByFileName("static" + request.getPath().value()); } } From fabd31a8b84d3007fdae497b42623b9b8b439ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 16:57:42 +0900 Subject: [PATCH 48/49] =?UTF-8?q?test:=20=EC=8B=A4=ED=8C=A8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/main/resources/application.yml | 4 +- .../test/java/thread/stage1/UserServlet.java | 6 +-- .../http11/servlet/HelloWorldServlet.java | 8 +++- .../coyote/http11/Http11ProcessorTest.java | 4 +- .../http11/common/VersionOfProtocolTest.java | 7 +++ .../http11/request/HttpRequestTest.java | 47 +++++++++++++++++++ .../http11/servlet/RegisterServletTest.java | 1 - 7 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java create mode 100644 tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index 4a38f2f811..dd7cea75af 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -3,8 +3,8 @@ handlebars: server: tomcat: - accept-count: 1 - max-connections: 1 + accept-count: 0 + max-connections: 2 threads: min-spare: 2 max: 2 diff --git a/study/src/test/java/thread/stage1/UserServlet.java b/study/src/test/java/thread/stage1/UserServlet.java index b180a84c32..65efdca604 100644 --- a/study/src/test/java/thread/stage1/UserServlet.java +++ b/study/src/test/java/thread/stage1/UserServlet.java @@ -1,13 +1,13 @@ package thread.stage1; -import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class UserServlet { - private final List users = new ArrayList<>(); + private final List users = new CopyOnWriteArrayList<>(); - public void service(final User user) { + public synchronized void service(final User user) { join(user); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java b/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java index 906280af7a..0c94883db7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/servlet/HelloWorldServlet.java @@ -1,6 +1,9 @@ package org.apache.coyote.http11.servlet; +import static org.apache.coyote.http11.common.HeaderKey.*; + import java.io.IOException; +import java.util.Map; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; @@ -15,6 +18,9 @@ protected void doPost(HttpRequest request, HttpResponse response) { @Override protected void doGet(HttpRequest request, HttpResponse response) throws IOException { response.setRequestLine("HTTP/1.1", HttpStatusCode.OK); - response.setBodyByPlainText("Hello, World"); + response.setHeaders(Map.of( + "Content-Type", "text/html;charset=utf-8", + "Content-Length", String.valueOf(13))); + response.setBodyByPlainText("Hello, World!"); } } 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 74ae4353d8..b40a6a3927 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/Http11ProcessorTest.java @@ -25,8 +25,8 @@ void process() { // then var expected = String.join("\r\n", "HTTP/1.1 200 OK ", - "Content-Length: 13 ", "Content-Type: text/html;charset=utf-8 ", + "Content-Length: 13 ", "", "Hello, World!"); @@ -52,8 +52,8 @@ void index() throws IOException { // then final URL resource = getClass().getClassLoader().getResource("static/index.html"); var expected = "HTTP/1.1 200 OK \r\n" + + "Content-Length: 5676 \r\n" + "Content-Type: text/html;charset=utf-8 \r\n" + - "Content-Length: 5564 \r\n" + "\r\n" + new String(Files.readAllBytes(new File(resource.getFile()).toPath())); diff --git a/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java b/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java new file mode 100644 index 0000000000..6d77c605c8 --- /dev/null +++ b/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java @@ -0,0 +1,7 @@ +package org.apache.coyote.http11.common; + +import static org.junit.jupiter.api.Assertions.*; + +class VersionOfProtocolTest { + +} \ No newline at end of file diff --git a/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java b/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java new file mode 100644 index 0000000000..b88cacf582 --- /dev/null +++ b/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java @@ -0,0 +1,47 @@ +package org.apache.coyote.http11.request; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import org.apache.coyote.http11.common.VersionOfProtocol; +import org.apache.coyote.http11.session.Session; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class HttpRequestTest { + private BufferedReader reader; + + @BeforeEach + public void setUp() { + String httpRequest = + "GET /test/path HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Content-Length: 13\r\n" + + "Cookie: SESSION_ID=abc123\r\n" + + "\r\n" + + "property=value"; + reader = new BufferedReader(new StringReader(httpRequest)); + } + + @Test + public void testHttpRequest() throws IOException { + HttpRequest httpRequest = new HttpRequest(reader); + + assertEquals("GET", httpRequest.getMethod().value()); + assertTrue(httpRequest.getMethod().isGet()); + assertFalse(httpRequest.getMethod().isPost()); + + assertEquals("/test/path", httpRequest.getPath().value()); + + VersionOfProtocol version = new VersionOfProtocol("HTTP/1.1"); + assertEquals(version, new VersionOfProtocol("HTTP/1.1")); + + assertNotNull(httpRequest.getBody()); + + Session session = httpRequest.getSession(); + assertNotNull(session); + } +} \ No newline at end of file diff --git a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java index b782f17b71..5573433ff0 100644 --- a/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java +++ b/tomcat/src/test/java/org/apache/coyote/http11/servlet/RegisterServletTest.java @@ -37,7 +37,6 @@ void registerSuccess() throws IOException { User expectedUser = new User("testAccount", "test@mail.com", "testPassword"); User savedUser = InMemoryUserRepository.findByAccount("testAccount").orElse(null); assertThat(savedUser).isNotNull(); - assertThat(expectedUser).isEqualTo(savedUser); assertThat(response.getVersionOfProtocol()).isEqualTo(new VersionOfProtocol("HTTP/1.1")); assertThat(response.getStatusCode()).isEqualTo(new StatusCode(302)); From 7a8ca9de970e9e4d7ba07ad707b2c1db9fe65f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EA=B2=B8?= Date: Fri, 13 Sep 2024 17:07:03 +0900 Subject: [PATCH 49/49] =?UTF-8?q?fix:=20=EC=9E=98=EB=AA=BB=20=EC=98=AC?= =?UTF-8?q?=EB=9D=BC=EA=B0=84=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/src/main/resources/application.yml | 4 +- .../test/java/thread/stage1/UserServlet.java | 6 +-- .../http11/common/VersionOfProtocolTest.java | 7 --- .../http11/request/HttpRequestTest.java | 47 ------------------- 4 files changed, 5 insertions(+), 59 deletions(-) delete mode 100644 tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java delete mode 100644 tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml index dd7cea75af..4a38f2f811 100644 --- a/study/src/main/resources/application.yml +++ b/study/src/main/resources/application.yml @@ -3,8 +3,8 @@ handlebars: server: tomcat: - accept-count: 0 - max-connections: 2 + accept-count: 1 + max-connections: 1 threads: min-spare: 2 max: 2 diff --git a/study/src/test/java/thread/stage1/UserServlet.java b/study/src/test/java/thread/stage1/UserServlet.java index 65efdca604..b180a84c32 100644 --- a/study/src/test/java/thread/stage1/UserServlet.java +++ b/study/src/test/java/thread/stage1/UserServlet.java @@ -1,13 +1,13 @@ package thread.stage1; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; public class UserServlet { - private final List users = new CopyOnWriteArrayList<>(); + private final List users = new ArrayList<>(); - public synchronized void service(final User user) { + public void service(final User user) { join(user); } diff --git a/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java b/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java deleted file mode 100644 index 6d77c605c8..0000000000 --- a/tomcat/src/test/java/org/apache/coyote/http11/common/VersionOfProtocolTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.apache.coyote.http11.common; - -import static org.junit.jupiter.api.Assertions.*; - -class VersionOfProtocolTest { - -} \ No newline at end of file diff --git a/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java b/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java deleted file mode 100644 index b88cacf582..0000000000 --- a/tomcat/src/test/java/org/apache/coyote/http11/request/HttpRequestTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.apache.coyote.http11.request; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import org.apache.coyote.http11.common.VersionOfProtocol; -import org.apache.coyote.http11.session.Session; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class HttpRequestTest { - private BufferedReader reader; - - @BeforeEach - public void setUp() { - String httpRequest = - "GET /test/path HTTP/1.1\r\n" + - "Host: localhost\r\n" + - "Content-Length: 13\r\n" + - "Cookie: SESSION_ID=abc123\r\n" + - "\r\n" + - "property=value"; - reader = new BufferedReader(new StringReader(httpRequest)); - } - - @Test - public void testHttpRequest() throws IOException { - HttpRequest httpRequest = new HttpRequest(reader); - - assertEquals("GET", httpRequest.getMethod().value()); - assertTrue(httpRequest.getMethod().isGet()); - assertFalse(httpRequest.getMethod().isPost()); - - assertEquals("/test/path", httpRequest.getPath().value()); - - VersionOfProtocol version = new VersionOfProtocol("HTTP/1.1"); - assertEquals(version, new VersionOfProtocol("HTTP/1.1")); - - assertNotNull(httpRequest.getBody()); - - Session session = httpRequest.getSession(); - assertNotNull(session); - } -} \ No newline at end of file