-
Notifications
You must be signed in to change notification settings - Fork 388
[3단계 Tomcat 구현하기] 마크(김승현) 미션 제출합니다. #634
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
fed02f6
7e91356
4a259b5
fddfdc6
1d08960
90931d9
7319283
ba5010d
c037870
7d4f988
38a85a1
721b7e9
6f53481
db007a2
36c22be
add93cd
7f37783
7497b66
a633a27
34d44a6
837933e
1b6cb98
0125570
4109760
b3de68a
ac157e2
c3c3791
1ceb56d
47f234f
4d930c8
8162290
351db10
4185398
f733f4a
9dd3ef8
759226d
0b20278
82f6c1d
b28e846
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,17 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import org.apache.catalina.connector.HttpRequest; | ||
| import org.apache.catalina.connector.HttpResponse; | ||
| import com.techcourse.http.MimeType; | ||
| import java.io.IOException; | ||
| import org.apache.catalina.StaticResourceProvider; | ||
| import jakarta.servlet.http.AbstractController; | ||
|
|
||
| public class DashBoardController extends AbstractController { | ||
|
|
||
| @Override | ||
| protected void doGet(HttpRequest request, HttpResponse response) throws IOException { | ||
| response.setBody(StaticResourceProvider.getStaticResource("/index.html")) | ||
| .setContentType(MimeType.HTML.getMimeType()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import org.apache.catalina.session.Session; | ||
| import org.apache.catalina.session.SessionManager; | ||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import org.apache.catalina.connector.HttpRequest; | ||
| import org.apache.catalina.connector.HttpResponse; | ||
| import com.techcourse.http.MimeType; | ||
| import com.techcourse.model.User; | ||
| import java.io.IOException; | ||
| import java.util.UUID; | ||
| import org.apache.catalina.StaticResourceProvider; | ||
| import jakarta.servlet.http.AbstractController; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| public class LoginController extends AbstractController { | ||
|
|
||
| private static final Logger log = LoggerFactory.getLogger(LoginController.class); | ||
| private static final String JSESSIONID = "JSESSIONID"; | ||
| private static final String ACCOUNT = "account"; | ||
| private static final String PASSWORD = "password"; | ||
| private static final String INDEX_HTML_PATH = "/index.html"; | ||
| private static final String LOGIN_HTML_PATH = "/login.html"; | ||
| private static final String ERROR_401_HTML_PATH = "/401.html"; | ||
|
|
||
| private final InMemoryUserRepository inMemoryUserRepository = InMemoryUserRepository.getInstance(); | ||
| private final SessionManager sessionManager = SessionManager.getInstance(); | ||
|
|
||
| @Override | ||
| public void doGet(HttpRequest request, HttpResponse response) throws IOException { | ||
| if (request.getCookie(JSESSIONID) != null) { | ||
| response.found(INDEX_HTML_PATH); | ||
| return; | ||
| } | ||
|
|
||
| response.setBody(StaticResourceProvider.getStaticResource(LOGIN_HTML_PATH)) | ||
| .setContentType(MimeType.HTML.getMimeType()); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doPost(HttpRequest request, HttpResponse response) { | ||
| if (!request.hasParameter(ACCOUNT) || !request.hasParameter(PASSWORD)) { | ||
| response.found(ERROR_401_HTML_PATH); | ||
| return; | ||
| } | ||
|
|
||
| String account = request.getParameter(ACCOUNT); | ||
| String password = request.getParameter(PASSWORD); | ||
| inMemoryUserRepository.findByAccount(account).ifPresentOrElse( | ||
| user -> login(user, request, response, password), | ||
| () -> response.found(ERROR_401_HTML_PATH) | ||
| ); | ||
| } | ||
|
|
||
| private void login(User user, HttpRequest request, HttpResponse response, String password) { | ||
| if (!user.checkPassword(password)) { | ||
| response.found(ERROR_401_HTML_PATH); | ||
| return; | ||
| } | ||
|
|
||
| log.info("user : {}", user); | ||
|
|
||
| if (request.getCookie(JSESSIONID) == null) { | ||
| Session session = new Session(UUID.randomUUID().toString()); | ||
| session.setAttribute("user", user); | ||
| sessionManager.add(session); | ||
| response.setCookie(JSESSIONID, session.getId()) | ||
| .setHttpOnly(true); | ||
| } | ||
| response.found(INDEX_HTML_PATH); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import org.apache.catalina.connector.HttpRequest; | ||
| import org.apache.catalina.connector.HttpResponse; | ||
| import com.techcourse.http.MimeType; | ||
| import com.techcourse.model.User; | ||
| import java.io.IOException; | ||
| import org.apache.catalina.StaticResourceProvider; | ||
| import jakarta.servlet.http.AbstractController; | ||
|
|
||
| public class RegisterController extends AbstractController { | ||
|
|
||
| private static final String ACCOUNT = "account"; | ||
| private static final String PASSWORD = "password"; | ||
| private static final String EMAIL = "email"; | ||
|
|
||
| private final InMemoryUserRepository inMemoryUserRepository = InMemoryUserRepository.getInstance(); | ||
|
|
||
| @Override | ||
| protected void doGet(HttpRequest request, HttpResponse response) throws IOException { | ||
| String registerHtml = StaticResourceProvider.getStaticResource("/register.html"); | ||
| response.setBody(registerHtml) | ||
| .setContentType(MimeType.HTML.getMimeType()); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doPost(HttpRequest request, HttpResponse response) { | ||
| if (!request.hasParameter(ACCOUNT) || !request.hasParameter(PASSWORD) || !request.hasParameter(EMAIL)) { | ||
| response.badRequest(); | ||
| return; | ||
| } | ||
|
|
||
| inMemoryUserRepository.save(new User( | ||
| request.getParameter(ACCOUNT), | ||
| request.getParameter(PASSWORD), | ||
| request.getParameter(EMAIL) | ||
| )); | ||
|
|
||
| response.found("/index.html"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import org.apache.catalina.connector.HttpRequest; | ||
| import org.apache.catalina.connector.HttpResponse; | ||
| import org.apache.catalina.StaticResourceProvider; | ||
| import jakarta.servlet.http.AbstractController; | ||
|
|
||
| public class StaticResourceController extends AbstractController { | ||
|
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. 정적 리소스(html, css, js)는 제가 구현하면서 고민한 부분이라 마크의 의견이 궁금합니다!
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. 먼저 생각된 부분은 웹 서버는 컨트롤러 없이 정적 자원을 응답할 수 있으니까 2번으로 구현하는 것이 간단하고 톰캣 구현하기 미션에 맞을 거라고 생각이 드네요...! 미아는 어떤 결론을 지으셨는지 궁금하네요! +) 카탈리나에서
정적 리소스는 doGet 등의 행위가 필요하다고 볼 수 있을 것 같아요. 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. 오호 톰캣 레퍼런스까지 👍 저는 static resource는 http request로 수정할 일이 없다고 생각했는데
세 가지 방법이나 !! 좋은 의견 감사합니다 🙇🏻♀️ 다 일리있는 의견 같아요. 저는 하지만 톰캣은 웹 서버가 아니라 서블릿 컨테이너의 기능을 하니까 마크의 구현 방식도 적절하고 확장하기 쉽다고 생각합니다! 굿
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. 그런 방법도 있겠네요! 꼭 AbstractController를 상속할 필요는 없었는데 말이죠. 좋은 방법 알려주셔서 고마워요😄 |
||
|
|
||
| @Override | ||
| protected void doGet(HttpRequest request, HttpResponse response) throws Exception { | ||
| String path = request.getPath(); | ||
| response.setBody(StaticResourceProvider.getStaticResource(path)) | ||
| .setContentType(StaticResourceProvider.probeContentType(path)); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,39 @@ | ||
| package com.techcourse.db; | ||
|
|
||
| import com.techcourse.model.User; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
|
|
||
| public class InMemoryUserRepository { | ||
|
|
||
| private static final InMemoryUserRepository INSTANCE = new InMemoryUserRepository(); | ||
| private static final Map<String, User> database = new ConcurrentHashMap<>(); | ||
|
|
||
| private final AtomicLong id = new AtomicLong(); | ||
|
|
||
| static { | ||
| final User user = new User(1L, "gugu", "password", "hkkang@woowahan.com"); | ||
| database.put(user.getAccount(), user); | ||
| INSTANCE.save(new User("gugu", "password", "hkkang@woowahan.com")); | ||
| } | ||
|
|
||
| public static InMemoryUserRepository getInstance() { | ||
| return INSTANCE; | ||
| } | ||
|
|
||
| public static void save(User user) { | ||
| public void save(User user) { | ||
| user.setId(id.getAndIncrement()); | ||
| database.put(user.getAccount(), user); | ||
| } | ||
|
|
||
| public static Optional<User> findByAccount(String account) { | ||
| public Optional<User> findByAccount(String account) { | ||
| return Optional.ofNullable(database.get(account)); | ||
| } | ||
|
|
||
| private InMemoryUserRepository() {} | ||
| private InMemoryUserRepository() { | ||
| } | ||
|
|
||
| public void clear() { | ||
| database.clear(); | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package com.techcourse.http; | ||
|
|
||
| import jakarta.servlet.http.HttpCookie; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import lombok.AllArgsConstructor; | ||
|
|
||
| @AllArgsConstructor | ||
| public class HttpHeaders { | ||
|
|
||
| private static final String HEADER_SEPARATOR = ": "; | ||
| private static final String CRLF = "\r\n"; | ||
| public static final String CONTENT_TYPE = "Content-Type"; | ||
| public static final String CONTENT_LENGTH = "Content-Length"; | ||
| public static final String SET_COOKIE_HEADER = "Set-Cookie"; | ||
| public static final String COOKIE = "Cookie"; | ||
| public static final String LOCATION = "Location"; | ||
| public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; | ||
|
|
||
| private final Map<String, String> headers; | ||
| private final HttpCookie cookie; | ||
|
|
||
| public HttpHeaders() { | ||
| this.headers = new HashMap<>(); | ||
| this.cookie = new HttpCookie(); | ||
| } | ||
|
|
||
| public void clear() { | ||
| headers.clear(); | ||
| cookie.clear(); | ||
| } | ||
|
|
||
| public String getHeadersString() { | ||
| if (cookie.isExist()) { | ||
| headers.put(SET_COOKIE_HEADER, cookie.toMessage()); | ||
| } | ||
| StringBuilder headersString = new StringBuilder(); | ||
| for (Map.Entry<String, String> entry : headers.entrySet()) { | ||
| headersString.append(entry.getKey()) | ||
| .append(HEADER_SEPARATOR) | ||
| .append(entry.getValue()) | ||
| .append(" ") | ||
| .append(CRLF); | ||
| } | ||
| headersString.append(cookie.toMessage()); | ||
| return headersString.toString(); | ||
| } | ||
|
|
||
| public String get(String key) { | ||
| return headers.get(key); | ||
| } | ||
|
|
||
| public void set(String key, String value) { | ||
| headers.put(key, value); | ||
| } | ||
|
|
||
| public void setContentType(String contentType) { | ||
| set(CONTENT_TYPE, contentType); | ||
| } | ||
|
|
||
| public void setContentLength(int contentLength) { | ||
| set(CONTENT_LENGTH, String.valueOf(contentLength)); | ||
| } | ||
|
|
||
| public void setCookie(String cookieKey, String cookieValue) { | ||
| cookie.setCookie(cookieKey, cookieValue); | ||
| } | ||
|
|
||
| public void setLocation(String location) { | ||
| set(LOCATION, location); | ||
| } | ||
|
|
||
| public String getCookie(String key) { | ||
| return cookie.getCookie(key); | ||
| } | ||
|
|
||
| public void setHttpOnly(boolean httpOnly) { | ||
| cookie.setHttpOnly(httpOnly); | ||
| } | ||
|
|
||
| public void setMaxAge(int maxAge) { | ||
| cookie.setMaxAge(maxAge); | ||
| } | ||
| } |
This file was deleted.
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.
controller에서도 검증 👍