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

[톰캣 구현하기 - 3, 4단계] 가비(이준희) 미션 제출합니다. #434

Merged
merged 29 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f6acd4d
refactor: 변수명 변경 및 매직넘버 추출
iamjooon2 Sep 6, 2023
1fa9495
refactor: RequestLine 객체 추출
iamjooon2 Sep 6, 2023
1f7285a
refactor: RequestLine 객체 추출
iamjooon2 Sep 6, 2023
33308d6
refactor: Headers 객체 추출
iamjooon2 Sep 7, 2023
d21d069
refactor: 자료구조 생성 시점을 생성자로 이동
iamjooon2 Sep 7, 2023
907c901
refactor: Response의 첫번째 라인인 StatusLine 객체 추출
iamjooon2 Sep 8, 2023
4733ff1
refactor: HttpResponse 내 Headers 객체 삽입
iamjooon2 Sep 8, 2023
e134f63
refactor: Handler를 Controller들로 분리
iamjooon2 Sep 9, 2023
b737ed4
refactor: LoginController 리팩터링
iamjooon2 Sep 9, 2023
de3b002
refactor: RegisterController 리팩터링
iamjooon2 Sep 9, 2023
3029d5d
refactor: 메서드 추출
iamjooon2 Sep 9, 2023
e64b136
refactor: abstractController 적용
iamjooon2 Sep 9, 2023
4f7f9a1
refactor: ResponseView 메서드 추출 개선
iamjooon2 Sep 9, 2023
5d9b50a
refactor: 패키지 구조 변경
iamjooon2 Sep 9, 2023
6ae8dca
test: register 인수테스트 추가
iamjooon2 Sep 9, 2023
0deab4a
refactor: 자식 클래스에서 중복되는 분기절 제거
iamjooon2 Sep 9, 2023
36467c8
test: 학습 테스트
iamjooon2 Sep 9, 2023
554c236
feat : threadPool 설정
iamjooon2 Sep 9, 2023
c1c4bf6
feat: 동시성 보장을 위해 session을 ConcurrentHashMap으로 변경
iamjooon2 Sep 9, 2023
30afd5a
test: 학습 테스트
iamjooon2 Sep 9, 2023
876e87c
fix: 깨지는 테스트 수정
iamjooon2 Sep 9, 2023
8b1cb1e
chore: 패키지 구조 수정
iamjooon2 Sep 9, 2023
3231f0d
chore: 코드스멜 제거
iamjooon2 Sep 9, 2023
9893af2
chore: 사용하지 않는 메서드 제거
iamjooon2 Sep 9, 2023
0b90504
refactor: 사용하지 않는 메서드 제거
iamjooon2 Sep 9, 2023
8c06beb
refactor: 사용하지 않는 메서드 제거
iamjooon2 Sep 9, 2023
71b256b
refactor: 연달아 사용하는 getter 제거
iamjooon2 Sep 9, 2023
49af628
chore: static import 추가
iamjooon2 Sep 9, 2023
d33e781
chore: 사용하지 않는 import 제거
iamjooon2 Sep 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions study/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ handlebars:

server:
tomcat:
accept-count: 1
max-connections: 1
accept-count: 2 # 쓰레드가 사용중일 때, 받은 요청이 대기하는 큐의 최대값
max-connections: 2 # 서버가 유지할 수 있는 최대 커넥션 수
threads:
max: 2
max: 2 # 실행가능 쓰레드 수
compression:
enabled: true
min-response-size : 10
2 changes: 1 addition & 1 deletion study/src/test/java/thread/stage0/SynchronizationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private static final class SynchronizedMethods {

private int sum = 0;

public void calculate() {
public synchronized void calculate() {
setSum(getSum() + 1);
}

Expand Down
6 changes: 3 additions & 3 deletions study/src/test/java/thread/stage0/ThreadPoolsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ void testNewFixedThreadPool() {
executor.submit(logWithSleep("hello fixed thread pools"));

// 올바른 값으로 바꿔서 테스트를 통과시키자.
final int expectedPoolSize = 0;
final int expectedQueueSize = 0;
final int expectedPoolSize = 2;
final int expectedQueueSize = 1;

assertThat(expectedPoolSize).isEqualTo(executor.getPoolSize());
assertThat(expectedQueueSize).isEqualTo(executor.getQueue().size());
Expand All @@ -46,7 +46,7 @@ void testNewCachedThreadPool() {
executor.submit(logWithSleep("hello cached thread pools"));

// 올바른 값으로 바꿔서 테스트를 통과시키자.
final int expectedPoolSize = 0;
final int expectedPoolSize = 3;
final int expectedQueueSize = 0;

assertThat(expectedPoolSize).isEqualTo(executor.getPoolSize());
Expand Down
141 changes: 0 additions & 141 deletions tomcat/src/main/java/nextstep/jwp/Handler.java

This file was deleted.

29 changes: 29 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/controller/FrontController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nextstep.jwp.controller;

import java.util.HashMap;
import java.util.Map;

import org.apache.catalina.controller.AbstractController;
import org.apache.catalina.controller.Controller;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public class FrontController extends AbstractController {

private static final Map<String, Controller> URIS = new HashMap<>();

static {
URIS.put("/", new HomeController());
URIS.put("/login", new LoginController());
URIS.put("/register", new RegisterController());
URIS.put("/index", new IndexController());
}

Choose a reason for hiding this comment

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

초기화 블럭 👍


@Override
public void service(HttpRequest request, HttpResponse response) {
String uri = request.getResourceUri();
Controller controller = URIS.getOrDefault(uri, new ResourceController());
controller.service(request, response);
}

}
26 changes: 26 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nextstep.jwp.controller;

import org.apache.catalina.controller.AbstractController;
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.response.ResponseBody;
import org.apache.coyote.http11.response.StatusLine;

import static org.apache.coyote.http11.request.ContentType.HTML;


public class HomeController extends AbstractController {
private static final String DEFAULT_MESSAGE = "Hello world!";

@Override
protected void doGet(HttpRequest request, HttpResponse response) {
StatusLine statusLine = new StatusLine(request.getProtocolVersion(), HttpStatus.OK);
response
.statusLine(statusLine)
.contentType(HTML.getValue())
.contentLength(DEFAULT_MESSAGE.getBytes().length)
.responseBody(new ResponseBody(DEFAULT_MESSAGE));
}

}
27 changes: 27 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/controller/IndexController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package nextstep.jwp.controller;

import org.apache.catalina.controller.AbstractController;
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.response.ResponseBody;
import org.apache.coyote.http11.response.StatusLine;
import org.apache.coyote.http11.util.FileReader;

import static org.apache.coyote.http11.request.ContentType.HTML;

public class IndexController extends AbstractController {
private static final String RESOURCE = "/index.html";

@Override
protected void doGet(HttpRequest request, HttpResponse response) {
ResponseBody responseBody = new ResponseBody(FileReader.read(RESOURCE));

Choose a reason for hiding this comment

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

FileReader 좋은데요~!? 👍

StatusLine statusLine = new StatusLine(request.getProtocolVersion(), HttpStatus.OK);
response
.statusLine(statusLine)
.contentType(HTML.getValue())
.contentLength(responseBody.getValue().getBytes().length)

Choose a reason for hiding this comment

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

responseBody.getValue().getBytes().length 이 부분 중복이 많이 생기는데
ResponseBody에 메소드로 만들어도 괜찮을거 같습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

아이고 이부분을 놓쳤었네요!

.responseBody(responseBody);
}

}
115 changes: 115 additions & 0 deletions tomcat/src/main/java/nextstep/jwp/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package nextstep.jwp.controller;

import java.util.Optional;
import java.util.UUID;

import nextstep.jwp.db.InMemoryUserRepository;
import nextstep.jwp.model.User;
import org.apache.coyote.http11.common.HttpCookie;
import org.apache.catalina.controller.AbstractController;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.request.RequestBody;
import org.apache.coyote.http11.response.HttpResponse;
import org.apache.coyote.http11.response.HttpStatus;
import org.apache.coyote.http11.response.ResponseBody;
import org.apache.coyote.http11.response.StatusLine;
import org.apache.catalina.Session;
import org.apache.catalina.SessionManager;
import org.apache.coyote.http11.util.FileReader;

import static org.apache.coyote.http11.request.ContentType.HTML;

public class LoginController extends AbstractController {

private static final String URI = "/login.html";
private static final String UNAUTHORIZED = "/401.html";
private static final String REDIRECT_HOME_URI = "/index.html";

public static final SessionManager SESSION_MANAGER = new SessionManager();

@Override
protected void doGet(HttpRequest request, HttpResponse response) {
if (hasCookie(request)) {
redirectHome(request, response);
return;
}
showLoginPage(request, response);
}

private boolean hasCookie(HttpRequest httpRequest) {
HttpCookie cookie = HttpCookie.from(httpRequest.getHeaderValue("Cookie"));
return SESSION_MANAGER.findSession(cookie.getValue("JSESSIONID")) != null;
}

private void redirectHome(HttpRequest request, HttpResponse response) {
StatusLine statusLine = new StatusLine(request.getProtocolVersion(), HttpStatus.FOUND);
ResponseBody responseBody = new ResponseBody(FileReader.read(REDIRECT_HOME_URI));
response
.statusLine(statusLine)
.contentType(HTML.getValue())
.contentLength(responseBody.getValue().getBytes().length)
.redirect(REDIRECT_HOME_URI)
.responseBody(responseBody);
}

private void showLoginPage(HttpRequest request, HttpResponse response) {
ResponseBody responseBody = new ResponseBody(FileReader.read(URI));
StatusLine statusLine = new StatusLine(request.getProtocolVersion(), HttpStatus.OK);
response
.statusLine(statusLine)
.contentType(HTML.getValue())
.contentLength(responseBody.getValue().length())
.responseBody(responseBody);
}

@Override
protected void doPost(HttpRequest httpRequest, HttpResponse httpResponse) {
Optional<User> optionalUser = findUser(httpRequest);
if (optionalUser.isEmpty()) {
redirectUnauthorized(httpRequest, httpResponse);
return;
}

successLogin(httpRequest, httpResponse);
}

private Optional<User> findUser(HttpRequest request) {
RequestBody requestBody = request.getRequestBody();
String account = requestBody.getValueOf("account");
String password = requestBody.getValueOf("password");
return InMemoryUserRepository.findByAccount(account)
.stream()
.filter(it -> it.checkPassword(password))
.findFirst();
}

private void redirectUnauthorized(HttpRequest httpRequest, HttpResponse httpResponse) {
ResponseBody responseBody = new ResponseBody(FileReader.read(UNAUTHORIZED));
httpResponse
.statusLine(new StatusLine(httpRequest.getProtocolVersion(), HttpStatus.UNAUTHORIZED))
.contentType(HTML.getValue())
.contentLength(responseBody.getValue().getBytes().length)
.redirect(UNAUTHORIZED)
.responseBody(responseBody);
}

private void successLogin(HttpRequest httpRequest, HttpResponse httpResponse) {
String sessionId = addSession();

ResponseBody responseBody = new ResponseBody(FileReader.read(REDIRECT_HOME_URI));
httpResponse
.statusLine(new StatusLine(httpRequest.getProtocolVersion(), HttpStatus.FOUND))
.contentType(HTML.getValue())
.contentLength(responseBody.getValue().getBytes().length)
.setCookie(HttpCookie.jSessionId(sessionId))
.redirect(REDIRECT_HOME_URI)
.responseBody(responseBody);
}

private String addSession() {
String uuid = UUID.randomUUID().toString();
SESSION_MANAGER.add(new Session(uuid));
return uuid;
}

}
Loading