diff --git a/study/src/main/resources/application.yml b/study/src/main/resources/application.yml
index 8b74bdfd88..9e7edae7af 100644
--- a/study/src/main/resources/application.yml
+++ b/study/src/main/resources/application.yml
@@ -4,7 +4,7 @@ handlebars:
server:
tomcat:
accept-count: 1
- max-connections: 1
+ max-connections: 2
threads:
min-spare: 2
max: 2
diff --git a/study/src/test/java/thread/stage0/SynchronizationTest.java b/study/src/test/java/thread/stage0/SynchronizationTest.java
index 59afce5646..6297f3dfdf 100644
--- a/study/src/test/java/thread/stage0/SynchronizationTest.java
+++ b/study/src/test/java/thread/stage0/SynchronizationTest.java
@@ -8,21 +8,17 @@
import org.junit.jupiter.api.Test;
/**
- * 다중 스레드 환경에서 두 개 이상의 스레드가 변경 가능한(mutable) 공유 데이터를 동시에 업데이트하면 경쟁 조건(race condition)이 발생한다.
- * 자바는 공유 데이터에 대한 스레드 접근을 동기화(synchronization)하여 경쟁 조건을 방지한다.
- * 동기화된 블록은 하나의 스레드만 접근하여 실행할 수 있다.
- *
- * Synchronization
- * https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
+ * 다중 스레드 환경에서 두 개 이상의 스레드가 변경 가능한(mutable) 공유 데이터를 동시에 업데이트하면 경쟁 조건(race condition)이 발생한다. 자바는 공유 데이터에 대한 스레드 접근을
+ * 동기화(synchronization)하여 경쟁 조건을 방지한다. 동기화된 블록은 하나의 스레드만 접근하여 실행할 수 있다.
+ *
+ * Synchronization https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
*/
class SynchronizationTest {
/**
- * 테스트가 성공하도록 SynchronizedMethods 클래스에 동기화를 적용해보자.
- * synchronized 키워드에 대하여 찾아보고 적용하면 된다.
- *
- * Guide to the Synchronized Keyword in Java
- * https://www.baeldung.com/java-synchronized
+ * 테스트가 성공하도록 SynchronizedMethods 클래스에 동기화를 적용해보자. synchronized 키워드에 대하여 찾아보고 적용하면 된다.
+ *
+ * Guide to the Synchronized Keyword in Java https://www.baeldung.com/java-synchronized
*/
@Test
void testSynchronized() throws InterruptedException {
diff --git a/study/src/test/java/thread/stage0/ThreadPoolsTest.java b/study/src/test/java/thread/stage0/ThreadPoolsTest.java
index c3ecd5c80c..afe5ff6db2 100644
--- a/study/src/test/java/thread/stage0/ThreadPoolsTest.java
+++ b/study/src/test/java/thread/stage0/ThreadPoolsTest.java
@@ -9,14 +9,11 @@
import org.slf4j.LoggerFactory;
/**
- * 스레드 풀은 무엇이고 어떻게 동작할까?
- * 테스트를 통과시키고 왜 해당 결과가 나왔는지 생각해보자.
- *
- * Thread Pools
- * https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
- *
- * Introduction to Thread Pools in Java
- * https://www.baeldung.com/thread-pool-java-and-guava
+ * 스레드 풀은 무엇이고 어떻게 동작할까? 테스트를 통과시키고 왜 해당 결과가 나왔는지 생각해보자.
+ *
+ * Thread Pools https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
+ *
+ * Introduction to Thread Pools in Java https://www.baeldung.com/thread-pool-java-and-guava
*/
class ThreadPoolsTest {
diff --git a/tomcat/src/main/java/com/techcourse/Application.java b/tomcat/src/main/java/com/techcourse/Application.java
index 6dc0e04e1d..dd81f6f6a0 100644
--- a/tomcat/src/main/java/com/techcourse/Application.java
+++ b/tomcat/src/main/java/com/techcourse/Application.java
@@ -1,6 +1,6 @@
package com.techcourse;
-import org.apache.catalina.startup.Tomcat;
+import org.apache.coyote.startup.Tomcat;
public class Application {
diff --git a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java
index d3fa57feeb..f1c4a0567a 100644
--- a/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java
+++ b/tomcat/src/main/java/com/techcourse/db/InMemoryUserRepository.java
@@ -10,10 +10,7 @@ public class InMemoryUserRepository {
private static final Map database = new ConcurrentHashMap<>();
- static {
- final User user = new User(1L, "gugu", "password", "hkkang@woowahan.com");
- database.put(user.getAccount(), user);
- }
+ private InMemoryUserRepository() {}
public static void save(User user) {
database.put(user.getAccount(), user);
@@ -23,5 +20,7 @@ public static Optional findByAccount(String account) {
return Optional.ofNullable(database.get(account));
}
- private InMemoryUserRepository() {}
+ public static void reset() {
+ database.clear();
+ }
}
diff --git a/tomcat/src/main/java/org/apache/catalina/ServletContainer.java b/tomcat/src/main/java/org/apache/catalina/ServletContainer.java
new file mode 100644
index 0000000000..ae74f93aaa
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/ServletContainer.java
@@ -0,0 +1,20 @@
+package org.apache.catalina;
+
+import org.apache.catalina.controller.Controller;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.apache.coyote.processor.ControllerMapper;
+
+public class ServletContainer {
+
+ private final ControllerMapper controllerMapper;
+
+ public ServletContainer(ControllerMapper controllerMapper) {
+ this.controllerMapper = controllerMapper;
+ }
+
+ public void run(HttpRequest httpRequest, HttpResponse httpResponse) {
+ Controller controller = controllerMapper.getController(httpRequest.getPath());
+ controller.service(httpRequest, httpResponse);
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/catalina/controller/AbstractController.java b/tomcat/src/main/java/org/apache/catalina/controller/AbstractController.java
new file mode 100644
index 0000000000..fc99718cf4
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/controller/AbstractController.java
@@ -0,0 +1,37 @@
+package org.apache.catalina.controller;
+
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.HttpMethod;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+
+public abstract class AbstractController implements Controller {
+
+ @Override
+ public void service(HttpRequest request, HttpResponse response) {
+ try {
+ if (request.isMethod(HttpMethod.GET)) {
+ doGet(request, response);
+ return;
+ }
+ if (request.isMethod(HttpMethod.POST)) {
+ doPost(request, response);
+ return;
+ }
+ throw new IllegalArgumentException("HttpMethod not found");
+ } catch (IllegalArgumentException e) {
+ response.setStatusCode(StatusCode.FOUND);
+ response.addHeader(HeaderName.LOCATION, "/500.html");
+ }
+ }
+
+ protected void doPost(HttpRequest request, HttpResponse response) {
+ throw new IllegalArgumentException("HttpMethod unsupported");
+ }
+
+ protected void doGet(HttpRequest request, HttpResponse response) {
+ throw new IllegalArgumentException("HttpMethod unsupported");
+ }
+}
+
diff --git a/tomcat/src/main/java/org/apache/catalina/controller/Controller.java b/tomcat/src/main/java/org/apache/catalina/controller/Controller.java
new file mode 100644
index 0000000000..7ca917421c
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/controller/Controller.java
@@ -0,0 +1,9 @@
+package org.apache.catalina.controller;
+
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+
+public interface Controller {
+
+ void service(HttpRequest request, HttpResponse response);
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/HomeController.java b/tomcat/src/main/java/org/apache/catalina/controller/HomeController.java
similarity index 56%
rename from tomcat/src/main/java/org/apache/coyote/controller/HomeController.java
rename to tomcat/src/main/java/org/apache/catalina/controller/HomeController.java
index 7b47ba6fdd..51ccda8134 100644
--- a/tomcat/src/main/java/org/apache/coyote/controller/HomeController.java
+++ b/tomcat/src/main/java/org/apache/catalina/controller/HomeController.java
@@ -1,8 +1,8 @@
-package org.apache.coyote.controller;
+package org.apache.catalina.controller;
-import org.apache.coyote.http.StatusCode;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
public class HomeController extends AbstractController {
diff --git a/tomcat/src/main/java/org/apache/catalina/controller/LoginController.java b/tomcat/src/main/java/org/apache/catalina/controller/LoginController.java
new file mode 100644
index 0000000000..6ee925abcd
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/controller/LoginController.java
@@ -0,0 +1,61 @@
+package org.apache.catalina.controller;
+
+import com.techcourse.db.InMemoryUserRepository;
+import com.techcourse.model.User;
+import java.util.Optional;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.manager.SessionManager;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+
+public class LoginController extends AbstractController {
+
+ private final SessionManager sessionManager;
+
+ public LoginController() {
+ this.sessionManager = SessionManager.getInstance();
+ }
+
+ @Override
+ protected void doPost(HttpRequest request, HttpResponse response) {
+ String account = request.getBodyParam("account");
+ String password = request.getBodyParam("password");
+ Optional user = InMemoryUserRepository.findByAccount(account);
+ if (!isMember(user, password)) {
+ response.setStatusCode(StatusCode.FOUND);
+ response.addHeader(HeaderName.LOCATION, "/401.html");
+
+ }
+ if (isMember(user, password)) {
+ response.setStatusCode(StatusCode.FOUND);
+ response.addHeader(HeaderName.LOCATION, "/index.html");
+ login(response, user.get());
+ }
+ }
+
+ private boolean isMember(Optional user, String password) {
+ return user.isPresent() && user.get().checkPassword(password);
+ }
+
+ private void login(HttpResponse response, User user) {
+ String sessionId = sessionManager.generateSession(user);
+ response.addSession(sessionId);
+ }
+
+ @Override
+ protected void doGet(HttpRequest request, HttpResponse response) {
+ if (hasLogined(request)) {
+ response.setStatusCode(StatusCode.FOUND);
+ response.addHeader(HeaderName.LOCATION, "/index.html");
+ }
+ if (!hasLogined(request)) {
+ response.setStatusCode(StatusCode.OK);
+ response.setBody("/login.html");
+ }
+ }
+
+ private boolean hasLogined(HttpRequest request) {
+ return request.hasSession() && sessionManager.isSessionExist(request.getSessionId());
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java b/tomcat/src/main/java/org/apache/catalina/controller/RegisterController.java
similarity index 56%
rename from tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java
rename to tomcat/src/main/java/org/apache/catalina/controller/RegisterController.java
index 79a0b1be5b..eb5fd26f23 100644
--- a/tomcat/src/main/java/org/apache/coyote/controller/RegisterController.java
+++ b/tomcat/src/main/java/org/apache/catalina/controller/RegisterController.java
@@ -1,21 +1,19 @@
-package org.apache.coyote.controller;
+package org.apache.catalina.controller;
import com.techcourse.db.InMemoryUserRepository;
import com.techcourse.model.User;
-import org.apache.coyote.http.HeaderName;
-import org.apache.coyote.http.StatusCode;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.request.RequestBody;
-import org.apache.coyote.response.HttpResponse;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
public class RegisterController extends AbstractController {
@Override
protected void doPost(HttpRequest request, HttpResponse response) {
- RequestBody requestBody = request.getBody();
- String account = requestBody.get("account");
- String password = requestBody.get("password");
- String email = requestBody.get("email");
+ String account = request.getBodyParam("account");
+ String password = request.getBodyParam("password");
+ String email = request.getBodyParam("email");
InMemoryUserRepository.save(new User(account, password, email));
response.setStatusCode(StatusCode.FOUND);
diff --git a/tomcat/src/main/java/org/apache/coyote/coockie/HttpCookie.java b/tomcat/src/main/java/org/apache/catalina/coockie/HttpCookie.java
similarity index 55%
rename from tomcat/src/main/java/org/apache/coyote/coockie/HttpCookie.java
rename to tomcat/src/main/java/org/apache/catalina/coockie/HttpCookie.java
index c8f5ccd3b1..1532757c62 100644
--- a/tomcat/src/main/java/org/apache/coyote/coockie/HttpCookie.java
+++ b/tomcat/src/main/java/org/apache/catalina/coockie/HttpCookie.java
@@ -1,11 +1,18 @@
-package org.apache.coyote.coockie;
+package org.apache.catalina.coockie;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.stream.Collectors;
public class HttpCookie {
+ public static final String COOKIE_DELIMITER = "; ";
+ public static final String COOKIE_VALUE_DELIMITER = "=";
+ public static final int KEY_INDEX = 0;
+ public static final int VALUE_INDEX = 1;
+ public static final int KEY_VALUE_COUNT = 2;
private static final String JSESSIONID_VALUE = "JSESSIONID";
private final Map cookies;
@@ -19,18 +26,14 @@ public HttpCookie(String rawCookies) {
}
private static Map mapCookies(String rawCookies) {
- Map cookieGroup = new HashMap<>();
-
- if (rawCookies != null && !rawCookies.isBlank()) {
- String[] cookiesElements = rawCookies.split("; ");
- for (int i = 0; i < cookiesElements.length; i++) {
- String[] cookiePair = cookiesElements[i].split("=");
- if (cookiePair.length > 1) {
- cookieGroup.put(cookiePair[0], cookiePair[1]);
- }
- }
+ if (rawCookies == null || rawCookies.isBlank()) {
+ return Map.of();
}
- return cookieGroup;
+
+ return Arrays.stream(rawCookies.split(COOKIE_DELIMITER))
+ .map(cookie -> cookie.split(COOKIE_VALUE_DELIMITER))
+ .filter(cookiePair -> cookiePair.length == KEY_VALUE_COUNT)
+ .collect(Collectors.toMap(cookiePair -> cookiePair[KEY_INDEX], cookiePair -> cookiePair[VALUE_INDEX]));
}
public boolean hasSessionId() {
@@ -41,6 +44,10 @@ public String getSessionId() {
return cookies.get(JSESSIONID_VALUE);
}
+ public boolean hasCookie() {
+ return !cookies.isEmpty();
+ }
+
public String getResponse() {
if (cookies.isEmpty()) {
return "";
@@ -49,7 +56,7 @@ public String getResponse() {
StringBuilder response = new StringBuilder();
for (Entry stringStringEntry : cookies.entrySet()) {
response.append(stringStringEntry.getKey())
- .append("=")
+ .append(COOKIE_VALUE_DELIMITER)
.append(stringStringEntry.getValue())
.append(";");
}
diff --git a/tomcat/src/main/java/com/techcourse/exception/UncheckedServletException.java b/tomcat/src/main/java/org/apache/catalina/exception/UncheckedServletException.java
similarity index 57%
rename from tomcat/src/main/java/com/techcourse/exception/UncheckedServletException.java
rename to tomcat/src/main/java/org/apache/catalina/exception/UncheckedServletException.java
index 64466b42de..549a48bcb3 100644
--- a/tomcat/src/main/java/com/techcourse/exception/UncheckedServletException.java
+++ b/tomcat/src/main/java/org/apache/catalina/exception/UncheckedServletException.java
@@ -1,8 +1,8 @@
-package com.techcourse.exception;
+package org.apache.catalina.exception;
public class UncheckedServletException extends RuntimeException {
public UncheckedServletException(Exception e) {
- super(e);
+ super("UncheckedServletException occured", e);
}
}
diff --git a/tomcat/src/main/java/org/apache/catalina/http/HeaderName.java b/tomcat/src/main/java/org/apache/catalina/http/HeaderName.java
new file mode 100644
index 0000000000..fec3ad723c
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/http/HeaderName.java
@@ -0,0 +1,21 @@
+package org.apache.catalina.http;
+
+public enum HeaderName {
+ CONTENT_LENGTH("Content-Length"),
+ COOKIE("Cookie"),
+ CONTENT_TYPE("Content-Type"),
+ LOCATION("Location"),
+ SET_COOKIE("Set-Cookie"),
+
+ ;
+
+ private final String value;
+
+ HeaderName(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/http/HttpMethod.java b/tomcat/src/main/java/org/apache/catalina/http/HttpMethod.java
similarity index 58%
rename from tomcat/src/main/java/org/apache/coyote/http/HttpMethod.java
rename to tomcat/src/main/java/org/apache/catalina/http/HttpMethod.java
index ecc69cf8d8..487c55cde3 100644
--- a/tomcat/src/main/java/org/apache/coyote/http/HttpMethod.java
+++ b/tomcat/src/main/java/org/apache/catalina/http/HttpMethod.java
@@ -1,4 +1,4 @@
-package org.apache.coyote.http;
+package org.apache.catalina.http;
public enum HttpMethod {
GET,
diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ProtocolVersion.java b/tomcat/src/main/java/org/apache/catalina/http/ProtocolVersion.java
similarity index 87%
rename from tomcat/src/main/java/org/apache/coyote/http11/ProtocolVersion.java
rename to tomcat/src/main/java/org/apache/catalina/http/ProtocolVersion.java
index 1955a3942c..238be35385 100644
--- a/tomcat/src/main/java/org/apache/coyote/http11/ProtocolVersion.java
+++ b/tomcat/src/main/java/org/apache/catalina/http/ProtocolVersion.java
@@ -1,4 +1,4 @@
-package org.apache.coyote.http11;
+package org.apache.catalina.http;
public enum ProtocolVersion {
HTTP1_1("HTTP/1.1"),
diff --git a/tomcat/src/main/java/org/apache/coyote/http/StatusCode.java b/tomcat/src/main/java/org/apache/catalina/http/StatusCode.java
similarity index 92%
rename from tomcat/src/main/java/org/apache/coyote/http/StatusCode.java
rename to tomcat/src/main/java/org/apache/catalina/http/StatusCode.java
index d521fda212..77cc8eaa8f 100644
--- a/tomcat/src/main/java/org/apache/coyote/http/StatusCode.java
+++ b/tomcat/src/main/java/org/apache/catalina/http/StatusCode.java
@@ -1,4 +1,4 @@
-package org.apache.coyote.http;
+package org.apache.catalina.http;
public enum StatusCode {
OK(200, "OK"),
diff --git a/tomcat/src/main/java/org/apache/coyote/manager/Manager.java b/tomcat/src/main/java/org/apache/catalina/manager/Manager.java
similarity index 95%
rename from tomcat/src/main/java/org/apache/coyote/manager/Manager.java
rename to tomcat/src/main/java/org/apache/catalina/manager/Manager.java
index 9d87f2970a..71459eb82b 100644
--- a/tomcat/src/main/java/org/apache/coyote/manager/Manager.java
+++ b/tomcat/src/main/java/org/apache/catalina/manager/Manager.java
@@ -1,7 +1,7 @@
-package org.apache.coyote.manager;
+package org.apache.catalina.manager;
import java.io.IOException;
-import org.apache.coyote.session.Session;
+import org.apache.catalina.session.Session;
/**
* A Manager manages the pool of Sessions that are associated with a
diff --git a/tomcat/src/main/java/org/apache/coyote/manager/SessionManager.java b/tomcat/src/main/java/org/apache/catalina/manager/SessionManager.java
similarity index 77%
rename from tomcat/src/main/java/org/apache/coyote/manager/SessionManager.java
rename to tomcat/src/main/java/org/apache/catalina/manager/SessionManager.java
index fe0c706c63..c0e8ab79c8 100644
--- a/tomcat/src/main/java/org/apache/coyote/manager/SessionManager.java
+++ b/tomcat/src/main/java/org/apache/catalina/manager/SessionManager.java
@@ -1,12 +1,12 @@
-package org.apache.coyote.manager;
+package org.apache.catalina.manager;
import com.techcourse.model.User;
-import java.util.HashMap;
import java.util.Map;
-import org.apache.coyote.session.Session;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.catalina.session.Session;
public class SessionManager implements Manager {
- private static final Map SESSIONS = new HashMap<>();
+ private static final Map SESSIONS = new ConcurrentHashMap<>();
private static SessionManager instance;
private SessionManager() {
@@ -14,7 +14,7 @@ private SessionManager() {
public static SessionManager getInstance() {
if (instance == null) {
- return new SessionManager();
+ instance = new SessionManager();
}
return instance;
}
diff --git a/tomcat/src/main/java/org/apache/coyote/request/HttpRequest.java b/tomcat/src/main/java/org/apache/catalina/request/HttpRequest.java
similarity index 87%
rename from tomcat/src/main/java/org/apache/coyote/request/HttpRequest.java
rename to tomcat/src/main/java/org/apache/catalina/request/HttpRequest.java
index e0c25a843f..f5f0ecb5e5 100644
--- a/tomcat/src/main/java/org/apache/coyote/request/HttpRequest.java
+++ b/tomcat/src/main/java/org/apache/catalina/request/HttpRequest.java
@@ -1,7 +1,7 @@
-package org.apache.coyote.request;
+package org.apache.catalina.request;
import java.util.List;
-import org.apache.coyote.http.HttpMethod;
+import org.apache.catalina.http.HttpMethod;
public class HttpRequest {
@@ -42,6 +42,10 @@ public String getHttpCookie() {
return header.getHttpCookie();
}
+ public boolean hasCookie() {
+ return header.hasCookie();
+ }
+
public boolean isMethod(HttpMethod httpMethod) {
return requestLine.isMethod(httpMethod);
}
@@ -50,19 +54,15 @@ public boolean isStaticRequest() {
return requestLine.isStaticRequest();
}
- public boolean hasQueryParam() {
- return requestLine.hasQueryParam();
- }
-
public boolean hasSession() {
return header.hasSession();
}
- public RequestBody getBody() {
- return body;
+ public String getBodyParam(String parameter) {
+ return body.get(parameter);
}
- public String getBody(String parameter) {
- return body.get(parameter);
+ public RequestBody getBody() {
+ return body;
}
}
diff --git a/tomcat/src/main/java/org/apache/coyote/request/QueuryParam.java b/tomcat/src/main/java/org/apache/catalina/request/QueuyParam.java
similarity index 62%
rename from tomcat/src/main/java/org/apache/coyote/request/QueuryParam.java
rename to tomcat/src/main/java/org/apache/catalina/request/QueuyParam.java
index 063ee3b15c..4b27665b13 100644
--- a/tomcat/src/main/java/org/apache/coyote/request/QueuryParam.java
+++ b/tomcat/src/main/java/org/apache/catalina/request/QueuyParam.java
@@ -1,17 +1,19 @@
-package org.apache.coyote.request;
+package org.apache.catalina.request;
import java.util.HashMap;
import java.util.Map;
-public class QueuryParam {
+public class QueuyParam {
public static final String QUERY_INDICATOR = "?";
- public static final String QUERY_COMPONENT_DELIMITER = "&";
- public static final String QUERY_COMPONENT_VALUE_DELIMITER = "=";
+ public static final String COMPONENT_DELIMITER = "&";
+ public static final String COMPONENT_VALUE_DELIMITER = "=";
+ public static final int KEY_INDEX = 0;
+ public static final int VALUE_INDEX = 1;
private final Map params;
- public QueuryParam(String requestLineEntry) {
+ public QueuyParam(String requestLineEntry) {
this.params = mapQueryParam(requestLineEntry);
}
@@ -23,12 +25,12 @@ private Map mapQueryParam(String requestLineEntry) {
int queryParamIndex = requestLineEntry.indexOf(QUERY_INDICATOR);
String queryString = requestLineEntry.substring(queryParamIndex + 1);
- String[] splittedQueryString = queryString.split(QUERY_COMPONENT_DELIMITER);
+ String[] splittedQueryString = queryString.split(COMPONENT_DELIMITER);
for (String queryParamEntry : splittedQueryString) {
mappedQueryParams.put(
- queryParamEntry.split(QUERY_COMPONENT_VALUE_DELIMITER)[0],
- queryParamEntry.split(QUERY_COMPONENT_VALUE_DELIMITER)[1]
+ queryParamEntry.split(COMPONENT_VALUE_DELIMITER)[KEY_INDEX],
+ queryParamEntry.split(COMPONENT_VALUE_DELIMITER)[VALUE_INDEX]
);
}
return mappedQueryParams;
diff --git a/tomcat/src/main/java/org/apache/catalina/request/RequestBody.java b/tomcat/src/main/java/org/apache/catalina/request/RequestBody.java
new file mode 100644
index 0000000000..59d5312027
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/request/RequestBody.java
@@ -0,0 +1,43 @@
+package org.apache.catalina.request;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class RequestBody {
+
+ public static final String COMPONENT_DELIMITER = "&";
+ public static final String COMPONENT_VALUE_DELIMITER = "=";
+ public static final int KEY_INDEX = 0;
+ public static final int VALUE_INDEX = 1;
+
+ private final Map body;
+
+ public RequestBody() {
+ this.body = new HashMap<>();
+ }
+
+ public RequestBody(String bodyLine) {
+ this.body = mapBody(bodyLine);
+ }
+
+ private Map mapBody(String bodyLine) {
+ if (bodyLine == null || bodyLine.isEmpty()) {
+ return Map.of();
+ }
+
+ return Arrays.stream(bodyLine.split(COMPONENT_DELIMITER))
+ .map(bodyElement -> bodyElement.split(COMPONENT_VALUE_DELIMITER))
+ .filter(bodyElements -> bodyElements.length == 2)
+ .collect(Collectors.toMap(bodyElements -> bodyElements[KEY_INDEX],
+ bodyElements -> bodyElements[VALUE_INDEX]));
+ }
+
+ public String get(String key) {
+ if (!body.containsKey(key)) {
+ throw new IllegalArgumentException("Body parameter not found");
+ }
+ return body.get(key);
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/request/RequestHeader.java b/tomcat/src/main/java/org/apache/catalina/request/RequestHeader.java
similarity index 65%
rename from tomcat/src/main/java/org/apache/coyote/request/RequestHeader.java
rename to tomcat/src/main/java/org/apache/catalina/request/RequestHeader.java
index 1b478cd98b..dc49643d8d 100644
--- a/tomcat/src/main/java/org/apache/coyote/request/RequestHeader.java
+++ b/tomcat/src/main/java/org/apache/catalina/request/RequestHeader.java
@@ -1,13 +1,18 @@
-package org.apache.coyote.request;
+package org.apache.catalina.request;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.coyote.coockie.HttpCookie;
-import org.apache.coyote.http.HeaderName;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.coockie.HttpCookie;
public class RequestHeader {
+ public static final String NAME_VALUE_DELIMITER = ": ";
+ public static final int NAME_VALUE_COUNT = 2;
+ public static final int NAME_INDEX = 0;
+ public static final int VALUE_INDEX = 1;
+
private final Map header;
private final HttpCookie httpCookie;
@@ -27,8 +32,8 @@ private Map mapHeader(List headerLines) {
Map rawHeader = new HashMap<>();
for (String line : headerLines) {
- String[] headerEntry = line.split(": ", 2);
- rawHeader.put(headerEntry[0], headerEntry[1]);
+ String[] headerEntry = line.split(NAME_VALUE_DELIMITER, NAME_VALUE_COUNT);
+ rawHeader.put(headerEntry[NAME_INDEX], headerEntry[VALUE_INDEX]);
}
return rawHeader;
}
@@ -44,4 +49,8 @@ public String getSessionId() {
public String getHttpCookie() {
return httpCookie.getResponse();
}
+
+ public boolean hasCookie() {
+ return httpCookie.hasCookie();
+ }
}
diff --git a/tomcat/src/main/java/org/apache/coyote/request/RequestLine.java b/tomcat/src/main/java/org/apache/catalina/request/RequestLine.java
similarity index 63%
rename from tomcat/src/main/java/org/apache/coyote/request/RequestLine.java
rename to tomcat/src/main/java/org/apache/catalina/request/RequestLine.java
index 350fa4d465..913136674c 100644
--- a/tomcat/src/main/java/org/apache/coyote/request/RequestLine.java
+++ b/tomcat/src/main/java/org/apache/catalina/request/RequestLine.java
@@ -1,31 +1,37 @@
-package org.apache.coyote.request;
+package org.apache.catalina.request;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
-import org.apache.coyote.http.HttpMethod;
+import org.apache.catalina.http.HttpMethod;
public class RequestLine {
+ public static final String COMPONENT_DELIMITER = " ";
+ public static final String PATH_INDICATOR = "?";
+ public static final int METHOD_INDEX = 0;
+ public static final int PATH_INDEX = 1;
+ public static final int VERSION_OF_PROTOCOL_INDEX = 2;
+
private final HttpMethod httpMethod;
private final String path;
private final String versionOfProtocol;
- private final QueuryParam queryParams;
+ private final QueuyParam queryParams;
public RequestLine(String headerLines) {
- String[] requestLineEntries = headerLines.split(" ");
+ String[] requestLineEntries = headerLines.split(COMPONENT_DELIMITER);
- this.httpMethod = HttpMethod.valueOf(requestLineEntries[0]);
- this.queryParams = new QueuryParam(requestLineEntries[1]);
- this.path = mapPath(requestLineEntries[1]);
- this.versionOfProtocol = requestLineEntries[2];
+ this.httpMethod = HttpMethod.valueOf(requestLineEntries[METHOD_INDEX]);
+ this.queryParams = new QueuyParam(requestLineEntries[PATH_INDEX]);
+ this.path = mapPath(requestLineEntries[PATH_INDEX]);
+ this.versionOfProtocol = requestLineEntries[VERSION_OF_PROTOCOL_INDEX];
}
private String mapPath(String path) {
if (queryParams.hasQueryParam()) {
- int queryStringIndex = path.indexOf("?");
+ int queryStringIndex = path.indexOf(PATH_INDICATOR);
return path.substring(0, queryStringIndex);
}
return path;
diff --git a/tomcat/src/main/java/org/apache/coyote/response/HttpResponse.java b/tomcat/src/main/java/org/apache/catalina/response/HttpResponse.java
similarity index 55%
rename from tomcat/src/main/java/org/apache/coyote/response/HttpResponse.java
rename to tomcat/src/main/java/org/apache/catalina/response/HttpResponse.java
index 05c460a468..6dbd62aba2 100644
--- a/tomcat/src/main/java/org/apache/coyote/response/HttpResponse.java
+++ b/tomcat/src/main/java/org/apache/catalina/response/HttpResponse.java
@@ -1,7 +1,10 @@
-package org.apache.coyote.response;
+package org.apache.catalina.response;
-import org.apache.coyote.http.HeaderName;
-import org.apache.coyote.http.StatusCode;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.StatusCode;
public class HttpResponse {
@@ -34,8 +37,25 @@ public void addHeader(HeaderName headerName, String value) {
header.addHeader(headerName, value);
}
+ public void setBody(String path, String contentType) {
+ body.setBody(path);
+ header.addHeader(HeaderName.CONTENT_LENGTH, String.valueOf(body.getLength()));
+ header.addHeader(HeaderName.CONTENT_TYPE, contentType);
+ }
+
public void setBody(String resource) {
body.setBody(resource);
header.addHeader(HeaderName.CONTENT_LENGTH, String.valueOf(body.getLength()));
+ String contentType;
+ try {
+ contentType = Files.probeContentType(new File(resource).toPath());
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Not found path");
+ }
+ header.addHeader(HeaderName.CONTENT_TYPE, contentType);
+ }
+
+ public void addSession(String sessionId) {
+ header.addSession(sessionId);
}
}
diff --git a/tomcat/src/main/java/org/apache/coyote/response/ResponseBody.java b/tomcat/src/main/java/org/apache/catalina/response/ResponseBody.java
similarity index 86%
rename from tomcat/src/main/java/org/apache/coyote/response/ResponseBody.java
rename to tomcat/src/main/java/org/apache/catalina/response/ResponseBody.java
index 105921ce7b..9834397160 100644
--- a/tomcat/src/main/java/org/apache/coyote/response/ResponseBody.java
+++ b/tomcat/src/main/java/org/apache/catalina/response/ResponseBody.java
@@ -1,6 +1,7 @@
-package org.apache.coyote.response;
+package org.apache.catalina.response;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -32,7 +33,7 @@ public void setBody(String resource) {
}
public int getLength() {
- return content.length();
+ return content.getBytes(StandardCharsets.UTF_8).length;
}
public String getContent() {
diff --git a/tomcat/src/main/java/org/apache/coyote/response/ResponseHeader.java b/tomcat/src/main/java/org/apache/catalina/response/ResponseHeader.java
similarity index 68%
rename from tomcat/src/main/java/org/apache/coyote/response/ResponseHeader.java
rename to tomcat/src/main/java/org/apache/catalina/response/ResponseHeader.java
index 9079199079..05ffde41a7 100644
--- a/tomcat/src/main/java/org/apache/coyote/response/ResponseHeader.java
+++ b/tomcat/src/main/java/org/apache/catalina/response/ResponseHeader.java
@@ -1,12 +1,14 @@
-package org.apache.coyote.response;
+package org.apache.catalina.response;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
-import org.apache.coyote.http.HeaderName;
+import org.apache.catalina.http.HeaderName;
public class ResponseHeader {
+ public static final String SESSION_KEY = "JSESSIONID";
+ public static final String SESSION_DELIMITER = "=";
private final Map header;
public ResponseHeader() {
@@ -28,4 +30,8 @@ public String getResponse() {
}
return String.valueOf(response);
}
+
+ public void addSession(String sessionId) {
+ addHeader(HeaderName.SET_COOKIE, SESSION_KEY + SESSION_DELIMITER + sessionId);
+ }
}
diff --git a/tomcat/src/main/java/org/apache/catalina/response/StatusLine.java b/tomcat/src/main/java/org/apache/catalina/response/StatusLine.java
new file mode 100644
index 0000000000..029ccd60d0
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/catalina/response/StatusLine.java
@@ -0,0 +1,23 @@
+package org.apache.catalina.response;
+
+import org.apache.catalina.http.ProtocolVersion;
+import org.apache.catalina.http.StatusCode;
+
+public class StatusLine {
+
+ private final ProtocolVersion versionOfProtocol;
+ private StatusCode statusCode;
+
+ public StatusLine() {
+ this.versionOfProtocol = ProtocolVersion.HTTP1_1;
+ this.statusCode = StatusCode.OK;
+ }
+
+ public String getResponse() {
+ return "%s %s %s".formatted(versionOfProtocol.getValue(), statusCode.getCode(), statusCode.getMessage());
+ }
+
+ public void setStatusCode(StatusCode statusCode) {
+ this.statusCode = statusCode;
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/session/Session.java b/tomcat/src/main/java/org/apache/catalina/session/Session.java
similarity index 94%
rename from tomcat/src/main/java/org/apache/coyote/session/Session.java
rename to tomcat/src/main/java/org/apache/catalina/session/Session.java
index 71b179e577..ecc62c36a4 100644
--- a/tomcat/src/main/java/org/apache/coyote/session/Session.java
+++ b/tomcat/src/main/java/org/apache/catalina/session/Session.java
@@ -1,4 +1,4 @@
-package org.apache.coyote.session;
+package org.apache.catalina.session;
import com.techcourse.model.User;
import java.util.HashMap;
diff --git a/tomcat/src/main/java/org/apache/coyote/connector/Connector.java b/tomcat/src/main/java/org/apache/coyote/connector/Connector.java
index 4a132ed9f9..9d715716a3 100644
--- a/tomcat/src/main/java/org/apache/coyote/connector/Connector.java
+++ b/tomcat/src/main/java/org/apache/coyote/connector/Connector.java
@@ -1,13 +1,14 @@
package org.apache.coyote.connector;
-import org.apache.coyote.processor.Http11Processor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.ServerSocket;
import java.net.Socket;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.apache.coyote.processor.Http11Processor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class Connector implements Runnable {
@@ -15,15 +16,18 @@ public class Connector implements Runnable {
private static final int DEFAULT_PORT = 8080;
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.executorService = Executors.newFixedThreadPool(maxThreads);
this.serverSocket = createServerSocket(port, acceptCount);
this.stopped = false;
}
@@ -67,7 +71,7 @@ private void process(final Socket connection) {
return;
}
var processor = new Http11Processor(connection);
- new Thread(processor).start();
+ executorService.submit(() -> processor.run());
}
public void stop() {
diff --git a/tomcat/src/main/java/org/apache/coyote/connector/RequestReader.java b/tomcat/src/main/java/org/apache/coyote/connector/RequestReader.java
new file mode 100644
index 0000000000..7ade67b6a5
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/coyote/connector/RequestReader.java
@@ -0,0 +1,47 @@
+package org.apache.coyote.connector;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.catalina.request.HttpRequest;
+
+public class RequestReader {
+
+ private RequestReader() {
+ }
+
+ public static HttpRequest readRequest(InputStream inputStream) throws IOException {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ List headerLines = new ArrayList<>();
+
+ String contentLengthHeader = readHeader(bufferedReader, headerLines);
+ String bodyLine = readBody(bufferedReader, contentLengthHeader);
+ return new HttpRequest(headerLines, bodyLine);
+ }
+
+ private static String readHeader(BufferedReader bufferedReader, List headerLines) throws IOException {
+ String rawLine;
+ String contentLengthHeader = null;
+ while ((rawLine = bufferedReader.readLine()) != null && !rawLine.isEmpty()) {
+ headerLines.add(rawLine);
+ if (rawLine.startsWith("Content-Length")) {
+ contentLengthHeader = rawLine.split(": ")[1];
+ }
+ }
+ return contentLengthHeader;
+ }
+
+ private static String readBody(BufferedReader bufferedReader, String contentLengthHeader) throws IOException {
+ if (contentLengthHeader == null) {
+ return "";
+ }
+ int contentLength = Integer.parseInt(contentLengthHeader);
+ char[] buffer = new char[contentLength];
+ bufferedReader.read(buffer, 0, contentLength);
+ return new String(buffer);
+ }
+}
+
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/AbstractController.java b/tomcat/src/main/java/org/apache/coyote/controller/AbstractController.java
deleted file mode 100644
index 996689650a..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/controller/AbstractController.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.apache.coyote.controller;
-
-import org.apache.coyote.http.HttpMethod;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
-
-public abstract class AbstractController implements Controller {
-
- @Override
- public void service(HttpRequest request, HttpResponse response) {
- if (request.isMethod(HttpMethod.GET)) {
- doGet(request, response);
- return;
- }
- if (request.isMethod(HttpMethod.POST)) {
- doPost(request, response);
- return;
- }
- throw new IllegalArgumentException("HttpMethod not found");
- }
-
- protected void doPost(HttpRequest request, HttpResponse response) { /* NOOP */ }
-
- protected void doGet(HttpRequest request, HttpResponse response) { /* NOOP */ }
-}
-
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java b/tomcat/src/main/java/org/apache/coyote/controller/Controller.java
deleted file mode 100644
index d97ddb99bb..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/controller/Controller.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.apache.coyote.controller;
-
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
-
-public interface Controller {
-
- void service(HttpRequest request, HttpResponse response);
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/controller/LoginController.java
deleted file mode 100644
index 7e84cca85d..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/controller/LoginController.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.apache.coyote.controller;
-
-import com.techcourse.db.InMemoryUserRepository;
-import com.techcourse.model.User;
-import java.util.Optional;
-import org.apache.coyote.http.HeaderName;
-import org.apache.coyote.http.StatusCode;
-import org.apache.coyote.manager.SessionManager;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
-
-public class LoginController extends AbstractController {
-
- private final SessionManager sessionManager;
-
- public LoginController() {
- this.sessionManager = SessionManager.getInstance();
- }
-
- @Override
- protected void doPost(HttpRequest request, HttpResponse response) {
- String account = request.getBody("account");
- String password = request.getBody("password");
- Optional user = InMemoryUserRepository.findByAccount(account);
-
- if (user.isEmpty() || !user.get().checkPassword(password)) {
- response.setStatusCode(StatusCode.UNAUTHORIZED);
- response.setBody("/401.html");
- }
- if (user.isPresent() && user.get().checkPassword(password)) {
- response.setStatusCode(StatusCode.FOUND);
- response.setBody("/index.html");
-
- String sessionId = sessionManager.generateSession(user.get());
- response.addHeader(HeaderName.SET_COOKIE, "JSESSIONID=" + sessionId);
- }
- }
-
- @Override
- protected void doGet(HttpRequest request, HttpResponse response) {
- if (request.hasSession() && sessionManager.isSessionExist(request.getSessionId())) {
- response.setStatusCode(StatusCode.FOUND); //
- response.addHeader(HeaderName.LOCATION, "/index.html");
- }
- if (!request.hasSession() || !sessionManager.isSessionExist(request.getSessionId())) {
- response.setStatusCode(StatusCode.OK);
- response.setBody("/login.html");
- }
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/controller/StaticController.java b/tomcat/src/main/java/org/apache/coyote/controller/StaticController.java
deleted file mode 100644
index 8611504b89..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/controller/StaticController.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.apache.coyote.controller;
-
-import org.apache.coyote.http.StatusCode;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
-
-public class StaticController extends AbstractController {
-
- @Override
- protected void doGet(HttpRequest request, HttpResponse response) {
- response.setStatusCode(StatusCode.OK);
- response.setBody(request.getPath());
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/http/HeaderName.java b/tomcat/src/main/java/org/apache/coyote/http/HeaderName.java
deleted file mode 100644
index b29f1f2c8c..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/http/HeaderName.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.apache.coyote.http;
-
-import java.util.Arrays;
-
-public enum HeaderName {
- CONTENT_LENGTH("Content-Length"),
- COOKIE("Cookie"),
- CONTENT_TYPE("Content-Type"),
- LOCATION("Location"),
- SET_COOKIE("Set-Cookie"),
-
- ;
-
- private final String value;
-
- HeaderName(String value) {
- this.value = value;
- }
-
- public static HeaderName findByName(String name) {
- return Arrays.stream(values())
- .filter(headerName -> headerName.value.equals(name))
- .findFirst()
- .orElseThrow(() -> new IllegalArgumentException("HeaderName not found"));
- }
-
- public String getValue() {
- return value;
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Dispatcher.java b/tomcat/src/main/java/org/apache/coyote/http11/Dispatcher.java
deleted file mode 100644
index ee0807aef8..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/http11/Dispatcher.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.apache.coyote.http11;
-
-import java.util.Map;
-import org.apache.coyote.controller.Controller;
-import org.apache.coyote.controller.HomeController;
-import org.apache.coyote.controller.LoginController;
-import org.apache.coyote.controller.RegisterController;
-import org.apache.coyote.controller.StaticController;
-import org.apache.coyote.http.HeaderName;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.response.HttpResponse;
-
-public class Dispatcher {
-
- private final Map controllers;
- private final Controller staticController;
-
- public Dispatcher() {
- this.controllers = Map.of(
- "/login", new LoginController(),
- "/register", new RegisterController(),
- "/", new HomeController()
- );
- this.staticController = new StaticController();
- }
-
- public void run(HttpRequest httpRequest, HttpResponse httpResponse) {
- httpResponse.addHeader(HeaderName.CONTENT_TYPE, httpRequest.getContentType());
- httpResponse.addHeader(HeaderName.SET_COOKIE, httpRequest.getHttpCookie());
-
- if (httpRequest.isStaticRequest()) {
- staticController.service(httpRequest, httpResponse);
- }
- if (!httpRequest.isStaticRequest()) {
- Controller controller = controllers.get(httpRequest.getPath());
- controller.service(httpRequest, httpResponse);
- }
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/processor/ControllerMapper.java b/tomcat/src/main/java/org/apache/coyote/processor/ControllerMapper.java
new file mode 100644
index 0000000000..5312674743
--- /dev/null
+++ b/tomcat/src/main/java/org/apache/coyote/processor/ControllerMapper.java
@@ -0,0 +1,24 @@
+package org.apache.coyote.processor;
+
+import java.util.Map;
+import org.apache.catalina.controller.Controller;
+import org.apache.catalina.controller.HomeController;
+import org.apache.catalina.controller.LoginController;
+import org.apache.catalina.controller.RegisterController;
+
+public class ControllerMapper {
+
+ private final Map controllers;
+
+ public ControllerMapper() {
+ this.controllers = Map.of(
+ "/login", new LoginController(),
+ "/register", new RegisterController(),
+ "/", new HomeController()
+ );
+ }
+
+ public Controller getController(String path) {
+ return controllers.get(path);
+ }
+}
diff --git a/tomcat/src/main/java/org/apache/coyote/processor/Http11Processor.java b/tomcat/src/main/java/org/apache/coyote/processor/Http11Processor.java
index c7260d3a59..8b22a4463d 100644
--- a/tomcat/src/main/java/org/apache/coyote/processor/Http11Processor.java
+++ b/tomcat/src/main/java/org/apache/coyote/processor/Http11Processor.java
@@ -1,13 +1,14 @@
package org.apache.coyote.processor;
-import com.techcourse.exception.UncheckedServletException;
import java.io.IOException;
import java.net.Socket;
-import org.apache.coyote.Processor;
-import org.apache.coyote.http11.Dispatcher;
-import org.apache.coyote.request.HttpRequest;
-import org.apache.coyote.request.RequestReader;
-import org.apache.coyote.response.HttpResponse;
+import org.apache.catalina.ServletContainer;
+import org.apache.catalina.exception.UncheckedServletException;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.apache.coyote.connector.RequestReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,9 +17,11 @@ public class Http11Processor implements Runnable, Processor {
private static final Logger log = LoggerFactory.getLogger(Http11Processor.class);
private final Socket connection;
+ private final ServletContainer servletContainer;
public Http11Processor(final Socket connection) {
this.connection = connection;
+ this.servletContainer = new ServletContainer(new ControllerMapper());
}
@Override
@@ -35,8 +38,14 @@ public void process(final Socket connection) {
HttpRequest httpRequest = RequestReader.readRequest(inputStream);
HttpResponse httpResponse = new HttpResponse();
- Dispatcher dispatcher = new Dispatcher();
- dispatcher.run(httpRequest, httpResponse);
+ if (httpRequest.isStaticRequest()) {
+ httpResponse.addHeader(HeaderName.CONTENT_TYPE, httpRequest.getContentType());
+ httpResponse.setStatusCode(StatusCode.OK);
+ httpResponse.setBody(httpRequest.getPath(), httpRequest.getContentType());
+ }
+ if (!httpRequest.isStaticRequest()) {
+ servletContainer.run(httpRequest, httpResponse);
+ }
outputStream.write(httpResponse.getReponse().getBytes());
outputStream.flush();
diff --git a/tomcat/src/main/java/org/apache/coyote/Processor.java b/tomcat/src/main/java/org/apache/coyote/processor/Processor.java
similarity index 96%
rename from tomcat/src/main/java/org/apache/coyote/Processor.java
rename to tomcat/src/main/java/org/apache/coyote/processor/Processor.java
index 6604ab83de..6d8113ee09 100644
--- a/tomcat/src/main/java/org/apache/coyote/Processor.java
+++ b/tomcat/src/main/java/org/apache/coyote/processor/Processor.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.coyote;
+package org.apache.coyote.processor;
import java.net.Socket;
diff --git a/tomcat/src/main/java/org/apache/coyote/request/RequestBody.java b/tomcat/src/main/java/org/apache/coyote/request/RequestBody.java
deleted file mode 100644
index 75827379bd..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/request/RequestBody.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.apache.coyote.request;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class RequestBody {
-
- private final Map body;
-
- public RequestBody() {
- this.body = new HashMap<>();
- }
-
- public RequestBody(String bodyLine) {
- this.body = mapBody(bodyLine);
- }
-
- private Map mapBody(String bodyLine) {
- Map rawBody = new HashMap<>();
-
- String[] bodyElements = bodyLine.split("&");
- for (int i = 0; i < bodyElements.length; i++) {
- String[] info = bodyElements[i].split("=");
- rawBody.put(info[0], info[1]);
- }
- return rawBody;
- }
-
- public String get(String key) {
- return body.get(key);
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/request/RequestReader.java b/tomcat/src/main/java/org/apache/coyote/request/RequestReader.java
deleted file mode 100644
index 6925b67851..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/request/RequestReader.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.coyote.request;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-
-public class RequestReader {
-
- public static HttpRequest readRequest(InputStream inputStream) {
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
-
- List headerLines = new ArrayList<>();
- String rawLine;
- String contentLengthHeader = "";
- try {
- while ((rawLine = bufferedReader.readLine()) != null && !rawLine.isEmpty()) {
- headerLines.add(rawLine);
-
- if (rawLine.startsWith("Content-Length")) {
- contentLengthHeader = rawLine.split(": ")[1];
- }
- }
-
- String bodyLine = "";
- if (!contentLengthHeader.isEmpty()) {
- bodyLine = readBody(bufferedReader, contentLengthHeader);
- }
-
- return new HttpRequest(headerLines, bodyLine);
-
- } catch (IOException e) {
- throw new IllegalStateException("Error reading input stream", e);
- }
- }
-
- private static String readBody(BufferedReader bufferedReader, String contentLengthHeader) throws IOException {
- int contentLength = Integer.parseInt(contentLengthHeader);
- char[] buffer = new char[contentLength];
- bufferedReader.read(buffer, 0, contentLength); // 본문을 버퍼로 읽어들임
- return new String(buffer); // 읽은 버퍼를 문자열로 변환
- }
-}
diff --git a/tomcat/src/main/java/org/apache/coyote/response/StatusLine.java b/tomcat/src/main/java/org/apache/coyote/response/StatusLine.java
deleted file mode 100644
index 189b283e71..0000000000
--- a/tomcat/src/main/java/org/apache/coyote/response/StatusLine.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.apache.coyote.response;
-
-import org.apache.coyote.http.StatusCode;
-import org.apache.coyote.http11.ProtocolVersion;
-
-public class StatusLine {
-
- private final ProtocolVersion versionOfProtocol;
- private StatusCode statusCode;
-
- public StatusLine() {
- this.versionOfProtocol = ProtocolVersion.HTTP1_1;
- this.statusCode = StatusCode.OK;
- }
-
- public String getResponse() {
- StringBuilder response = new StringBuilder();
- response.append(versionOfProtocol.getValue())
- .append(" ")
- .append(statusCode.getCode())
- .append(" ")
- .append(statusCode.getMessage());
- return String.valueOf(response);
- }
-
- public void setStatusCode(StatusCode statusCode) {
- this.statusCode = statusCode;
- }
-}
diff --git a/tomcat/src/main/java/org/apache/catalina/startup/Tomcat.java b/tomcat/src/main/java/org/apache/coyote/startup/Tomcat.java
similarity index 94%
rename from tomcat/src/main/java/org/apache/catalina/startup/Tomcat.java
rename to tomcat/src/main/java/org/apache/coyote/startup/Tomcat.java
index 3027877bc6..508e3cc910 100644
--- a/tomcat/src/main/java/org/apache/catalina/startup/Tomcat.java
+++ b/tomcat/src/main/java/org/apache/coyote/startup/Tomcat.java
@@ -1,11 +1,10 @@
-package org.apache.catalina.startup;
+package org.apache.coyote.startup;
+import java.io.IOException;
import org.apache.coyote.connector.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-
public class Tomcat {
private static final Logger log = LoggerFactory.getLogger(Tomcat.class);
diff --git a/tomcat/src/test/java/org/apache/catalina/controller/AbstractControllerTest.java b/tomcat/src/test/java/org/apache/catalina/controller/AbstractControllerTest.java
new file mode 100644
index 0000000000..712280fd27
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/catalina/controller/AbstractControllerTest.java
@@ -0,0 +1,39 @@
+package org.apache.catalina.controller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.junit.jupiter.api.Test;
+
+class AbstractControllerTest {
+
+ @Test
+ void doGet() {
+ // given
+ AbstractController abstractController = new TestController();
+ HttpRequest request = new HttpRequest(List.of("GET / HTTP/1.1"), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ abstractController.service(request, response);
+
+ // then
+ assertThat(response.getReponse()).contains("Content-Length: 1");
+ }
+
+ @Test
+ void doPost() {
+ // given
+ AbstractController abstractController = new TestController();
+ HttpRequest request = new HttpRequest(List.of("POST / HTTP/1.1"), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ abstractController.service(request, response);
+
+ // then
+ assertThat(response.getReponse()).contains("Content-Length: 0");
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/catalina/controller/HomeControllerTest.java b/tomcat/src/test/java/org/apache/catalina/controller/HomeControllerTest.java
new file mode 100644
index 0000000000..9d6426c191
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/catalina/controller/HomeControllerTest.java
@@ -0,0 +1,29 @@
+package org.apache.catalina.controller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+
+import java.util.List;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.junit.jupiter.api.Test;
+
+class HomeControllerTest {
+
+ @Test
+ void doGet() {
+ // given
+ HomeController homeController = new HomeController();
+ HttpRequest request = new HttpRequest(List.of("GET / HTTP/1.1"), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ homeController.doGet(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("200 OK"),
+ () -> assertThat(response.getReponse()).contains("대시보드")
+ );
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/catalina/controller/LoginControllerTest.java b/tomcat/src/test/java/org/apache/catalina/controller/LoginControllerTest.java
new file mode 100644
index 0000000000..950cb015a0
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/catalina/controller/LoginControllerTest.java
@@ -0,0 +1,115 @@
+package org.apache.catalina.controller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+
+import com.techcourse.db.InMemoryUserRepository;
+import com.techcourse.model.User;
+import java.util.List;
+import org.apache.catalina.manager.SessionManager;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.apache.catalina.session.Session;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class LoginControllerTest {
+
+ private final SessionManager sessionManager;
+
+ public LoginControllerTest() {
+ this.sessionManager = SessionManager.getInstance();
+ }
+
+ @BeforeEach
+ void initializeDatabase() {
+ InMemoryUserRepository.reset();
+ }
+
+ @Test
+ void doPost_로그인성공() {
+ // given
+ LoginController loginController = new LoginController();
+ String account = "account";
+ String password = "password";
+ String email = "email";
+ InMemoryUserRepository.save(new User(account, password, email));
+
+ HttpRequest request = new HttpRequest(
+ List.of("POST / HTTP/1.1"),
+ "account=" + account + "&password=" + password + "&email=" + email
+ );
+ HttpResponse response = new HttpResponse();
+
+ // when
+ loginController.doPost(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("302 FOUND"),
+ () -> assertThat(response.getReponse()).contains("Location: /index.html")
+ );
+ }
+
+ @Test
+ void doPost_로그인실패() {
+ // given
+ LoginController loginController = new LoginController();
+ String account = "account";
+ String password = "password";
+ String email = "email";
+ HttpRequest request = new HttpRequest(
+ List.of("POST / HTTP/1.1"),
+ "account=" + account + "&password=" + password + "&email=" + email
+ );
+ HttpResponse response = new HttpResponse();
+
+ // when
+ loginController.doPost(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("302 FOUND"),
+ () -> assertThat(response.getReponse()).contains("Location: /401.html")
+ );
+ }
+
+ @Test
+ void doGet_로그인_안한_상태() {
+ // given
+ LoginController loginController = new LoginController();
+ HttpRequest request = new HttpRequest(List.of("GET / HTTP/1.1"), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ loginController.doGet(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("200 OK"),
+ () -> assertThat(response.getReponse()).contains("로그인")
+ );
+ }
+
+ @Test
+ void doGet_로그인_한_상태() {
+ // given
+ LoginController loginController = new LoginController();
+ Session session = new Session(new User("account", "password", "email"));
+ sessionManager.add(session);
+ HttpRequest request = new HttpRequest(List.of(
+ "GET / HTTP/1.1",
+ "Cookie: JSESSIONID=" + session.getId() + "; "
+ ), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ loginController.doGet(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("302 FOUND"),
+ () -> assertThat(response.getReponse()).contains("Location: /index.html")
+ );
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/catalina/controller/RegisterControllerTest.java b/tomcat/src/test/java/org/apache/catalina/controller/RegisterControllerTest.java
new file mode 100644
index 0000000000..86e72076aa
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/catalina/controller/RegisterControllerTest.java
@@ -0,0 +1,52 @@
+package org.apache.catalina.controller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+
+import java.util.List;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+import org.junit.jupiter.api.Test;
+
+class RegisterControllerTest {
+ @Test
+ void doPost() {
+ // given
+ RegisterController registerController = new RegisterController();
+ String account = "account";
+ String password = "password";
+ String email = "email";
+
+ HttpRequest request = new HttpRequest(
+ List.of("POST / HTTP/1.1"),
+ "account=" + account + "&password=" + password + "&email=" + email
+ );
+ HttpResponse response = new HttpResponse();
+
+ // when
+ registerController.doPost(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("302 FOUND"),
+ () -> assertThat(response.getReponse()).contains("Location: /index.html")
+ );
+ }
+
+ @Test
+ void doGet() {
+ // given
+ RegisterController registerController = new RegisterController();
+ HttpRequest request = new HttpRequest(List.of("GET / HTTP/1.1"), "");
+ HttpResponse response = new HttpResponse();
+
+ // when
+ registerController.doGet(request, response);
+
+ // then
+ assertAll(
+ () -> assertThat(response.getReponse()).contains("200 OK"),
+ () -> assertThat(response.getReponse()).contains("회원가입")
+ );
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/catalina/controller/TestController.java b/tomcat/src/test/java/org/apache/catalina/controller/TestController.java
new file mode 100644
index 0000000000..dea486a4d2
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/catalina/controller/TestController.java
@@ -0,0 +1,17 @@
+package org.apache.catalina.controller;
+
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.request.HttpRequest;
+import org.apache.catalina.response.HttpResponse;
+
+public class TestController extends AbstractController {
+ @Override
+ protected void doPost(HttpRequest request, HttpResponse response) {
+ response.addHeader(HeaderName.CONTENT_LENGTH, "0");
+ }
+
+ @Override
+ protected void doGet(HttpRequest request, HttpResponse response) {
+ response.addHeader(HeaderName.CONTENT_LENGTH, "1");
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/coyote/coockie/HttpCookieTest.java b/tomcat/src/test/java/org/apache/coyote/coockie/HttpCookieTest.java
index 101a9a1f94..9ad599f31b 100644
--- a/tomcat/src/test/java/org/apache/coyote/coockie/HttpCookieTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/coockie/HttpCookieTest.java
@@ -1,6 +1,8 @@
package org.apache.coyote.coockie;
import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.catalina.coockie.HttpCookie;
import org.junit.jupiter.api.Test;
class HttpCookieTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/processor/ControllerMapperTest.java b/tomcat/src/test/java/org/apache/coyote/processor/ControllerMapperTest.java
new file mode 100644
index 0000000000..50dad28f14
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/coyote/processor/ControllerMapperTest.java
@@ -0,0 +1,22 @@
+package org.apache.coyote.processor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.catalina.controller.Controller;
+import org.apache.catalina.controller.HomeController;
+import org.junit.jupiter.api.Test;
+
+class ControllerMapperTest {
+
+ @Test
+ void getController() {
+ // given
+ ControllerMapper controllerMapper = new ControllerMapper();
+
+ // when
+ Controller controller = controllerMapper.getController("/");
+
+ // then
+ assertThat(controller.getClass()).isEqualTo(HomeController.class);
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/coyote/request/QueuryParamTest.java b/tomcat/src/test/java/org/apache/coyote/request/QueuryParamTest.java
deleted file mode 100644
index 835a948993..0000000000
--- a/tomcat/src/test/java/org/apache/coyote/request/QueuryParamTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.apache.coyote.request;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
-
-class QueuryParamTest {
-
- @Test
- void hasQueryParam() {
- QueuryParam queuryParam = new QueuryParam("GET /index.html?name=kirby&part=backend HTTP/1.1");
- assertThat(queuryParam.hasQueryParam()).isTrue();
- }
-
- @Test
- void getQueryParam() {
- QueuryParam queuryParam = new QueuryParam("GET /index.html?name=kirby&part=backend HTTP/1.1");
- assertThat(queuryParam.getQueryParam("name")).isEqualTo("kirby");
- }
-}
diff --git a/tomcat/src/test/java/org/apache/coyote/request/QueuyParamTest.java b/tomcat/src/test/java/org/apache/coyote/request/QueuyParamTest.java
new file mode 100644
index 0000000000..3b0447e52e
--- /dev/null
+++ b/tomcat/src/test/java/org/apache/coyote/request/QueuyParamTest.java
@@ -0,0 +1,21 @@
+package org.apache.coyote.request;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.catalina.request.QueuyParam;
+import org.junit.jupiter.api.Test;
+
+class QueuyParamTest {
+
+ @Test
+ void hasQueryParam() {
+ QueuyParam queuyParam = new QueuyParam("GET /index.html?name=kirby&part=backend HTTP/1.1");
+ assertThat(queuyParam.hasQueryParam()).isTrue();
+ }
+
+ @Test
+ void getQueryParam() {
+ QueuyParam queuyParam = new QueuyParam("GET /index.html?name=kirby&part=backend HTTP/1.1");
+ assertThat(queuyParam.getQueryParam("name")).isEqualTo("kirby");
+ }
+}
diff --git a/tomcat/src/test/java/org/apache/coyote/request/RequestBodyTest.java b/tomcat/src/test/java/org/apache/coyote/request/RequestBodyTest.java
index 756c4c534e..5446928d66 100644
--- a/tomcat/src/test/java/org/apache/coyote/request/RequestBodyTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/request/RequestBodyTest.java
@@ -1,8 +1,8 @@
package org.apache.coyote.request;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.*;
+import org.apache.catalina.request.RequestBody;
import org.junit.jupiter.api.Test;
class RequestBodyTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/request/RequestHeaderTest.java b/tomcat/src/test/java/org/apache/coyote/request/RequestHeaderTest.java
index 1f982c12bf..d725afb904 100644
--- a/tomcat/src/test/java/org/apache/coyote/request/RequestHeaderTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/request/RequestHeaderTest.java
@@ -3,6 +3,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
+import org.apache.catalina.request.RequestHeader;
import org.junit.jupiter.api.Test;
class RequestHeaderTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/request/RequestLineTest.java b/tomcat/src/test/java/org/apache/coyote/request/RequestLineTest.java
index fea726836e..819c2f4e58 100644
--- a/tomcat/src/test/java/org/apache/coyote/request/RequestLineTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/request/RequestLineTest.java
@@ -2,7 +2,8 @@
import static org.assertj.core.api.Assertions.assertThat;
-import org.apache.coyote.http.HttpMethod;
+import org.apache.catalina.http.HttpMethod;
+import org.apache.catalina.request.RequestLine;
import org.junit.jupiter.api.Test;
class RequestLineTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/response/HttpResponseTest.java b/tomcat/src/test/java/org/apache/coyote/response/HttpResponseTest.java
index 32a627ed7e..b768f3c6d2 100644
--- a/tomcat/src/test/java/org/apache/coyote/response/HttpResponseTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/response/HttpResponseTest.java
@@ -2,8 +2,9 @@
import static org.assertj.core.api.Assertions.assertThat;
-import org.apache.coyote.http.HeaderName;
-import org.apache.coyote.http.StatusCode;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.http.StatusCode;
+import org.apache.catalina.response.HttpResponse;
import org.junit.jupiter.api.Test;
class HttpResponseTest {
@@ -43,5 +44,6 @@ class HttpResponseTest {
// then
assertThat(response.getReponse()).contains("대시보드");
+ assertThat(response.getReponse()).contains("Content-Length: 5670");
}
}
diff --git a/tomcat/src/test/java/org/apache/coyote/response/ResponseBodyTest.java b/tomcat/src/test/java/org/apache/coyote/response/ResponseBodyTest.java
index 9f16c17bd0..5eef1c223b 100644
--- a/tomcat/src/test/java/org/apache/coyote/response/ResponseBodyTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/response/ResponseBodyTest.java
@@ -2,6 +2,7 @@
import static org.assertj.core.api.Assertions.assertThat;
+import org.apache.catalina.response.ResponseBody;
import org.junit.jupiter.api.Test;
class ResponseBodyTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/response/ResponseHeaderTest.java b/tomcat/src/test/java/org/apache/coyote/response/ResponseHeaderTest.java
index 3f575452d4..d1688ac1f7 100644
--- a/tomcat/src/test/java/org/apache/coyote/response/ResponseHeaderTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/response/ResponseHeaderTest.java
@@ -2,7 +2,8 @@
import static org.assertj.core.api.Assertions.assertThat;
-import org.apache.coyote.http.HeaderName;
+import org.apache.catalina.http.HeaderName;
+import org.apache.catalina.response.ResponseHeader;
import org.junit.jupiter.api.Test;
class ResponseHeaderTest {
diff --git a/tomcat/src/test/java/org/apache/coyote/response/StatusLineTest.java b/tomcat/src/test/java/org/apache/coyote/response/StatusLineTest.java
index cd06411390..cd55a078de 100644
--- a/tomcat/src/test/java/org/apache/coyote/response/StatusLineTest.java
+++ b/tomcat/src/test/java/org/apache/coyote/response/StatusLineTest.java
@@ -2,6 +2,7 @@
import static org.assertj.core.api.Assertions.assertThat;
+import org.apache.catalina.response.StatusLine;
import org.junit.jupiter.api.Test;
class StatusLineTest {