Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[톰캣 구현하기 - 1, 2단계] 다즐(최우창) 미션 제출합니다. #316

Merged
merged 13 commits into from
Sep 5, 2023
Merged
49 changes: 49 additions & 0 deletions tomcat/src/main/java/org/apache/coyote/handle/ViewResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.apache.coyote.handle;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import org.apache.coyote.common.ContentType;
import org.apache.coyote.common.HttpStatus;
import org.apache.coyote.response.HttpResponse;

public class ViewResolver {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와우 이렇게 빠르게 ViewResolver를 도입해 해결하다니.. 멋집니다~! 보면 코드 수정도 많고 구조 변화도 있었던 것 같은데,, 고생했어요 ~!!


private static final String STATIC_DIRECTORY = "static";
private static final String SLASH = File.separator;
private static final String NOT_FOUND = "404.html";
private static final ViewResolver VIEW_RESOLVER = new ViewResolver();

private ViewResolver() {
}

public static ViewResolver getInstance() {
return VIEW_RESOLVER;
}

public void renderPage(final HttpResponse httpResponse, final HttpStatus httpStatus, final String page)
throws IOException {
try {
httpResponse.setStatus(httpStatus);
httpResponse.setContentType(getContentType(page));
httpResponse.setContent(getBody(page));
} catch (NullPointerException e) {
httpResponse.setStatus(HttpStatus.NOT_FOUND);
httpResponse.setContentType(ContentType.TEXT_HTML.getType());
httpResponse.setContent(getBody(NOT_FOUND));
}
}

private String getContentType(final String page) {
final String extension = page.substring(page.lastIndexOf(".") + 1);
String contentType = ContentType.getTypeFrom(extension);
return contentType == null ? ContentType.APPLICATION_OCTET_STREAM.getType() : contentType;
}

private String getBody(final String page) throws IOException {
final URL resource = ClassLoader.getSystemClassLoader().getResource(STATIC_DIRECTORY + SLASH + page);
final File file = new File(resource.getFile());
return new String(Files.readAllBytes(file.toPath()));
}
}
Original file line number Diff line number Diff line change
@@ -1,44 +1,15 @@
package org.apache.coyote.handle.handler;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import org.apache.coyote.common.ContentType;
import org.apache.coyote.common.HttpStatus;
import org.apache.coyote.request.Accept;
import org.apache.coyote.request.HttpRequest;
import org.apache.coyote.response.HttpResponse;

public class FileHandler implements Handler {

@Override
public void doGet(final HttpRequest httpRequest, final HttpResponse httpResponse) throws IOException {
final String contentType = getContentType(httpRequest);
final String body = getBody(httpRequest);

httpResponse.setStatus(HttpStatus.OK);
httpResponse.setContentType(contentType);
httpResponse.setContent(body);
}

private String getContentType(final HttpRequest httpRequest) {
final List<Accept> accepts = httpRequest.getAccepts();
String contentType = ContentType.getTypeFrom(accepts);
if (contentType == null) {
final String uriPath = httpRequest.getUriPath();
final String extension = uriPath.substring(uriPath.lastIndexOf(".") + 1);
contentType = ContentType.getTypeFrom(extension);
}
return contentType;
}

private String getBody(final HttpRequest httpRequest) throws IOException {
final String uriPath = httpRequest.getUriPath();
final URL resource = ClassLoader.getSystemClassLoader().getResource(STATIC_DIRECTORY + uriPath);
final File file = new File(resource.getFile());
return new String(Files.readAllBytes(file.toPath()));
viewResolver.renderPage(httpResponse, HttpStatus.OK, httpRequest.getUriPath().substring(1));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package org.apache.coyote.handle.handler;

import java.io.IOException;
import org.apache.coyote.handle.ViewResolver;
import org.apache.coyote.request.HttpRequest;
import org.apache.coyote.response.HttpResponse;

public interface Handler {

String STATIC_DIRECTORY = "static";
ViewResolver viewResolver = ViewResolver.getInstance();

void doGet(final HttpRequest httpRequest, final HttpResponse httpResponse) throws IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -22,9 +20,10 @@
public class LoginHandler implements Handler {

private static final Logger log = LoggerFactory.getLogger(LoginHandler.class);
private static final String LOGIN_PAGE = "/login.html";
private static final String LOGIN_SUCCESS_PAGE = "/index.html";
private static final String LOGIN_FAIL_PAGE = "/401.html";
private static final String SLASH = File.separator;
private static final String LOGIN_PAGE = "login.html";
private static final String LOGIN_SUCCESS_PAGE = "index.html";
private static final String LOGIN_FAIL_PAGE = "401.html";
private static final String ACCOUNT = "account";
private static final String PASSWORD = "password";
private static final String JSESSIONID = "JSESSIONID";
Expand All @@ -34,10 +33,11 @@ public void doGet(final HttpRequest httpRequest, final HttpResponse httpResponse
final HttpCookie httpCookie = httpRequest.getCookie();
final String cookie = httpCookie.getCookie(JSESSIONID);
if (cookie == null || SessionManager.findSession(cookie) == null) {
renderPage(httpResponse, HttpStatus.OK, LOGIN_PAGE);
viewResolver.renderPage(httpResponse, HttpStatus.OK, LOGIN_PAGE);
return;
}
renderPage(httpResponse, HttpStatus.FOUND, LOGIN_SUCCESS_PAGE);
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + LOGIN_SUCCESS_PAGE);
}

@Override
Expand All @@ -47,45 +47,27 @@ public void doPost(final HttpRequest httpRequest, final HttpResponse httpRespons
final String password = body.get(PASSWORD);
if (account == null || password == null) {
log.warn("Account Or Password Not Exist");
renderPage(httpResponse, HttpStatus.FOUND, LOGIN_FAIL_PAGE);
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + LOGIN_FAIL_PAGE);
return;
}

final Optional<User> findUser = InMemoryUserRepository.findByAccount(account);
if (findUser.isEmpty() || !findUser.get().checkPassword(password)) {
log.warn("Login Fail");
renderPage(httpResponse, HttpStatus.FOUND, LOGIN_FAIL_PAGE);
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + LOGIN_FAIL_PAGE);
return;
}
loginSuccess(httpResponse, findUser.get());
}

private void loginSuccess(final HttpResponse httpResponse, final User user) throws IOException {
private void loginSuccess(final HttpResponse httpResponse, final User user) {
final Session session = new Session(UUID.randomUUID().toString());
session.setAttribute("user", user);
SessionManager.add(session);
httpResponse.addCookie(JSESSIONID, session.getId());
renderPage(httpResponse, HttpStatus.FOUND, LOGIN_SUCCESS_PAGE);
}

private void renderPage(
final HttpResponse httpResponse,
final HttpStatus httpStatus,
final String page
) throws IOException {
final String body = getBody(page);
httpResponse.setStatus(httpStatus);
if (httpStatus == HttpStatus.FOUND) {
httpResponse.setLocation(page);
} else {
httpResponse.setContentType(ContentType.TEXT_HTML.getType());
httpResponse.setContent(body);
}
}

private String getBody(final String page) throws IOException {
final URL resource = ClassLoader.getSystemClassLoader().getResource(STATIC_DIRECTORY + page);
final File file = new File(resource.getFile());
return new String(Files.readAllBytes(file.toPath()));
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + LOGIN_SUCCESS_PAGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -21,17 +19,18 @@
public class RegisterHandler implements Handler {

private static final Logger log = LoggerFactory.getLogger(RegisterHandler.class);
private static final String REGISTER_PAGE = "/register.html";
private static final String REGISTER_SUCCESS_PAGE = "/index.html";
private static final String REGISTER_FAIL_PAGE = "/400.html";
private static final String SLASH = File.separator;
private static final String REGISTER_PAGE = "register.html";
private static final String REGISTER_SUCCESS_PAGE = "index.html";
private static final String REGISTER_FAIL_PAGE = "400.html";
private static final String ACCOUNT = "account";
private static final String PASSWORD = "password";
private static final String EMAIL = "email";
private static final String JSESSIONID = "JSESSIONID";

@Override
public void doGet(final HttpRequest httpRequest, final HttpResponse httpResponse) throws IOException {
renderPage(httpResponse, HttpStatus.OK, REGISTER_PAGE);
viewResolver.renderPage(httpResponse, HttpStatus.OK, REGISTER_PAGE);
}

@Override
Expand All @@ -42,47 +41,29 @@ public void doPost(final HttpRequest httpRequest, final HttpResponse httpRespons
final String email = body.get(EMAIL);
if (account == null || password == null || email == null) {
log.warn("Account Or Password Or Email Not Exist");
renderPage(httpResponse, HttpStatus.FOUND, REGISTER_FAIL_PAGE);
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + REGISTER_FAIL_PAGE);
return;
}

final Optional<User> findUser = InMemoryUserRepository.findByAccount(body.get(ACCOUNT));
if (findUser.isPresent()) {
log.warn("Registered Account");
renderPage(httpResponse, HttpStatus.FOUND, REGISTER_FAIL_PAGE);
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + REGISTER_FAIL_PAGE);
return;
}
final User user = new User(account, password, email);
registerSuccess(httpResponse, user);
}

private void registerSuccess(final HttpResponse httpResponse, final User user) throws IOException {
private void registerSuccess(final HttpResponse httpResponse, final User user) {
InMemoryUserRepository.save(user);
final Session session = new Session(UUID.randomUUID().toString());
session.setAttribute("user", user);
SessionManager.add(session);
httpResponse.addCookie(JSESSIONID, session.getId());
renderPage(httpResponse, HttpStatus.FOUND, REGISTER_SUCCESS_PAGE);
}

private void renderPage(
final HttpResponse httpResponse,
final HttpStatus httpStatus,
final String page
) throws IOException {
final String body = getBody(page);
httpResponse.setStatus(httpStatus);
if (httpStatus == HttpStatus.FOUND) {
httpResponse.setLocation(page);
} else {
httpResponse.setContentType(ContentType.TEXT_HTML.getType());
httpResponse.setContent(body);
}
}

private String getBody(final String page) throws IOException {
final URL resource = ClassLoader.getSystemClassLoader().getResource(STATIC_DIRECTORY + page);
final File file = new File(resource.getFile());
return new String(Files.readAllBytes(file.toPath()));
httpResponse.setStatus(HttpStatus.FOUND);
httpResponse.setLocation(SLASH + REGISTER_SUCCESS_PAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.apache.coyote.handle;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import org.apache.coyote.common.HttpStatus;
import org.apache.coyote.common.HttpVersion;
import org.apache.coyote.response.HttpResponse;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class ViewResolverTest {

@Nested
class 페이지_렌더링 {

@Test
void 존재하는_페이지라면_해당_페이지를_렌더링한다() throws Exception {
final HttpResponse httpResponse = new HttpResponse(HttpVersion.HTTP_11);
final HttpStatus httpStatus = HttpStatus.OK;
final String page = "index.html";

final ViewResolver viewResolver = ViewResolver.getInstance();
viewResolver.renderPage(httpResponse, httpStatus, page);

final URL resource = getClass().getClassLoader().getResource("static/index.html");
final String expected = String.join("\r\n",
"HTTP/1.1 200 OK ",
"Content-Type: text/html;charset=utf-8 ",
"Content-Length: 5564 ",
"",
new String(Files.readAllBytes(new File(resource.getFile()).toPath()))
);
assertThat(httpResponse).hasToString(expected);
}

@Test
void 존재하지_않는_페이지라면_404_페이지를_렌더링한다() throws Exception {
final HttpResponse httpResponse = new HttpResponse(HttpVersion.HTTP_11);
final HttpStatus httpStatus = HttpStatus.OK;
final String page = "hello.html";

final ViewResolver viewResolver = ViewResolver.getInstance();
viewResolver.renderPage(httpResponse, httpStatus, page);

final URL resource = getClass().getClassLoader().getResource("static/404.html");
final String expected = String.join("\r\n",
"HTTP/1.1 404 Not Found ",
"Content-Type: text/html;charset=utf-8 ",
"Content-Length: 2426 ",
"",
new String(Files.readAllBytes(new File(resource.getFile()).toPath()))
);
assertThat(httpResponse).hasToString(expected);
}
}
}