-
Notifications
You must be signed in to change notification settings - Fork 309
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단계] 디노(신종화) 미션 제출합니다. #441
Changes from 7 commits
fb1a684
c8b8685
6faa7a2
656a8e3
14cea64
e6454d2
e88da3c
46d938a
5f41b28
7566751
a0278bd
304fe4d
c5d20eb
51ca60f
f53d16f
d3994c8
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,19 @@ | ||
package nextstep.jwp; | ||
|
||
import java.io.IOException; | ||
import org.apache.catalina.AbstractController; | ||
import org.apache.coyote.http11.FileExtractor; | ||
import org.apache.coyote.http11.HttpStatusCode; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
import org.apache.coyote.http11.response.ResponseBody; | ||
|
||
public class DefaultController extends AbstractController { | ||
|
||
@Override | ||
protected HttpResponse doGet(final HttpRequest request) throws IOException { | ||
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.
저는 컨트롤러 로직에 따라서 Response가 달라지기 때문에 일단 저의 생각은 이런데, 이런 의미로 질문하신게 아닐까요?? |
||
final String resource = request.getRequestPath().getResource(); | ||
final ResponseBody responseBody = FileExtractor.extractFile(resource); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package nextstep.jwp; | ||
|
||
import java.io.IOException; | ||
import org.apache.catalina.AbstractController; | ||
import org.apache.coyote.http11.ExtensionType; | ||
import org.apache.coyote.http11.HttpStatusCode; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
import org.apache.coyote.http11.response.ResponseBody; | ||
|
||
public class HomeController extends AbstractController { | ||
|
||
private static final String DEFAULT_CONTENT = "Hello world!"; | ||
|
||
@Override | ||
protected HttpResponse doGet(final HttpRequest request) throws IOException { | ||
final ResponseBody responseBody = ResponseBody.of(ExtensionType.HTML.getExtension(), DEFAULT_CONTENT); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package nextstep.jwp; | ||
|
||
import static org.reflections.Reflections.log; | ||
|
||
import java.io.IOException; | ||
import java.util.UUID; | ||
import nextstep.jwp.db.InMemoryUserRepository; | ||
import nextstep.jwp.exception.LoginException; | ||
import nextstep.jwp.model.User; | ||
import org.apache.catalina.AbstractController; | ||
import org.apache.catalina.SessionManager; | ||
import org.apache.coyote.http11.FileExtractor; | ||
import org.apache.coyote.http11.HttpCookie; | ||
import org.apache.coyote.http11.HttpStatusCode; | ||
import org.apache.coyote.http11.Session; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
import org.apache.coyote.http11.response.ResponseBody; | ||
|
||
public class LoginController extends AbstractController { | ||
|
||
private static final SessionManager sessionManager = new SessionManager(); | ||
|
||
private static final String JSESSIONID = "JSESSIONID"; | ||
private static final String INDEX = "/index"; | ||
private static final String ACCOUNT = "account"; | ||
private static final String PASSWORD = "password"; | ||
private static final String COOKIE = "Cookie"; | ||
private static final String USER = "user"; | ||
private static final String UNAUTHORIZED = "/401"; | ||
|
||
@Override | ||
protected HttpResponse doPost(final HttpRequest request) throws IOException { | ||
try { | ||
final String userName = request.getRequestBody().get(ACCOUNT); | ||
final String password = request.getRequestBody().get(PASSWORD); | ||
|
||
final User user = InMemoryUserRepository.findByAccount(userName) | ||
.orElseThrow(LoginException::new); | ||
|
||
if (user.checkPassword(password)) { | ||
log.info("user : " + user); | ||
final HttpCookie cookie = HttpCookie.from(request.getRequestHeaders().geHeaderValue(COOKIE)); | ||
checkSession(user, cookie); | ||
final ResponseBody responseBody = FileExtractor.extractFile(INDEX); | ||
final HttpResponse httpResponse = HttpResponse.of(HttpStatusCode.FOUND, responseBody); | ||
httpResponse.addCookie(cookie); | ||
return httpResponse; | ||
} | ||
throw new LoginException(); | ||
} catch (LoginException exception) { | ||
final ResponseBody responseBody = FileExtractor.extractFile(UNAUTHORIZED); | ||
return HttpResponse.of(HttpStatusCode.UNAUTHORIZED, responseBody); | ||
} | ||
} | ||
|
||
private void checkSession(final User user, final HttpCookie cookie) { | ||
if (!cookie.contains(JSESSIONID)) { | ||
final Session session = new Session(UUID.randomUUID().toString()); | ||
session.setAttribute(USER, user); | ||
sessionManager.add(session); | ||
cookie.setCookie(JSESSIONID, session.getId()); | ||
} | ||
} | ||
|
||
@Override | ||
protected HttpResponse doGet(final HttpRequest request) throws IOException { | ||
final HttpCookie cookie = HttpCookie.from(request.getRequestHeaders().geHeaderValue(COOKIE)); | ||
final String requestResource = request.getRequestPath().getResource(); | ||
|
||
if (cookie.contains(JSESSIONID)) { | ||
final ResponseBody responseBody = FileExtractor.extractFile(INDEX); | ||
final HttpResponse httpResponse = HttpResponse.of(HttpStatusCode.FOUND, responseBody); | ||
httpResponse.addCookie(cookie); | ||
return httpResponse; | ||
} | ||
final ResponseBody responseBody = FileExtractor.extractFile(requestResource); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package nextstep.jwp; | ||
|
||
import java.io.IOException; | ||
import java.util.Map; | ||
import nextstep.jwp.db.InMemoryUserRepository; | ||
import nextstep.jwp.model.User; | ||
import org.apache.catalina.AbstractController; | ||
import org.apache.coyote.http11.FileExtractor; | ||
import org.apache.coyote.http11.HttpStatusCode; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
import org.apache.coyote.http11.response.ResponseBody; | ||
|
||
public class RegisterController extends AbstractController { | ||
|
||
private static final String BAD_REQUEST = "/400"; | ||
private static final String CONFLICT = "/409"; | ||
private static final String INDEX = "/index"; | ||
private static final String REGISTER = "/register"; | ||
private static final String ACCOUNT = "account"; | ||
private static final String PASSWORD = "password"; | ||
private static final String EMAIL = "email"; | ||
|
||
@Override | ||
protected HttpResponse doPost(final HttpRequest request) throws IOException { | ||
final Map<String, String> requestBody = request.getRequestBody(); | ||
|
||
final String account = requestBody.get(ACCOUNT); | ||
final String password = requestBody.get(PASSWORD); | ||
final String email = requestBody.get(EMAIL); | ||
|
||
if (account.isBlank() || password.isBlank() || email.isBlank()) { | ||
final ResponseBody responseBody = FileExtractor.extractFile(BAD_REQUEST); | ||
return HttpResponse.of(HttpStatusCode.BAD_REQUEST, responseBody); | ||
} | ||
|
||
if (InMemoryUserRepository.checkExistingId(account)) { | ||
final ResponseBody responseBody = FileExtractor.extractFile(CONFLICT); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
final User user = new User(account, password, email); | ||
InMemoryUserRepository.save(user); | ||
final ResponseBody responseBody = FileExtractor.extractFile(INDEX); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
|
||
@Override | ||
protected HttpResponse doGet(final HttpRequest request) throws IOException { | ||
final ResponseBody responseBody = FileExtractor.extractFile(REGISTER); | ||
return HttpResponse.of(HttpStatusCode.OK, responseBody); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,19 +3,23 @@ | |
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
import nextstep.jwp.model.User; | ||
|
||
public class InMemoryUserRepository { | ||
|
||
private static final AtomicLong id = new AtomicLong(1L); | ||
|
||
private static final Map<String, User> database = new ConcurrentHashMap<>(); | ||
|
||
static { | ||
final User user = new User(1L, "gugu", "password", "[email protected]"); | ||
final User user = new User(id.getAndIncrement(), "gugu", "password", "[email protected]"); | ||
database.put(user.getAccount(), user); | ||
} | ||
|
||
public static void save(User user) { | ||
database.put(user.getAccount(), user); | ||
final User userWithId = new User(id.getAndIncrement(), user.getAccount(), user.getPassword(), user.getEmail()); | ||
database.put(user.getAccount(), userWithId); | ||
} | ||
|
||
public static Optional<User> findByAccount(String account) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.apache.catalina; | ||
|
||
import java.io.IOException; | ||
import org.apache.coyote.http11.request.HttpMethod; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
|
||
public class AbstractController implements Controller { | ||
|
||
@Override | ||
public HttpResponse service(final HttpRequest request) throws IOException { | ||
if (request.getHttpMethod().equals(HttpMethod.GET)) { | ||
return doGet(request); | ||
} | ||
if (request.getHttpMethod().equals(HttpMethod.POST)) { | ||
return doPost(request); | ||
} | ||
throw new UnsupportedOperationException(); | ||
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. 제가 제안드린 방향을 고려해서 해주신 것 같아요!! 👍🏻 그래도 잘 고려해주셔서 감사합니다 ㅎㅎ |
||
} | ||
|
||
|
||
protected HttpResponse doPost(final HttpRequest request) throws IOException { | ||
return null; | ||
} | ||
|
||
protected HttpResponse doGet(final HttpRequest request) throws IOException { | ||
return null; | ||
} | ||
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해서 사용하고 있는데, 그리고 POST를 사용하지 않는 컨트롤러에서 POST 요청이 온다면 실제는 어떻게 동작하는지 생각해보고 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. 아 너무 좋습니다. 7566751 반영 완! |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.apache.catalina; | ||
|
||
import java.io.IOException; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
import org.apache.coyote.http11.response.HttpResponse; | ||
|
||
public interface Controller { | ||
|
||
HttpResponse service(final HttpRequest request) throws IOException; | ||
} | ||
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. 넵넵 저도 확인하고 구조 변경했습니다.! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.apache.catalina; | ||
|
||
import nextstep.jwp.DefaultController; | ||
import nextstep.jwp.HomeController; | ||
import nextstep.jwp.LoginController; | ||
import nextstep.jwp.RegisterController; | ||
import org.apache.coyote.http11.request.HttpRequest; | ||
|
||
public class RequestMapping { | ||
|
||
public Controller getController(final HttpRequest request) { | ||
final String resource = request.getRequestPath().getResource(); | ||
|
||
if (resource.equals("/")) { | ||
return new HomeController(); | ||
} | ||
if (resource.equals("/login")) { | ||
return new LoginController(); | ||
} | ||
if (resource.equals("/register")) { | ||
return new RegisterController(); | ||
} | ||
|
||
return new DefaultController(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,19 @@ | ||
package org.apache.coyote.http11; | ||
package org.apache.catalina; | ||
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.
이 부분에 대해서 Apache의 coyote, catalina 패키지 중에 어떤 패키지에 둘지 고민하신 것 같아요! 찾아보니 톰캣의 catalina에서 Session 관리를 한다고 하더라구요! 실제 코드에서 구구가 만든 Manager를 구현하고 있는데 catalina 패키지에 만들어 놓으셨네요! |
||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import org.apache.catalina.Manager; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import org.apache.coyote.http11.Session; | ||
|
||
public class SessionManager implements Manager{ | ||
public class SessionManager implements Manager { | ||
|
||
private static final Map<String, Session> SESSIONS = new HashMap<>(); | ||
private static final Map<String, Session> SESSIONS = new ConcurrentHashMap<>(); | ||
|
||
@Override | ||
public void add(final Session session) { | ||
SESSIONS.put(session.getId(), session); | ||
} | ||
|
||
@Override | ||
public Session findSession(final String id) { | ||
return SESSIONS.get(id); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
package org.apache.coyote.http11; | ||
|
||
import java.util.Arrays; | ||
import org.apache.coyote.http11.request.RequestLine; | ||
import nextstep.jwp.exception.NotAllowedMethodException; | ||
|
||
public enum HttpExtensionType { | ||
public enum ExtensionType { | ||
|
||
HTML(".html", "text/html;charset=utf-8"), | ||
CSS(".css", "text/css"), | ||
|
@@ -14,23 +14,16 @@ public enum HttpExtensionType { | |
private final String extension; | ||
private final String contentType; | ||
|
||
HttpExtensionType(final String extension, final String contentType) { | ||
ExtensionType(final String extension, final String contentType) { | ||
this.extension = extension; | ||
this.contentType = contentType; | ||
} | ||
|
||
public static HttpExtensionType from(final String extension) { | ||
public static ExtensionType from(final String extension) { | ||
return Arrays.stream(values()) | ||
.filter(it -> extension.contains(it.extension)) | ||
.findAny() | ||
.orElse(HTML); | ||
} | ||
|
||
public static HttpExtensionType from(final RequestLine requestLine) { | ||
return Arrays.stream(values()) | ||
.filter(it -> requestLine.hasFileExtension(it.getExtension())) | ||
.findAny() | ||
.orElse(HTML); | ||
.orElseThrow(NotAllowedMethodException::new); | ||
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. 여기서 Extension을 찾지 못하면 NotAllowedMethodException을 발생시키고 있는데, 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. NotAllowedExtenstionException 만들어 반환하도록 변경했습니다! |
||
} | ||
|
||
public String getExtension() { | ||
|
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.
이 부분은 현재 어디가 마음에 안 드시는 걸까요??
저는 의존성 방향은 생각조차 못 했는데,, 대단하십니다!
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.
패키지 간 양방향 의존이 일어나지 않는 방향으로 구현하고 싶었습니다!
51ca60f