From 109ed4365f273bc71aef924ff26583bebbe45d98 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Fri, 8 Sep 2023 21:31:35 +0900 Subject: [PATCH 01/15] =?UTF-8?q?refactor:=20HttpRequest=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=83=81=EC=88=98=ED=99=94,?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=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 --- .../org/apache/coyote/http11/HttpRequest.java | 28 ++++++------- .../apache/coyote/http11/HttpRequestBody.java | 13 ++++-- .../coyote/http11/HttpRequestFirstLine.java | 38 ------------------ .../coyote/http11/HttpRequestHeader.java | 33 ++++++++------- .../apache/coyote/http11/HttpRequestLine.java | 40 +++++++++++++++++++ .../org/apache/coyote/http11/HttpVersion.java | 16 ++++++++ .../coyote/http11/{HttpPath.java => Uri.java} | 10 ++--- 7 files changed, 102 insertions(+), 76 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestFirstLine.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java rename tomcat/src/main/java/org/apache/coyote/http11/{HttpPath.java => Uri.java} (75%) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java index 827c951dbd..2fba3a8a44 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java @@ -5,41 +5,41 @@ public class HttpRequest { - private final HttpRequestFirstLine firstLine; + private final HttpRequestLine requestLine; private final HttpRequestHeader headers; private final HttpRequestBody body; public static HttpRequest from(final BufferedReader bufferedReader) throws IOException { final String firstLine = bufferedReader.readLine(); - final HttpRequestFirstLine httpRequestFirstLine = HttpRequestFirstLine.from(firstLine); + final HttpRequestLine httpRequestLine = HttpRequestLine.from(firstLine); final HttpRequestHeader headers = HttpRequestHeader.from(bufferedReader); final HttpRequestBody httpRequestBody = HttpRequestBody.of(bufferedReader, headers); - return new HttpRequest(httpRequestFirstLine, headers, httpRequestBody); + return new HttpRequest(httpRequestLine, headers, httpRequestBody); } private HttpRequest( - final HttpRequestFirstLine firstLine, + final HttpRequestLine requestLine, final HttpRequestHeader headers, final HttpRequestBody body ) { - this.firstLine = firstLine; + this.requestLine = requestLine; this.headers = headers; this.body = body; } public boolean isLogin() { - final HttpPath httpPath = firstLine.getHttpPath(); - return httpPath.isLogin(); + final Uri uri = requestLine.getUri(); + return uri.isLogin(); } public boolean isRegister() { - final HttpPath httpPath = firstLine.getHttpPath(); - return httpPath.isRegister(); + final Uri uri = requestLine.getUri(); + return uri.isRegister(); } public boolean isCorrectMethod(final HttpMethod method) { - return firstLine.getHttpMethod() == method; + return requestLine.getHttpMethod() == method; } public boolean hasJSessionId() { @@ -50,12 +50,12 @@ public String getJSessionId() { return headers.getJSessionId(); } - public HttpRequestFirstLine getFirstLine() { - return firstLine; + public HttpRequestLine getRequestLine() { + return requestLine; } - public HttpPath getPath() { - return firstLine.getHttpPath(); + public Uri getPath() { + return requestLine.getUri(); } public HttpRequestBody getBody() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java index 1f346ac0e2..b2e8feeeee 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java @@ -8,15 +8,20 @@ public class HttpRequestBody { + private static final String EMPTY_STRING = ""; + private static final String CONTENT_LENGTH = "Content-Length"; + private static final String USER_INFO_DELIMITER = "&"; + private static final String USER_INFO_SEPARATOR = "="; + private final String body; public static HttpRequestBody of( final BufferedReader bufferedReader, final HttpRequestHeader headers ) throws IOException { - final String requestContentLength = headers.get("Content-Length"); + final String requestContentLength = headers.get(CONTENT_LENGTH); if (requestContentLength == null) { - return new HttpRequestBody(""); + return new HttpRequestBody(EMPTY_STRING); } final int contentLength = Integer.parseInt(requestContentLength); final char[] buffer = new char[contentLength]; @@ -29,8 +34,8 @@ private HttpRequestBody(final String body) { } public Map parseUserInfos() { - return Arrays.stream(body.split("&")) - .map(info -> Arrays.asList(info.split("="))) + return Arrays.stream(body.split(USER_INFO_DELIMITER)) + .map(info -> Arrays.asList(info.split(USER_INFO_SEPARATOR))) .collect(Collectors.toMap(infos -> infos.get(0), infos -> infos.get(1), (a, b) -> b)); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestFirstLine.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestFirstLine.java deleted file mode 100644 index 9d97f06e54..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestFirstLine.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.apache.coyote.http11; - -import java.util.Arrays; -import java.util.List; - -public class HttpRequestFirstLine { - - private final HttpMethod httpMethod; - private final HttpPath httpPath; - private final String protocolVersion; - - public static HttpRequestFirstLine from(final String firstLine) { - final List firstLines = Arrays.asList(firstLine.split(" ")); - return new HttpRequestFirstLine(firstLines.get(0), firstLines.get(1), firstLines.get(2)); - } - - public HttpRequestFirstLine( - final String httpMethod, - final String uri, - final String protocolVersion - ) { - this.httpMethod = HttpMethod.valueOf(httpMethod); - this.httpPath = HttpPath.from(uri); - this.protocolVersion = protocolVersion; - } - - public HttpMethod getHttpMethod() { - return httpMethod; - } - - public HttpPath getHttpPath() { - return httpPath; - } - - public String getProtocolVersion() { - return protocolVersion; - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java index 4facf5e523..9ecf87f9d2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java @@ -8,6 +8,12 @@ public class HttpRequestHeader { + private static final String HEADER_SEPARATOR = ": "; + private static final String COOKIE_DELIMITER = "; "; + private static final String COOKIE_SEPARATOR = "="; + private static final String COOKIE = "Cookie"; + private static final String JSESSIONID = "JSESSIONID"; + private final Map headers; public static HttpRequestHeader from(final BufferedReader bufferedReader) throws IOException { @@ -15,7 +21,7 @@ public static HttpRequestHeader from(final BufferedReader bufferedReader) throws String line = bufferedReader.readLine(); while (!"".equals(line)) { - final String[] header = line.split(": "); + final String[] header = line.split(HEADER_SEPARATOR); headers.put(header[0], header[1]); line = bufferedReader.readLine(); @@ -29,26 +35,23 @@ private HttpRequestHeader(final Map headers) { } public boolean hasJSessionId() { - final String cookie = headers.get("Cookie"); + final String cookie = headers.get(COOKIE); if (cookie != null) { - return Arrays.stream(cookie.split("; ")) - .map(it -> it.split("=")) - .anyMatch(it -> it[0].equals("JSESSIONID")); + return Arrays.stream(cookie.split(COOKIE_DELIMITER)) + .map(it -> it.split(COOKIE_SEPARATOR)) + .anyMatch(it -> it[0].equals(JSESSIONID)); } return false; } public String getJSessionId() { - final String cookie = headers.get("Cookie"); - if (cookie != null) { - return Arrays.stream(cookie.split("; ")) - .map(s -> s.split("=")) - .filter(word -> word[0].equals("JSESSIONID")) - .findAny() - .map(word -> word[1]) - .orElse(null); - } - return null; + final String cookie = headers.get(COOKIE); + return Arrays.stream(cookie.split(COOKIE_DELIMITER)) + .map(s -> s.split(COOKIE_SEPARATOR)) + .filter(word -> word[0].equals(JSESSIONID)) + .findAny() + .map(word -> word[1]) + .orElse(null); } public String get(final String key) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java new file mode 100644 index 0000000000..3b7e4b9d70 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java @@ -0,0 +1,40 @@ +package org.apache.coyote.http11; + +import java.util.Arrays; +import java.util.List; + +public class HttpRequestLine { + + private static final String SEPARATOR = " "; + + private final HttpMethod httpMethod; + private final Uri uri; + private final HttpVersion httpVersion; + + public static HttpRequestLine from(final String requestLine) { + final List requestLineInfos = Arrays.asList(requestLine.split(SEPARATOR)); + return new HttpRequestLine(requestLineInfos.get(0), requestLineInfos.get(1), requestLineInfos.get(2)); + } + + public HttpRequestLine( + final String httpMethod, + final String uri, + final String httpVersion + ) { + this.httpMethod = HttpMethod.valueOf(httpMethod); + this.uri = Uri.from(uri); + this.httpVersion = HttpVersion.valueOf(httpVersion); + } + + public HttpMethod getHttpMethod() { + return httpMethod; + } + + public Uri getUri() { + return uri; + } + + public HttpVersion getHttpVersion() { + return httpVersion; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java new file mode 100644 index 0000000000..0a70702b24 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java @@ -0,0 +1,16 @@ +package org.apache.coyote.http11; + +public enum HttpVersion { + + HTTP10("HTTP/1.0"), + HTTP11("HTTP/1.1"), + HTTP20("HTTP/2.0"), + HTTP30("HTTP/3.0"), + ; + + private final String value; + + HttpVersion(final String value) { + this.value = value; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpPath.java b/tomcat/src/main/java/org/apache/coyote/http11/Uri.java similarity index 75% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpPath.java rename to tomcat/src/main/java/org/apache/coyote/http11/Uri.java index 1097e920d4..124c0a3021 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpPath.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Uri.java @@ -1,21 +1,21 @@ package org.apache.coyote.http11; -public class HttpPath { +public class Uri { private final String path; private final QueryString queryString; - public static HttpPath from(final String uri) { + public static Uri from(final String uri) { if (uri.contains("?")) { final int index = uri.indexOf("?"); final String path = uri.substring(0, index); final String queryString = uri.substring(index + 1); - return new HttpPath(path, queryString); + return new Uri(path, queryString); } - return new HttpPath(uri, ""); + return new Uri(uri, ""); } - private HttpPath(final String path, final String queryString) { + private Uri(final String path, final String queryString) { this.path = path; this.queryString = QueryString.from(queryString); } From bc524587f296c4e004c74e811a6ced2442b7925a Mon Sep 17 00:00:00 2001 From: jeomxon Date: Sun, 10 Sep 2023 21:23:33 +0900 Subject: [PATCH 02/15] =?UTF-8?q?refactor:=20HttpResponse=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=97=AD=ED=95=A0=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20Controller=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/catalina/Manager.java | 2 +- .../apache/coyote/http11/Http11Processor.java | 20 ++-- .../coyote/http11/HttpRequestHandler.java | 80 ------------- .../apache/coyote/http11/HttpResponse.java | 97 --------------- .../coyote/http11/HttpResponseEntity.java | 49 -------- .../org/apache/coyote/http11/HttpVersion.java | 13 ++ .../coyote/http11/{ => auth}/HttpCookie.java | 2 +- .../coyote/http11/{ => auth}/Session.java | 2 +- .../http11/{ => auth}/SessionManager.java | 2 +- .../http11/controller/AbstractController.java | 24 ++++ .../coyote/http11/controller/Controller.java | 9 ++ .../http11/controller/LoginController.java | 63 ++++++++++ .../http11/controller/PageController.java | 14 +++ .../http11/controller/RegisterController.java | 35 ++++++ .../http11/controller/RequestMapping.java | 24 ++++ .../http11/controller/RootController.java | 17 +++ .../http11/{ => request}/HttpMethod.java | 2 +- .../http11/{ => request}/HttpRequest.java | 24 +--- .../http11/{ => request}/HttpRequestBody.java | 2 +- .../{ => request}/HttpRequestHeader.java | 2 +- .../http11/{ => request}/HttpRequestLine.java | 9 +- .../http11/{ => request}/QueryString.java | 2 +- .../coyote/http11/{ => request}/Uri.java | 10 +- .../http11/{ => response}/ContentType.java | 2 +- .../coyote/http11/response/HttpResponse.java | 112 ++++++++++++++++++ .../http11/response/HttpResponseHeader.java | 27 +++++ .../http11/{ => response}/HttpStatus.java | 2 +- .../http11/response/HttpStatusLine.java | 26 ++++ 28 files changed, 396 insertions(+), 277 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHandler.java delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/HttpResponseEntity.java rename tomcat/src/main/java/org/apache/coyote/http11/{ => auth}/HttpCookie.java (95%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => auth}/Session.java (94%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => auth}/SessionManager.java (93%) 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 create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/PageController.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/RootController.java rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/HttpMethod.java (56%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/HttpRequest.java (70%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/HttpRequestBody.java (97%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/HttpRequestHeader.java (97%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/HttpRequestLine.java (83%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/QueryString.java (95%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => request}/Uri.java (79%) rename tomcat/src/main/java/org/apache/coyote/http11/{ => response}/ContentType.java (94%) 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/HttpResponseHeader.java rename tomcat/src/main/java/org/apache/coyote/http11/{ => response}/HttpStatus.java (84%) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusLine.java diff --git a/tomcat/src/main/java/org/apache/catalina/Manager.java b/tomcat/src/main/java/org/apache/catalina/Manager.java index 3965f45765..64969003a4 100644 --- a/tomcat/src/main/java/org/apache/catalina/Manager.java +++ b/tomcat/src/main/java/org/apache/catalina/Manager.java @@ -1,6 +1,6 @@ package org.apache.catalina; -import org.apache.coyote.http11.Session; +import org.apache.coyote.http11.auth.Session; /** * A Manager manages the pool of Sessions that are associated with a particular Container. Different Manager 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 3e150c214a..6c43260013 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -1,16 +1,20 @@ package org.apache.coyote.http11; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; -import nextstep.jwp.exception.UncheckedServletException; import org.apache.coyote.Processor; +import org.apache.coyote.http11.auth.SessionManager; +import org.apache.coyote.http11.controller.Controller; +import org.apache.coyote.http11.controller.RequestMapping; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Http11Processor implements Runnable, Processor { + public static final SessionManager SESSION_MANAGER = new SessionManager(); private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); private final Socket connection; @@ -33,13 +37,15 @@ public void process(final Socket connection) { final BufferedReader bufferedReader = new BufferedReader(inputStreamReader) ) { final HttpRequest request = HttpRequest.from(bufferedReader); - final HttpRequestHandler requestHandler = new HttpRequestHandler(request); - final HttpResponseEntity responseEntity = requestHandler.handle(); - final String response = HttpResponse.getResponse(responseEntity); + final HttpResponse response = new HttpResponse(); - outputStream.write(response.getBytes()); + final RequestMapping requestMapping = new RequestMapping(); + final Controller controller = requestMapping.getController(request); + controller.service(request, response); + + outputStream.write(response.get().getBytes()); outputStream.flush(); - } catch (IOException | UncheckedServletException e) { + } catch (Exception e) { log.error(e.getMessage(), e); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHandler.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHandler.java deleted file mode 100644 index d0ad0f54c1..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.coyote.http11; - -import java.util.Map; -import java.util.UUID; -import nextstep.jwp.db.InMemoryUserRepository; -import nextstep.jwp.model.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HttpRequestHandler { - - private static final String MAIN_PAGE = "/index.html"; - private static final String LOGIN_PAGE = "/login.html"; - private static final String REGISTER_PAGE = "/register.html"; - private static final String UNAUTHORIZED_PAGE = "/401.html"; - private static final Logger log = LoggerFactory.getLogger(HttpRequestHandler.class); - private static final SessionManager SESSION_MANAGER = new SessionManager(); - - private final HttpRequest httpRequest; - - public HttpRequestHandler(final HttpRequest httpRequest) { - this.httpRequest = httpRequest; - } - - public HttpResponseEntity handle() { - final HttpRequestBody requestBody = httpRequest.getBody(); - - if (httpRequest.isLogin()) { - if (httpRequest.isCorrectMethod(HttpMethod.GET)) { - if (httpRequest.hasJSessionId()) { - final Session session = SESSION_MANAGER.findSession(httpRequest.getJSessionId()); - final User user = (User) session.getAttribute("user"); - return new HttpResponseEntity(HttpStatus.FOUND, MAIN_PAGE, true); - } - return new HttpResponseEntity(HttpStatus.OK, LOGIN_PAGE); - } - return login(requestBody); - } - - if (httpRequest.isRegister()) { - if (httpRequest.isCorrectMethod(HttpMethod.GET)) { - return new HttpResponseEntity(HttpStatus.OK, REGISTER_PAGE); - } - - final Map userInfos = requestBody.parseUserInfos(); - if (httpRequest.isCorrectMethod(HttpMethod.POST) && - InMemoryUserRepository.isNonExistentByAccount(userInfos.get("account"))) { - return register(userInfos); - } - } - return new HttpResponseEntity(HttpStatus.OK, httpRequest.getPath().getPath()); - } - - private HttpResponseEntity login(final HttpRequestBody requestBody) { - final Map userInfos = requestBody.parseUserInfos(); - final String account = userInfos.get("account"); - final String password = userInfos.get("password"); - final User user = InMemoryUserRepository.findByAccount(account) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 계정입니다.")); - - if (user.checkPassword(password)) { - final SessionManager sessionManager = new SessionManager(); - final Session session = new Session(UUID.randomUUID().toString()); - session.setAttribute("user", user); - sessionManager.add(session); - - log.info("로그인 성공! 아이디: {}", account); - final HttpResponseEntity responseEntity = new HttpResponseEntity(HttpStatus.FOUND, MAIN_PAGE, true); - responseEntity.addCookie(HttpCookie.ofJSessionId(session.getId())); - return responseEntity; - } - return new HttpResponseEntity(HttpStatus.FOUND, UNAUTHORIZED_PAGE, true); - } - - private HttpResponseEntity register(final Map userInfos) { - final User user = new User(userInfos.get("account"), userInfos.get("password"), userInfos.get("email")); - InMemoryUserRepository.save(user); - return new HttpResponseEntity(HttpStatus.FOUND, MAIN_PAGE, true); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java deleted file mode 100644 index 553fe7459c..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponse.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.apache.coyote.http11; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Files; - -public class HttpResponse { - - private static final String CHARSET_UTF_8 = ";charset=utf-8"; - private static final String BLANK = " "; - - private HttpResponse() { - } - - public static String getResponse(final HttpResponseEntity responseEntity) throws IOException { - final String contentType = ContentType.getByPath(responseEntity.getPath()) + CHARSET_UTF_8; - if (responseEntity.getPath().equals("/")) { - return makeResponse(contentType, responseEntity, "Hello world!"); - } - if (responseEntity.isRedirect()) { - if (responseEntity.hasCookie()) { - return makeRedirectResponseWithCookie(responseEntity, responseEntity.getHttpCookie()); - } - return makeRedirectResponse(responseEntity); - } - - final URL resource = HttpResponse.class.getClassLoader().getResource("static" + responseEntity.getPath()); - final String responseBody = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); - return makeResponse(contentType, responseEntity, responseBody); - } - - private static String makeResponse( - final String contentType, - final HttpResponseEntity responseEntity, - final String body - ) { - if (responseEntity.hasCookie()) { - return makeGeneralResponseWithCookie(contentType, responseEntity, body, responseEntity.getHttpCookie()); - } - return makeGeneralResponse(contentType, responseEntity, body); - } - - private static String makeRedirectResponse(final HttpResponseEntity responseEntity) { - final HttpStatus status = responseEntity.getHttpStatus(); - return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Location: " + responseEntity.getPath() + BLANK, - "" - ); - } - - private static String makeRedirectResponseWithCookie( - final HttpResponseEntity responseEntity, - final HttpCookie cookie - ) { - final HttpStatus status = responseEntity.getHttpStatus(); - return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.getValues() + BLANK, - "Location: " + responseEntity.getPath() + BLANK, - "" - ); - } - - private static String makeGeneralResponseWithCookie( - final String contentType, - final HttpResponseEntity responseEntity, - final String body, - final HttpCookie cookie - ) { - final HttpStatus status = responseEntity.getHttpStatus(); - return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.getValues() + BLANK, - "Content-Type: " + contentType + BLANK, - "Content-Length: " + body.getBytes().length + BLANK, - "", - body - ); - } - - private static String makeGeneralResponse( - final String contentType, - final HttpResponseEntity responseEntity, - final String body - ) { - final HttpStatus status = responseEntity.getHttpStatus(); - return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Content-Type: " + contentType + BLANK, - "Content-Length: " + body.getBytes().length + BLANK, - "", - body - ); - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseEntity.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseEntity.java deleted file mode 100644 index 40b6b4cb7e..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpResponseEntity.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.apache.coyote.http11; - -import java.util.HashMap; - -public class HttpResponseEntity { - - private final HttpStatus httpStatus; - private final String path; - private HttpCookie httpCookie; - private boolean isRedirect; - - public HttpResponseEntity(final HttpStatus httpStatus, final String path) { - this.httpStatus = httpStatus; - this.path = path; - this.httpCookie = new HttpCookie(new HashMap<>()); - this.isRedirect = false; - } - - public HttpResponseEntity(final HttpStatus httpStatus, final String path, final boolean isRedirect) { - this.httpStatus = httpStatus; - this.path = path; - this.httpCookie = new HttpCookie(new HashMap<>()); - this.isRedirect = isRedirect; - } - - public boolean isRedirect() { - return isRedirect; - } - - public boolean hasCookie() { - return httpCookie.isNotEmpty(); - } - - public void addCookie(final HttpCookie httpCookie) { - this.httpCookie = httpCookie; - } - - public HttpStatus getHttpStatus() { - return httpStatus; - } - - public String getPath() { - return path; - } - - public HttpCookie getHttpCookie() { - return httpCookie; - } -} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java index 0a70702b24..68db06e23a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpVersion.java @@ -1,5 +1,7 @@ package org.apache.coyote.http11; +import java.util.Arrays; + public enum HttpVersion { HTTP10("HTTP/1.0"), @@ -13,4 +15,15 @@ public enum HttpVersion { HttpVersion(final String value) { this.value = value; } + + public static HttpVersion findVersion(final String value) { + return Arrays.stream(values()) + .filter(it -> it.value.equals(value)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("해당하는 http버전이 존재하지 않습니다.")); + } + + public String getValue() { + return value; + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java b/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java similarity index 95% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java rename to tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java index 898209c241..44829113e1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.auth; import java.util.HashMap; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java similarity index 94% rename from tomcat/src/main/java/org/apache/coyote/http11/Session.java rename to tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java index 68dc27b207..388f43c430 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.auth; import java.util.HashMap; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java similarity index 93% rename from tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java rename to tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java index e403af0bcb..b42db19ec1 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/SessionManager.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.auth; import java.util.HashMap; import java.util.Map; 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..e160de79c3 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/AbstractController.java @@ -0,0 +1,24 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpMethod; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; + +public abstract class AbstractController implements Controller { + + @Override + public void service(final HttpRequest request, final HttpResponse response) throws Exception { + if (request.matchesMethod(HttpMethod.GET)) { + doGet(request, response); + } + if (request.matchesMethod(HttpMethod.POST)) { + doPost(request, response); + } + } + + protected void doPost(final HttpRequest request, final HttpResponse response) throws Exception { + } + + protected void doGet(final HttpRequest request, final 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..c0a0c507a4 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/Controller.java @@ -0,0 +1,9 @@ +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/controller/LoginController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java new file mode 100644 index 0000000000..0cc0179706 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/LoginController.java @@ -0,0 +1,63 @@ +package org.apache.coyote.http11.controller; + +import static org.apache.coyote.http11.Http11Processor.SESSION_MANAGER; + +import java.util.Map; +import java.util.UUID; +import nextstep.jwp.db.InMemoryUserRepository; +import nextstep.jwp.model.User; +import org.apache.coyote.http11.auth.HttpCookie; +import org.apache.coyote.http11.auth.Session; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoginController extends AbstractController { + + private static final String MAIN_PAGE = "/index.html"; + private static final String LOGIN_PAGE = "/login.html"; + private static final String UNAUTHORIZED_PAGE = "/401.html"; + + private static final Logger log = LoggerFactory.getLogger(LoginController.class); + + @Override + protected void doPost(final HttpRequest request, final HttpResponse response) { + final Map userInfos = request.getBody().parseUserInfos(); + final String account = userInfos.get("account"); + final String password = userInfos.get("password"); + final User user = InMemoryUserRepository.findByAccount(account) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 계정입니다.")); + + if (user.checkPassword(password)) { + final Session session = new Session(UUID.randomUUID().toString()); + session.setAttribute("user", user); + SESSION_MANAGER.add(session); + + log.info("로그인 성공! 아이디: {}", account); + response.setHttpStatus(HttpStatus.FOUND); + response.setPath(MAIN_PAGE); + response.setRedirect(); + response.addCookie(HttpCookie.ofJSessionId(session.getId())); + return; + } + response.setHttpStatus(HttpStatus.FOUND); + response.setPath(UNAUTHORIZED_PAGE); + response.setRedirect(); + } + + @Override + protected void doGet(final HttpRequest request, final HttpResponse response) { + if (request.hasJSessionId()) { + final Session session = SESSION_MANAGER.findSession(request.getJSessionId()); + final User user = (User) session.getAttribute("user"); + response.setHttpStatus(HttpStatus.FOUND); + response.setPath(MAIN_PAGE); + response.setRedirect(); + return; + } + response.setHttpStatus(HttpStatus.OK); + response.setPath(LOGIN_PAGE); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/PageController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/PageController.java new file mode 100644 index 0000000000..8f227d8f5d --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/PageController.java @@ -0,0 +1,14 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; + +public class PageController extends AbstractController { + + @Override + protected void doGet(final HttpRequest request, final HttpResponse response) { + response.setHttpStatus(HttpStatus.OK); + response.setPath(request.getUri().getPath()); + } +} 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..bfa140ffea --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java @@ -0,0 +1,35 @@ +package org.apache.coyote.http11.controller; + +import java.util.Map; +import nextstep.jwp.db.InMemoryUserRepository; +import nextstep.jwp.model.User; +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; + +public class RegisterController extends AbstractController { + + private static final String MAIN_PAGE = "/index.html"; + private static final String REGISTER_PAGE = "/register.html"; + + @Override + protected void doPost(final HttpRequest request, final HttpResponse response) { + final Map userInfos = request.getBody().parseUserInfos(); + if (InMemoryUserRepository.isNonExistentByAccount(userInfos.get("account"))) { + final User user = new User(userInfos.get("account"), userInfos.get("password"), userInfos.get("email")); + InMemoryUserRepository.save(user); + response.setHttpStatus(HttpStatus.FOUND); + response.setPath(MAIN_PAGE); + response.setRedirect(); + return; + } + response.setHttpStatus(HttpStatus.OK); + response.setPath(request.getUri().getPath()); + } + + @Override + protected void doGet(final HttpRequest request, final HttpResponse response) { + response.setHttpStatus(HttpStatus.OK); + response.setPath(REGISTER_PAGE); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java new file mode 100644 index 0000000000..67ba028aea --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java @@ -0,0 +1,24 @@ +package org.apache.coyote.http11.controller; + +import java.util.HashMap; +import java.util.Map; +import org.apache.coyote.http11.request.HttpRequest; + +public class RequestMapping { + + private static final String ROOT_PATH = "/"; + private static final String LOGIN_PATH = "/login"; + private static final String REGISTER_PATH = "/register"; + + private static final Map REQUEST_MAPPER = new HashMap<>(); + + static { + REQUEST_MAPPER.put(ROOT_PATH, new RootController()); + REQUEST_MAPPER.put(LOGIN_PATH, new LoginController()); + REQUEST_MAPPER.put(REGISTER_PATH, new RegisterController()); + } + + public Controller getController(final HttpRequest request) { + return REQUEST_MAPPER.getOrDefault(request.getUri().getPath(), new PageController()); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RootController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/RootController.java new file mode 100644 index 0000000000..c6439ccaa0 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RootController.java @@ -0,0 +1,17 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; + +public class RootController extends AbstractController { + + private static final String ROOT_PATH = "/"; + + @Override + protected void doGet(final HttpRequest request, final HttpResponse response) { + response.setHttpStatus(HttpStatus.OK); + response.setPath(ROOT_PATH); + response.setBody("Hello world!"); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpMethod.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpMethod.java similarity index 56% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpMethod.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpMethod.java index 42cee77d48..afcd690f8e 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpMethod.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpMethod.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; public enum HttpMethod { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java similarity index 70% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java index 2fba3a8a44..eb9e2fb874 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequest.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequest.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; import java.io.BufferedReader; import java.io.IOException; @@ -10,8 +10,8 @@ public class HttpRequest { private final HttpRequestBody body; public static HttpRequest from(final BufferedReader bufferedReader) throws IOException { - final String firstLine = bufferedReader.readLine(); - final HttpRequestLine httpRequestLine = HttpRequestLine.from(firstLine); + final String requestLine = bufferedReader.readLine(); + final HttpRequestLine httpRequestLine = HttpRequestLine.from(requestLine); final HttpRequestHeader headers = HttpRequestHeader.from(bufferedReader); final HttpRequestBody httpRequestBody = HttpRequestBody.of(bufferedReader, headers); @@ -28,17 +28,7 @@ private HttpRequest( this.body = body; } - public boolean isLogin() { - final Uri uri = requestLine.getUri(); - return uri.isLogin(); - } - - public boolean isRegister() { - final Uri uri = requestLine.getUri(); - return uri.isRegister(); - } - - public boolean isCorrectMethod(final HttpMethod method) { + public boolean matchesMethod(final HttpMethod method) { return requestLine.getHttpMethod() == method; } @@ -50,11 +40,7 @@ public String getJSessionId() { return headers.getJSessionId(); } - public HttpRequestLine getRequestLine() { - return requestLine; - } - - public Uri getPath() { + public Uri getUri() { return requestLine.getUri(); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestBody.java similarity index 97% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestBody.java index b2e8feeeee..552c6ec253 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestBody.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestBody.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; import java.io.BufferedReader; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestHeader.java similarity index 97% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestHeader.java index 9ecf87f9d2..14906f4d18 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestHeader.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; import java.io.BufferedReader; import java.io.IOException; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java similarity index 83% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java index 3b7e4b9d70..0e9b5a0627 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpRequestLine.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java @@ -1,7 +1,8 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; import java.util.Arrays; import java.util.List; +import org.apache.coyote.http11.HttpVersion; public class HttpRequestLine { @@ -23,7 +24,7 @@ public HttpRequestLine( ) { this.httpMethod = HttpMethod.valueOf(httpMethod); this.uri = Uri.from(uri); - this.httpVersion = HttpVersion.valueOf(httpVersion); + this.httpVersion = HttpVersion.findVersion(httpVersion); } public HttpMethod getHttpMethod() { @@ -33,8 +34,4 @@ public HttpMethod getHttpMethod() { public Uri getUri() { return uri; } - - public HttpVersion getHttpVersion() { - return httpVersion; - } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/QueryString.java b/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java similarity index 95% rename from tomcat/src/main/java/org/apache/coyote/http11/QueryString.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java index 84ac52390f..c27833fc08 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/QueryString.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; import java.util.Arrays; import java.util.HashMap; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/Uri.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java similarity index 79% rename from tomcat/src/main/java/org/apache/coyote/http11/Uri.java rename to tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java index 124c0a3021..8ac54383a5 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Uri.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.request; public class Uri { @@ -20,14 +20,6 @@ private Uri(final String path, final String queryString) { this.queryString = QueryString.from(queryString); } - public boolean isLogin() { - return path.equals("/login"); - } - - public boolean isRegister() { - return path.equals("/register"); - } - public String getPath() { return path; } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java similarity index 94% rename from tomcat/src/main/java/org/apache/coyote/http11/ContentType.java rename to tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java index f17f6bee14..9035acef3c 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.response; import java.util.Arrays; 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..de0c9c4b23 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -0,0 +1,112 @@ +package org.apache.coyote.http11.response; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import org.apache.coyote.http11.HttpVersion; +import org.apache.coyote.http11.auth.HttpCookie; + +public class HttpResponse { + + private static final String CHARSET_UTF_8 = ";charset=utf-8"; + private static final String BLANK = " "; + + private final HttpResponseHeader httpResponseHeader = new HttpResponseHeader(); + private HttpStatusLine httpStatusLine; + private String path; + private String body; + private boolean isRedirect = false; + + public String get() throws IOException { + final String contentType = ContentType.getByPath(path) + CHARSET_UTF_8; + if (path.equals("/")) { + return makeResponse(contentType); + } + if (isRedirect) { + if (httpResponseHeader.hasCookie()) { + return makeRedirectResponseWithCookie(); + } + return makeRedirectResponse(); + } + + final URL resource = HttpResponse.class.getClassLoader().getResource("static" + path); + this.body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); + return makeResponse(contentType); + } + + private String makeResponse(final String contentType) { + if (httpResponseHeader.hasCookie()) { + return makeGeneralResponseWithCookie(contentType, body); + } + return makeGeneralResponse(contentType, body); + } + + private String makeRedirectResponse() { + final HttpStatus status = httpStatusLine.getHttpStatus(); + return String.join("\r\n", + "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + "Location: " + path + BLANK, + "" + ); + } + + private String makeRedirectResponseWithCookie() { + final HttpStatus status = httpStatusLine.getHttpStatus(); + final HttpCookie cookie = httpResponseHeader.getCookie(); + return String.join("\r\n", + "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + "Set-Cookie: " + cookie.getValues() + BLANK, + "Location: " + path + BLANK, + "" + ); + } + + private String makeGeneralResponseWithCookie(final String contentType, final String body) { + final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); + final HttpStatus status = httpStatusLine.getHttpStatus(); + final HttpCookie cookie = httpResponseHeader.getCookie(); + return String.join("\r\n", + httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, + "Set-Cookie: " + cookie.getValues() + BLANK, + "Content-Type: " + contentType + BLANK, + "Content-Length: " + body.getBytes().length + BLANK, + "", + body + ); + } + + private String makeGeneralResponse( + final String contentType, + final String body + ) { + final HttpStatus status = httpStatusLine.getHttpStatus(); + return String.join("\r\n", + "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + "Content-Type: " + contentType + BLANK, + "Content-Length: " + body.getBytes().length + BLANK, + "", + body + ); + } + + public void addCookie(final HttpCookie cookie) { + this.httpResponseHeader.setCookie(cookie); + } + + public void setHttpStatus(final HttpStatus httpStatus) { + this.httpStatusLine = HttpStatusLine.from(httpStatus); + } + + public void setPath(final String path) { + this.path = path; + } + + public void setBody(final String body) { + this.body = body; + } + + public void setRedirect() { + isRedirect = true; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java new file mode 100644 index 0000000000..13b2c04fd1 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java @@ -0,0 +1,27 @@ +package org.apache.coyote.http11.response; + +import java.util.HashMap; +import java.util.Map; +import org.apache.coyote.http11.auth.HttpCookie; + +public class HttpResponseHeader { + + private final Map headers = new HashMap<>(); + private HttpCookie cookie; + + public HttpResponseHeader() { + this.cookie = new HttpCookie(new HashMap<>()); + } + + public boolean hasCookie() { + return cookie.isNotEmpty(); + } + + public void setCookie(final HttpCookie cookie) { + this.cookie = cookie; + } + + public HttpCookie getCookie() { + return cookie; + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpStatus.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java similarity index 84% rename from tomcat/src/main/java/org/apache/coyote/http11/HttpStatus.java rename to tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java index d5694455b6..8cae7c5d7a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpStatus.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11; +package org.apache.coyote.http11.response; public enum HttpStatus { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusLine.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusLine.java new file mode 100644 index 0000000000..bd09ed0f59 --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatusLine.java @@ -0,0 +1,26 @@ +package org.apache.coyote.http11.response; + +import org.apache.coyote.http11.HttpVersion; + +public class HttpStatusLine { + + private final HttpVersion httpVersion; + private final HttpStatus httpStatus; + + public static HttpStatusLine from(final HttpStatus httpStatus) { + return new HttpStatusLine(HttpVersion.HTTP11, httpStatus); + } + + private HttpStatusLine(final HttpVersion httpVersion, final HttpStatus httpStatus) { + this.httpVersion = httpVersion; + this.httpStatus = httpStatus; + } + + public HttpVersion getHttpVersion() { + return httpVersion; + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } +} From 4f9e7d52412c18cf98602787b4e1c280df217709 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Sun, 10 Sep 2023 22:16:15 +0900 Subject: [PATCH 03/15] =?UTF-8?q?refactor:=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=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/auth/HttpCookie.java | 2 +- .../apache/coyote/http11/response/ContentType.java | 14 +++----------- .../coyote/http11/response/HttpResponse.java | 6 +++--- .../apache/coyote/http11/response/HttpStatus.java | 1 - 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java b/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java index 44829113e1..356b56fda4 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java @@ -19,7 +19,7 @@ public HttpCookie(final Map values) { this.values = values; } - public String getValues() { + public String printValues() { return values.keySet() .stream() .map(key -> key + "=" + values.get(key) + "; ") diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java index 9035acef3c..49aebc8e9a 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java @@ -19,17 +19,9 @@ public enum ContentType { public static String getByPath(final String path) { return Arrays.stream(values()) - .filter(it -> path.endsWith(it.getFileExtension())) - .map(ContentType::getType) + .filter(it -> path.endsWith(it.fileExtension)) + .map(it -> it.type) .findAny() - .orElse(HTML.getType()); - } - - public String getType() { - return type; - } - - public String getFileExtension() { - return fileExtension; + .orElse(HTML.type); } } 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 de0c9c4b23..fb2d6028f3 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponse.java @@ -56,7 +56,7 @@ private String makeRedirectResponseWithCookie() { final HttpCookie cookie = httpResponseHeader.getCookie(); return String.join("\r\n", "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.getValues() + BLANK, + "Set-Cookie: " + cookie.printValues() + BLANK, "Location: " + path + BLANK, "" ); @@ -68,7 +68,7 @@ private String makeGeneralResponseWithCookie(final String contentType, final Str final HttpCookie cookie = httpResponseHeader.getCookie(); return String.join("\r\n", httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.getValues() + BLANK, + "Set-Cookie: " + cookie.printValues() + BLANK, "Content-Type: " + contentType + BLANK, "Content-Length: " + body.getBytes().length + BLANK, "", @@ -93,7 +93,7 @@ private String makeGeneralResponse( public void addCookie(final HttpCookie cookie) { this.httpResponseHeader.setCookie(cookie); } - + public void setHttpStatus(final HttpStatus httpStatus) { this.httpStatusLine = HttpStatusLine.from(httpStatus); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java index 8cae7c5d7a..7e3417fdb9 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpStatus.java @@ -4,7 +4,6 @@ public enum HttpStatus { OK(200), FOUND(302), - UNAUTHORIZED(401), ; private final int code; From 0fc7f2f07c59c7899b606b73900dd1b58e7dd943 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Sun, 10 Sep 2023 22:18:37 +0900 Subject: [PATCH 04/15] =?UTF-8?q?refactor:=20sendRedirect=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A1=9C=20=EC=97=AD=ED=95=A0=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/coyote/http11/controller/LoginController.java | 9 +++------ .../coyote/http11/controller/RegisterController.java | 3 +-- .../org/apache/coyote/http11/response/HttpResponse.java | 9 +++++---- 3 files changed, 9 insertions(+), 12 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 0cc0179706..5505155d0c 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 @@ -37,14 +37,12 @@ protected void doPost(final HttpRequest request, final HttpResponse response) { log.info("로그인 성공! 아이디: {}", account); response.setHttpStatus(HttpStatus.FOUND); - response.setPath(MAIN_PAGE); - response.setRedirect(); + response.sendRedirect(MAIN_PAGE); response.addCookie(HttpCookie.ofJSessionId(session.getId())); return; } response.setHttpStatus(HttpStatus.FOUND); - response.setPath(UNAUTHORIZED_PAGE); - response.setRedirect(); + response.sendRedirect(UNAUTHORIZED_PAGE); } @Override @@ -53,8 +51,7 @@ protected void doGet(final HttpRequest request, final HttpResponse response) { final Session session = SESSION_MANAGER.findSession(request.getJSessionId()); final User user = (User) session.getAttribute("user"); response.setHttpStatus(HttpStatus.FOUND); - response.setPath(MAIN_PAGE); - response.setRedirect(); + response.sendRedirect(MAIN_PAGE); return; } response.setHttpStatus(HttpStatus.OK); 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 index bfa140ffea..5579ac36ad 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java @@ -19,8 +19,7 @@ protected void doPost(final HttpRequest request, final HttpResponse response) { final User user = new User(userInfos.get("account"), userInfos.get("password"), userInfos.get("email")); InMemoryUserRepository.save(user); response.setHttpStatus(HttpStatus.FOUND); - response.setPath(MAIN_PAGE); - response.setRedirect(); + response.sendRedirect(MAIN_PAGE); return; } response.setHttpStatus(HttpStatus.OK); 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 fb2d6028f3..029f0fc3a7 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 @@ -94,6 +94,11 @@ public void addCookie(final HttpCookie cookie) { this.httpResponseHeader.setCookie(cookie); } + public void sendRedirect(final String path) { + this.path = path; + this.isRedirect = true; + } + public void setHttpStatus(final HttpStatus httpStatus) { this.httpStatusLine = HttpStatusLine.from(httpStatus); } @@ -105,8 +110,4 @@ public void setPath(final String path) { public void setBody(final String body) { this.body = body; } - - public void setRedirect() { - isRedirect = true; - } } From a1a1fd501877f1c498f1cbf8c9528c3febac4fc3 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Sun, 10 Sep 2023 22:39:37 +0900 Subject: [PATCH 05/15] =?UTF-8?q?refactor:=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 --- .../apache/coyote/http11/request/QueryString.java | 11 +++++------ .../java/org/apache/coyote/http11/request/Uri.java | 13 ++++++------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java b/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java index c27833fc08..96644f2296 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/QueryString.java @@ -7,14 +7,17 @@ public class QueryString { + private static final String QUERY_STRING_DELIMITER = "&"; + private static final String QUERY_STRING_SEPARATOR = "="; + private final Map params; public static QueryString from(final String queryString) { if (queryString.isEmpty()) { return new QueryString(new HashMap<>()); } - final Map params = Arrays.stream(queryString.split("&")) - .map(string -> Arrays.asList(string.split("="))) + final Map params = Arrays.stream(queryString.split(QUERY_STRING_DELIMITER)) + .map(string -> Arrays.asList(string.split(QUERY_STRING_SEPARATOR))) .collect(Collectors.toMap(data -> data.get(0), data -> data.get(1), (a, b) -> b)); return new QueryString(params); } @@ -23,10 +26,6 @@ private QueryString(final Map params) { this.params = params; } - public boolean hasNoQueryString() { - return params.isEmpty(); - } - public String get(final String key) { return params.get(key); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java b/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java index 8ac54383a5..424efbb742 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/Uri.java @@ -2,17 +2,20 @@ public class Uri { + private static final String QUERY_STRING_START_LETTER = "?"; + private static final String EMPTY_STRING = ""; + private final String path; private final QueryString queryString; public static Uri from(final String uri) { - if (uri.contains("?")) { - final int index = uri.indexOf("?"); + if (uri.contains(QUERY_STRING_START_LETTER)) { + final int index = uri.indexOf(QUERY_STRING_START_LETTER); final String path = uri.substring(0, index); final String queryString = uri.substring(index + 1); return new Uri(path, queryString); } - return new Uri(uri, ""); + return new Uri(uri, EMPTY_STRING); } private Uri(final String path, final String queryString) { @@ -23,8 +26,4 @@ private Uri(final String path, final String queryString) { public String getPath() { return path; } - - public QueryString getQueryString() { - return queryString; - } } From 9db934560d82b7e7c4447b22e2ab559e3b98f6c7 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Sun, 10 Sep 2023 22:39:51 +0900 Subject: [PATCH 06/15] =?UTF-8?q?refactor:=20=EC=97=86=EB=8A=94=20?= =?UTF-8?q?=EC=84=B8=EC=85=98=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/controller/LoginController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 5505155d0c..2814bc0994 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 @@ -49,7 +49,9 @@ protected void doPost(final HttpRequest request, final HttpResponse response) { protected void doGet(final HttpRequest request, final HttpResponse response) { if (request.hasJSessionId()) { final Session session = SESSION_MANAGER.findSession(request.getJSessionId()); - final User user = (User) session.getAttribute("user"); + if (session == null) { + throw new IllegalArgumentException("존재하지 않는 세션입니다."); + } response.setHttpStatus(HttpStatus.FOUND); response.sendRedirect(MAIN_PAGE); return; From da79b67e3f58d46fef8a4dc13de90f67777160f6 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Mon, 11 Sep 2023 00:50:45 +0900 Subject: [PATCH 07/15] =?UTF-8?q?refactor:=20Executors=EB=A1=9C=20Thread?= =?UTF-8?q?=20Pool=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20SessionManager=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=EC=84=B1=20=EC=BB=AC=EB=A0=89=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/catalina/connector/Connector.java | 18 +++++++++++------- .../coyote/http11/auth/SessionManager.java | 4 ++-- 2 files changed, 13 insertions(+), 9 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..eaef2ec2d9 100644 --- a/tomcat/src/main/java/org/apache/catalina/connector/Connector.java +++ b/tomcat/src/main/java/org/apache/catalina/connector/Connector.java @@ -1,13 +1,14 @@ package org.apache.catalina.connector; -import org.apache.coyote.http11.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.http11.Http11Processor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Connector implements Runnable { @@ -15,16 +16,19 @@ 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 final ExecutorService executorService; private boolean stopped; 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.executorService = Executors.newFixedThreadPool(maxThreads); this.stopped = false; } @@ -67,7 +71,7 @@ private void process(final Socket connection) { return; } var processor = new Http11Processor(connection); - new Thread(processor).start(); + executorService.execute(processor); } public void stop() { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java index b42db19ec1..b54b676109 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java @@ -1,12 +1,12 @@ package org.apache.coyote.http11.auth; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.catalina.Manager; public class SessionManager implements Manager { - private static final Map SESSIONS = new HashMap<>(); + private static final Map SESSIONS = new ConcurrentHashMap<>(); public SessionManager() { } From 6b294dcda6e80f2ce6d1e199d899b7d14d3db974 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Mon, 11 Sep 2023 01:48:04 +0900 Subject: [PATCH 08/15] =?UTF-8?q?refactor:=20get,=20post=EC=9D=B4=EC=99=B8?= =?UTF-8?q?=EC=9D=98=20=EC=9A=94=EC=B2=AD=EC=9D=B4=20=EC=99=94=EC=9D=84=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20404=EB=A1=9C=20redirect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coyote/http11/controller/AbstractController.java | 3 +++ .../org/apache/coyote/http11/response/ContentType.java | 8 +++++--- 2 files changed, 8 insertions(+), 3 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 e160de79c3..2bc5ca567e 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 @@ -3,6 +3,7 @@ import org.apache.coyote.http11.request.HttpMethod; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; public abstract class AbstractController implements Controller { @@ -14,6 +15,8 @@ public void service(final HttpRequest request, final HttpResponse response) thro if (request.matchesMethod(HttpMethod.POST)) { doPost(request, response); } + response.setHttpStatus(HttpStatus.FOUND); + response.sendRedirect("/404.html"); } protected void doPost(final HttpRequest request, final HttpResponse response) throws Exception { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java index 49aebc8e9a..ddfcf643a2 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java @@ -7,10 +7,12 @@ public enum ContentType { HTML("text/html", ".html"), CSS("text/css", ".css"), JS("application/javascript", ".js"), - ICO("image/x-icon", ".ico"); + ICO("image/x-icon", ".ico"), + SVG("image/svg+xml", ".svg"), + ; - final String type; - final String fileExtension; + private final String type; + private final String fileExtension; ContentType(final String type, final String fileExtension) { this.type = type; From d02ff6137ecee01dfdb5880f5fb2547215dba01c Mon Sep 17 00:00:00 2001 From: jeomxon Date: Mon, 11 Sep 2023 01:54:01 +0900 Subject: [PATCH 09/15] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20?= =?UTF-8?q?=EC=83=81=EC=88=98=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/{auth => }/HttpCookie.java | 7 +++++-- .../apache/coyote/http11/controller/LoginController.java | 2 +- .../org/apache/coyote/http11/response/HttpResponse.java | 2 +- .../apache/coyote/http11/response/HttpResponseHeader.java | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/{auth => }/HttpCookie.java (74%) diff --git a/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java similarity index 74% rename from tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java rename to tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java index 356b56fda4..4af4554b71 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/auth/HttpCookie.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.auth; +package org.apache.coyote.http11; import java.util.HashMap; import java.util.Map; @@ -6,6 +6,9 @@ public class HttpCookie { + private static final String COOKIE_DELIMITER = "; "; + private static final String COOKIE_SEPARATOR = "="; + private final Map values; public static HttpCookie ofJSessionId(final String jSessionId) { @@ -22,7 +25,7 @@ public HttpCookie(final Map values) { public String printValues() { return values.keySet() .stream() - .map(key -> key + "=" + values.get(key) + "; ") + .map(key -> key + COOKIE_SEPARATOR + values.get(key) + COOKIE_DELIMITER) .collect(Collectors.joining()); } 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 2814bc0994..0f763c09ec 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 @@ -6,7 +6,7 @@ import java.util.UUID; import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.model.User; -import org.apache.coyote.http11.auth.HttpCookie; +import org.apache.coyote.http11.HttpCookie; import org.apache.coyote.http11.auth.Session; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; 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 029f0fc3a7..8aff36b1ec 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 @@ -4,8 +4,8 @@ import java.io.IOException; import java.net.URL; import java.nio.file.Files; +import org.apache.coyote.http11.HttpCookie; import org.apache.coyote.http11.HttpVersion; -import org.apache.coyote.http11.auth.HttpCookie; public class HttpResponse { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java index 13b2c04fd1..96192f9e57 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java @@ -2,7 +2,7 @@ import java.util.HashMap; import java.util.Map; -import org.apache.coyote.http11.auth.HttpCookie; +import org.apache.coyote.http11.HttpCookie; public class HttpResponseHeader { From 7fe69af6a1a8bc0b06d6c064034e8ded4f520c5d Mon Sep 17 00:00:00 2001 From: jeomxon Date: Mon, 11 Sep 2023 02:04:54 +0900 Subject: [PATCH 10/15] =?UTF-8?q?refactor:=20=EB=B6=84=EA=B8=B0=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20return=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/controller/AbstractController.java | 2 ++ 1 file changed, 2 insertions(+) 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 2bc5ca567e..f0b7964b2d 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 @@ -11,9 +11,11 @@ public abstract class AbstractController implements Controller { public void service(final HttpRequest request, final HttpResponse response) throws Exception { if (request.matchesMethod(HttpMethod.GET)) { doGet(request, response); + return; } if (request.matchesMethod(HttpMethod.POST)) { doPost(request, response); + return; } response.setHttpStatus(HttpStatus.FOUND); response.sendRedirect("/404.html"); From 5f5bcb164bc4df902809690d672b0ff7819af4e2 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Mon, 11 Sep 2023 17:03:18 +0900 Subject: [PATCH 11/15] =?UTF-8?q?refactor:=20HttpResponse=EC=9D=98=20HttpV?= =?UTF-8?q?ersion=EC=9D=84=20=ED=86=B5=EC=9D=BC=EB=90=9C=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/response/HttpResponse.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 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 8aff36b1ec..b76d2b51ab 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 @@ -43,19 +43,21 @@ private String makeResponse(final String contentType) { } private String makeRedirectResponse() { + final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); final HttpStatus status = httpStatusLine.getHttpStatus(); return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, "Location: " + path + BLANK, "" ); } private String makeRedirectResponseWithCookie() { + final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); final HttpStatus status = httpStatusLine.getHttpStatus(); final HttpCookie cookie = httpResponseHeader.getCookie(); return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, "Set-Cookie: " + cookie.printValues() + BLANK, "Location: " + path + BLANK, "" @@ -80,9 +82,10 @@ private String makeGeneralResponse( final String contentType, final String body ) { + final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); final HttpStatus status = httpStatusLine.getHttpStatus(); return String.join("\r\n", - "HTTP/1.1" + BLANK + status.getCode() + BLANK + status.name() + BLANK, + httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, "Content-Type: " + contentType + BLANK, "Content-Length: " + body.getBytes().length + BLANK, "", From 0ccfc56deb7b99dc79c77f28aba45bf2c74b47d5 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Wed, 13 Sep 2023 11:57:32 +0900 Subject: [PATCH 12/15] =?UTF-8?q?refactor:=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 --- .../src/main/java/org/apache/catalina/Manager.java | 2 +- .../org/apache/coyote/http11/Http11Processor.java | 2 +- .../coyote/http11/controller/AbstractController.java | 4 +++- .../coyote/http11/controller/LoginController.java | 12 ++++++++---- .../coyote/http11/request/HttpRequestLine.java | 2 +- .../apache/coyote/http11/response/HttpResponse.java | 6 ++++-- .../coyote/http11/{auth => session}/Session.java | 2 +- .../http11/{auth => session}/SessionManager.java | 5 +---- 8 files changed, 20 insertions(+), 15 deletions(-) rename tomcat/src/main/java/org/apache/coyote/http11/{auth => session}/Session.java (93%) rename tomcat/src/main/java/org/apache/coyote/http11/{auth => session}/SessionManager.java (88%) diff --git a/tomcat/src/main/java/org/apache/catalina/Manager.java b/tomcat/src/main/java/org/apache/catalina/Manager.java index 64969003a4..fb2a55dcb4 100644 --- a/tomcat/src/main/java/org/apache/catalina/Manager.java +++ b/tomcat/src/main/java/org/apache/catalina/Manager.java @@ -1,6 +1,6 @@ package org.apache.catalina; -import org.apache.coyote.http11.auth.Session; +import org.apache.coyote.http11.session.Session; /** * A Manager manages the pool of Sessions that are associated with a particular Container. Different Manager 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 6c43260013..5964879811 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java @@ -4,11 +4,11 @@ import java.io.InputStreamReader; import java.net.Socket; import org.apache.coyote.Processor; -import org.apache.coyote.http11.auth.SessionManager; import org.apache.coyote.http11.controller.Controller; import org.apache.coyote.http11.controller.RequestMapping; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.session.SessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 f0b7964b2d..b923f81c59 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 @@ -7,6 +7,8 @@ public abstract class AbstractController implements Controller { + private static final String NOT_FOUND_PAGE = "/404.html"; + @Override public void service(final HttpRequest request, final HttpResponse response) throws Exception { if (request.matchesMethod(HttpMethod.GET)) { @@ -18,7 +20,7 @@ public void service(final HttpRequest request, final HttpResponse response) thro return; } response.setHttpStatus(HttpStatus.FOUND); - response.sendRedirect("/404.html"); + response.sendRedirect(NOT_FOUND_PAGE); } protected void doPost(final HttpRequest request, final HttpResponse response) throws Exception { 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 0f763c09ec..c83f4a1be0 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 @@ -7,10 +7,10 @@ import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.model.User; import org.apache.coyote.http11.HttpCookie; -import org.apache.coyote.http11.auth.Session; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; import org.apache.coyote.http11.response.HttpStatus; +import org.apache.coyote.http11.session.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,9 +49,7 @@ protected void doPost(final HttpRequest request, final HttpResponse response) { protected void doGet(final HttpRequest request, final HttpResponse response) { if (request.hasJSessionId()) { final Session session = SESSION_MANAGER.findSession(request.getJSessionId()); - if (session == null) { - throw new IllegalArgumentException("존재하지 않는 세션입니다."); - } + validateExistentSession(session); response.setHttpStatus(HttpStatus.FOUND); response.sendRedirect(MAIN_PAGE); return; @@ -59,4 +57,10 @@ protected void doGet(final HttpRequest request, final HttpResponse response) { response.setHttpStatus(HttpStatus.OK); response.setPath(LOGIN_PAGE); } + + private void validateExistentSession(final Session session) { + if (session == null) { + throw new IllegalArgumentException("존재하지 않는 세션입니다."); + } + } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java index 0e9b5a0627..d24d3ecaad 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/request/HttpRequestLine.java @@ -17,7 +17,7 @@ public static HttpRequestLine from(final String requestLine) { return new HttpRequestLine(requestLineInfos.get(0), requestLineInfos.get(1), requestLineInfos.get(2)); } - public HttpRequestLine( + private HttpRequestLine( final String httpMethod, final String uri, final String httpVersion 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 b76d2b51ab..2978660aec 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 @@ -11,6 +11,8 @@ public class HttpResponse { private static final String CHARSET_UTF_8 = ";charset=utf-8"; private static final String BLANK = " "; + private static final String STATIC_PATH = "static"; + private static final String ROOT_PATH = "/"; private final HttpResponseHeader httpResponseHeader = new HttpResponseHeader(); private HttpStatusLine httpStatusLine; @@ -20,7 +22,7 @@ public class HttpResponse { public String get() throws IOException { final String contentType = ContentType.getByPath(path) + CHARSET_UTF_8; - if (path.equals("/")) { + if (path.equals(ROOT_PATH)) { return makeResponse(contentType); } if (isRedirect) { @@ -30,7 +32,7 @@ public String get() throws IOException { return makeRedirectResponse(); } - final URL resource = HttpResponse.class.getClassLoader().getResource("static" + path); + final URL resource = HttpResponse.class.getClassLoader().getResource(STATIC_PATH + path); this.body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); return makeResponse(contentType); } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java similarity index 93% rename from tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java rename to tomcat/src/main/java/org/apache/coyote/http11/session/Session.java index 388f43c430..4b29b70c07 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/auth/Session.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/Session.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.auth; +package org.apache.coyote.http11.session; import java.util.HashMap; import java.util.Map; diff --git a/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java b/tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java similarity index 88% rename from tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java rename to tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java index b54b676109..2c38f1b8a0 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/auth/SessionManager.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/session/SessionManager.java @@ -1,4 +1,4 @@ -package org.apache.coyote.http11.auth; +package org.apache.coyote.http11.session; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -8,9 +8,6 @@ public class SessionManager implements Manager { private static final Map SESSIONS = new ConcurrentHashMap<>(); - public SessionManager() { - } - @Override public void add(final Session session) { SESSIONS.put(session.getId(), session); From 7417df7d17b50a0e7db64603c7f11654960878ad Mon Sep 17 00:00:00 2001 From: jeomxon Date: Wed, 13 Sep 2023 12:27:18 +0900 Subject: [PATCH 13/15] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C=20=EC=8B=9C=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8F=84?= =?UTF-8?q?=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 --- .../http11/controller/RegisterController.java | 16 ++++++++++++++++ .../coyote/http11/response/HttpResponse.java | 4 ++++ 2 files changed, 20 insertions(+) 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 index 5579ac36ad..76f49b538b 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RegisterController.java @@ -1,11 +1,14 @@ package org.apache.coyote.http11.controller; +import static org.apache.coyote.http11.Http11Processor.SESSION_MANAGER; + import java.util.Map; import nextstep.jwp.db.InMemoryUserRepository; import nextstep.jwp.model.User; import org.apache.coyote.http11.request.HttpRequest; import org.apache.coyote.http11.response.HttpResponse; import org.apache.coyote.http11.response.HttpStatus; +import org.apache.coyote.http11.session.Session; public class RegisterController extends AbstractController { @@ -28,7 +31,20 @@ protected void doPost(final HttpRequest request, final HttpResponse response) { @Override protected void doGet(final HttpRequest request, final HttpResponse response) { + if (request.hasJSessionId()) { + final Session session = SESSION_MANAGER.findSession(request.getJSessionId()); + validateExistentSession(session); + response.setHttpStatus(HttpStatus.FOUND); + response.sendRedirect(MAIN_PAGE); + return; + } response.setHttpStatus(HttpStatus.OK); response.setPath(REGISTER_PAGE); } + + private void validateExistentSession(final Session session) { + if (session == null) { + throw new IllegalArgumentException("존재하지 않는 세션입니다."); + } + } } 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 2978660aec..94d01674aa 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 @@ -11,6 +11,7 @@ public class HttpResponse { private static final String CHARSET_UTF_8 = ";charset=utf-8"; private static final String BLANK = " "; + private static final String EMPTY_STRING = ""; private static final String STATIC_PATH = "static"; private static final String ROOT_PATH = "/"; @@ -33,6 +34,9 @@ public String get() throws IOException { } final URL resource = HttpResponse.class.getClassLoader().getResource(STATIC_PATH + path); + if (resource == null) { + return EMPTY_STRING; + } this.body = new String(Files.readAllBytes(new File(resource.getFile()).toPath())); return makeResponse(contentType); } From f4e182152029fce82ac97a119007a7a8b9daa96f Mon Sep 17 00:00:00 2001 From: jeomxon Date: Thu, 14 Sep 2023 13:24:58 +0900 Subject: [PATCH 14/15] =?UTF-8?q?refactor:=20=EC=A7=80=EC=A0=95=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=9A=94=EC=B2=AD=EC=9D=B4=20?= =?UTF-8?q?=EC=99=94=EC=9D=84=20=EB=95=8C=20404=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=EC=8B=9C=ED=82=A4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../http11/controller/NotFoundController.java | 16 ++++++++++++++++ .../coyote/http11/controller/RequestMapping.java | 7 ++++++- .../coyote/http11/response/ContentType.java | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tomcat/src/main/java/org/apache/coyote/http11/controller/NotFoundController.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/NotFoundController.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/NotFoundController.java new file mode 100644 index 0000000000..dc56452b5a --- /dev/null +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/NotFoundController.java @@ -0,0 +1,16 @@ +package org.apache.coyote.http11.controller; + +import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.HttpResponse; +import org.apache.coyote.http11.response.HttpStatus; + +public class NotFoundController extends AbstractController { + + private static final String NOT_FOUND_PAGE = "/404.html"; + + @Override + protected void doGet(final HttpRequest request, final HttpResponse response) throws Exception { + response.setHttpStatus(HttpStatus.OK); + response.setPath(NOT_FOUND_PAGE); + } +} diff --git a/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java b/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java index 67ba028aea..9c2b134ecc 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/controller/RequestMapping.java @@ -3,6 +3,7 @@ import java.util.HashMap; import java.util.Map; import org.apache.coyote.http11.request.HttpRequest; +import org.apache.coyote.http11.response.ContentType; public class RequestMapping { @@ -19,6 +20,10 @@ public class RequestMapping { } public Controller getController(final HttpRequest request) { - return REQUEST_MAPPER.getOrDefault(request.getUri().getPath(), new PageController()); + final String requestPath = request.getUri().getPath(); + if (ContentType.matchesFileExtension(requestPath)) { + return new PageController(); + } + return REQUEST_MAPPER.getOrDefault(requestPath, new NotFoundController()); } } diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java index ddfcf643a2..84961ee4c7 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/response/ContentType.java @@ -26,4 +26,9 @@ public static String getByPath(final String path) { .findAny() .orElse(HTML.type); } + + public static boolean matchesFileExtension(final String path) { + return Arrays.stream(values()) + .anyMatch(contentType -> path.endsWith(contentType.fileExtension)); + } } From 363ba00c889aee4c8e353c36ee2d6cd4a0127543 Mon Sep 17 00:00:00 2001 From: jeomxon Date: Thu, 14 Sep 2023 13:59:28 +0900 Subject: [PATCH 15/15] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/apache/coyote/http11/HttpCookie.java | 6 ++++- .../coyote/http11/response/HttpResponse.java | 14 +++++----- .../http11/response/HttpResponseHeader.java | 27 ------------------- 3 files changed, 11 insertions(+), 36 deletions(-) delete mode 100644 tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java diff --git a/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java b/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java index 4af4554b71..7b70e60464 100644 --- a/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java +++ b/tomcat/src/main/java/org/apache/coyote/http11/HttpCookie.java @@ -18,7 +18,11 @@ public static HttpCookie ofJSessionId(final String jSessionId) { return new HttpCookie(values); } - public HttpCookie(final Map values) { + public HttpCookie() { + this.values = new HashMap<>(); + } + + private HttpCookie(final Map values) { this.values = values; } 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 94d01674aa..27115e3303 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 @@ -15,7 +15,7 @@ public class HttpResponse { private static final String STATIC_PATH = "static"; private static final String ROOT_PATH = "/"; - private final HttpResponseHeader httpResponseHeader = new HttpResponseHeader(); + private HttpCookie httpCookie = new HttpCookie(); private HttpStatusLine httpStatusLine; private String path; private String body; @@ -27,7 +27,7 @@ public String get() throws IOException { return makeResponse(contentType); } if (isRedirect) { - if (httpResponseHeader.hasCookie()) { + if (httpCookie.isNotEmpty()) { return makeRedirectResponseWithCookie(); } return makeRedirectResponse(); @@ -42,7 +42,7 @@ public String get() throws IOException { } private String makeResponse(final String contentType) { - if (httpResponseHeader.hasCookie()) { + if (httpCookie.isNotEmpty()) { return makeGeneralResponseWithCookie(contentType, body); } return makeGeneralResponse(contentType, body); @@ -61,10 +61,9 @@ private String makeRedirectResponse() { private String makeRedirectResponseWithCookie() { final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); final HttpStatus status = httpStatusLine.getHttpStatus(); - final HttpCookie cookie = httpResponseHeader.getCookie(); return String.join("\r\n", httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.printValues() + BLANK, + "Set-Cookie: " + httpCookie.printValues() + BLANK, "Location: " + path + BLANK, "" ); @@ -73,10 +72,9 @@ private String makeRedirectResponseWithCookie() { private String makeGeneralResponseWithCookie(final String contentType, final String body) { final HttpVersion httpVersion = httpStatusLine.getHttpVersion(); final HttpStatus status = httpStatusLine.getHttpStatus(); - final HttpCookie cookie = httpResponseHeader.getCookie(); return String.join("\r\n", httpVersion.getValue() + BLANK + status.getCode() + BLANK + status.name() + BLANK, - "Set-Cookie: " + cookie.printValues() + BLANK, + "Set-Cookie: " + httpCookie.printValues() + BLANK, "Content-Type: " + contentType + BLANK, "Content-Length: " + body.getBytes().length + BLANK, "", @@ -100,7 +98,7 @@ private String makeGeneralResponse( } public void addCookie(final HttpCookie cookie) { - this.httpResponseHeader.setCookie(cookie); + this.httpCookie = cookie; } public void sendRedirect(final String path) { diff --git a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java b/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java deleted file mode 100644 index 96192f9e57..0000000000 --- a/tomcat/src/main/java/org/apache/coyote/http11/response/HttpResponseHeader.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.apache.coyote.http11.response; - -import java.util.HashMap; -import java.util.Map; -import org.apache.coyote.http11.HttpCookie; - -public class HttpResponseHeader { - - private final Map headers = new HashMap<>(); - private HttpCookie cookie; - - public HttpResponseHeader() { - this.cookie = new HttpCookie(new HashMap<>()); - } - - public boolean hasCookie() { - return cookie.isNotEmpty(); - } - - public void setCookie(final HttpCookie cookie) { - this.cookie = cookie; - } - - public HttpCookie getCookie() { - return cookie; - } -}