-
Notifications
You must be signed in to change notification settings - Fork 388
[4단계 - Tomcat 구현하기] 커비(이현지) 미션 제출합니다. #701
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
Changes from all commits
a008e41
4d1ddba
0c72d8b
0350a5b
a894c8b
f1a4282
5b0809f
fb880dd
cd1fc33
7259fc0
0f111af
b195f6a
4adda66
cfdbbca
301298b
cb46cc3
9f2d58e
6a82dec
467d2f1
79452b0
efa49b5
30371c1
b00cb3f
5f9029f
da88afd
a14e45e
065d170
12cbfa3
a1c6664
4abdea0
5c8196e
476b3ba
c4876a0
f3cdd17
3661793
ab53d08
73a926c
d37c00f
1253132
026883b
ca007e7
3548068
a4b2479
1399174
fc50aae
310a6b8
0d76eca
5dd2132
2b4b5ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package org.apache.catalina; | ||
|
|
||
| import org.apache.catalina.controller.Controller; | ||
| import org.apache.catalina.request.HttpRequest; | ||
| import org.apache.catalina.response.HttpResponse; | ||
| import org.apache.coyote.processor.ControllerMapper; | ||
|
|
||
| public class ServletContainer { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 매핑되어있는 서블릿(해당 구조에서는 컨트롤러가 서블릿 역할을 한다고 생각합니다)를 받아서, 서블릿의 실행 함수를 호출하는 역할을 하기에 서블릿 컨테이너의 역할이라고 생각했습니다~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 서블릿 컨테이너는 서블릿의 실행에 관한 전반적인 영역을 다룹니다. 단순히 매핑되어 있는 걸 호출하기만 하는게 아닌 서블릿의 생명주기도 다루고 멀티 스레드를 통해 리소스도 관리해요. 대표적으로 톰켓이 서블릿 컨테이너의 예시라고 볼 수 있어요 지금 해당 클래스를
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어떤 서블릿과 연결해줄지 결정하고, 서블릿의 service 함수를 호출하는 역할을 하기에 충분히 서블릿 컨테이너라고 이름 붙일 수 있다고 생각해요~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
그럼 질문이요! 현재 해당 클래스와
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 서블릿 컨테이너 = 톰캣은 아니라고 생각해요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
커비가 어떤 말을 하는 지는 이해했지만 그게 정말 맞는진 모르겠어요... 단순히 매핑되어 있는 걸 호출하는게 서블릿의 생명 주기를 관리하는 걸로는 받아들일 수 없을 것 같아요! |
||
|
|
||
| private final ControllerMapper controllerMapper; | ||
|
|
||
| public ServletContainer(ControllerMapper controllerMapper) { | ||
| this.controllerMapper = controllerMapper; | ||
| } | ||
|
|
||
| public void run(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
| Controller controller = controllerMapper.getController(httpRequest.getPath()); | ||
| controller.service(httpRequest, httpResponse); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package org.apache.catalina.controller; | ||
|
|
||
| import org.apache.catalina.http.HeaderName; | ||
| import org.apache.catalina.http.HttpMethod; | ||
| import org.apache.catalina.http.StatusCode; | ||
| import org.apache.catalina.request.HttpRequest; | ||
| import org.apache.catalina.response.HttpResponse; | ||
|
|
||
| public abstract class AbstractController implements Controller { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 질문입니다! 만약에
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 예외 처리가 필요하겠네요~ |
||
|
|
||
| @Override | ||
| public void service(HttpRequest request, HttpResponse response) { | ||
| try { | ||
| if (request.isMethod(HttpMethod.GET)) { | ||
| doGet(request, response); | ||
| return; | ||
| } | ||
| if (request.isMethod(HttpMethod.POST)) { | ||
| doPost(request, response); | ||
| return; | ||
| } | ||
| throw new IllegalArgumentException("HttpMethod not found"); | ||
| } catch (IllegalArgumentException e) { | ||
| response.setStatusCode(StatusCode.FOUND); | ||
| response.addHeader(HeaderName.LOCATION, "/500.html"); | ||
| } | ||
| } | ||
|
|
||
| protected void doPost(HttpRequest request, HttpResponse response) { | ||
| throw new IllegalArgumentException("HttpMethod unsupported"); | ||
| } | ||
|
|
||
| protected void doGet(HttpRequest request, HttpResponse response) { | ||
| throw new IllegalArgumentException("HttpMethod unsupported"); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package org.apache.catalina.controller; | ||
|
|
||
| import org.apache.catalina.request.HttpRequest; | ||
| import org.apache.catalina.response.HttpResponse; | ||
|
|
||
| public interface Controller { | ||
|
|
||
| void service(HttpRequest request, HttpResponse response); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package org.apache.catalina.controller; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import com.techcourse.model.User; | ||
| import java.util.Optional; | ||
| import org.apache.catalina.http.HeaderName; | ||
| import org.apache.catalina.http.StatusCode; | ||
| import org.apache.catalina.manager.SessionManager; | ||
| import org.apache.catalina.request.HttpRequest; | ||
| import org.apache.catalina.response.HttpResponse; | ||
|
|
||
| public class LoginController extends AbstractController { | ||
|
|
||
| private final SessionManager sessionManager; | ||
|
|
||
| public LoginController() { | ||
| this.sessionManager = SessionManager.getInstance(); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doPost(HttpRequest request, HttpResponse response) { | ||
| String account = request.getBodyParam("account"); | ||
| String password = request.getBodyParam("password"); | ||
|
Comment on lines
+22
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 만약
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. null을 반환합니다~ 호출하는 곳에서는 Optional.empty()을 반환하게 됩니다~ |
||
| Optional<User> user = InMemoryUserRepository.findByAccount(account); | ||
| if (!isMember(user, password)) { | ||
| response.setStatusCode(StatusCode.FOUND); | ||
| response.addHeader(HeaderName.LOCATION, "/401.html"); | ||
|
|
||
| } | ||
| if (isMember(user, password)) { | ||
| response.setStatusCode(StatusCode.FOUND); | ||
| response.addHeader(HeaderName.LOCATION, "/index.html"); | ||
| login(response, user.get()); | ||
| } | ||
| } | ||
|
|
||
| private boolean isMember(Optional<User> user, String password) { | ||
| return user.isPresent() && user.get().checkPassword(password); | ||
| } | ||
|
|
||
| private void login(HttpResponse response, User user) { | ||
| String sessionId = sessionManager.generateSession(user); | ||
| response.addSession(sessionId); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doGet(HttpRequest request, HttpResponse response) { | ||
| if (hasLogined(request)) { | ||
| response.setStatusCode(StatusCode.FOUND); | ||
| response.addHeader(HeaderName.LOCATION, "/index.html"); | ||
| } | ||
| if (!hasLogined(request)) { | ||
| response.setStatusCode(StatusCode.OK); | ||
| response.setBody("/login.html"); | ||
| } | ||
| } | ||
|
|
||
| private boolean hasLogined(HttpRequest request) { | ||
| return request.hasSession() && sessionManager.isSessionExist(request.getSessionId()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,19 @@ | ||
| package org.apache.coyote.controller; | ||
| package org.apache.catalina.controller; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import com.techcourse.model.User; | ||
| import org.apache.coyote.http.HeaderName; | ||
| import org.apache.coyote.http.StatusCode; | ||
| import org.apache.coyote.request.HttpRequest; | ||
| import org.apache.coyote.request.RequestBody; | ||
| import org.apache.coyote.response.HttpResponse; | ||
| import org.apache.catalina.http.HeaderName; | ||
| import org.apache.catalina.http.StatusCode; | ||
| import org.apache.catalina.request.HttpRequest; | ||
| import org.apache.catalina.response.HttpResponse; | ||
|
|
||
| public class RegisterController extends AbstractController { | ||
|
|
||
| @Override | ||
| protected void doPost(HttpRequest request, HttpResponse response) { | ||
| RequestBody requestBody = request.getBody(); | ||
| String account = requestBody.get("account"); | ||
| String password = requestBody.get("password"); | ||
| String email = requestBody.get("email"); | ||
| String account = request.getBodyParam("account"); | ||
| String password = request.getBodyParam("password"); | ||
| String email = request.getBodyParam("email"); | ||
|
Comment on lines
+14
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 예외 처리를 추가해주었습니다~ |
||
| InMemoryUserRepository.save(new User(account, password, email)); | ||
|
|
||
| response.setStatusCode(StatusCode.FOUND); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| package com.techcourse.exception; | ||
| package org.apache.catalina.exception; | ||
|
|
||
| public class UncheckedServletException extends RuntimeException { | ||
|
|
||
| public UncheckedServletException(Exception e) { | ||
| super(e); | ||
| super("UncheckedServletException occured", e); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package org.apache.catalina.http; | ||
|
|
||
| public enum HeaderName { | ||
| CONTENT_LENGTH("Content-Length"), | ||
| COOKIE("Cookie"), | ||
| CONTENT_TYPE("Content-Type"), | ||
| LOCATION("Location"), | ||
| SET_COOKIE("Set-Cookie"), | ||
|
|
||
| ; | ||
|
|
||
| private final String value; | ||
|
|
||
| HeaderName(String value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public String getValue() { | ||
| return value; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package org.apache.coyote.http; | ||
| package org.apache.catalina.http; | ||
|
|
||
| public enum HttpMethod { | ||
| GET, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package org.apache.coyote.http; | ||
| package org.apache.catalina.http; | ||
|
|
||
| public enum StatusCode { | ||
| OK(200, "OK"), | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
질문입니다!
☺️ ☺️
max-connections가 무엇을 의미하나요?왜 해당 값만 변경해도 테스트가 통과하나요?
accept-count는 테스트를 통과하는데 영향이 없나요?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
max-connections는 동시에 처리할 수 있는 최대 연결수를 의미해요!
테스트에서 200을 응답하면 올라가는 count가 2어야지 통과되게 되어있기때문에
정상 처리되어야하는 연결수를 2로 바꾸어주었습니다.
accept-count는 쓰레드로 할당은 못되었지만 대기할 수 있는 대기열의 크기를 의미하므로 영향을 주지 않습니다~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#687 (comment)
해당 테스트 코드를 보면 200을 반환하는 수가 2개면 통과하도록 되어 있어요. 그러면 대기하고 있다가 처리하면 통과하는 게 맞지 않을까요?
accept-count도 테스트에 영향을 미칠 수 있어요!레벨 4가 되서 많이 바쁜 건 알지만 좀 더 학습 테스트를 활용해 보는 건 어떨까요?☺️ ☺️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accept-count 숫자만큼 기다리다가 타임아웃이 발생하여서 max-commections 숫자만큼만 200을 응답하는군요~ 덕분에 알아갑니다!