-
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
[톰캣 구현하기 - 1,2단계] 에단(김석호) 미션 제출합니다. #372
Conversation
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.
안녕하세요 에단!
톰켓 구현하시느라 고생 많으셨습니다. 브랜치 step2는 노리신 건가요!? 😀
이번에 어려웠던거 같은데 FrontHandler, HandlerMapping 등 잘 구현해주셨네요 ㅎㅎ
특히 support 부분 인상 깊었습니다 👍🏻👍🏻
잘 구현해주셨지만 좀 더 개선할 점이 보여 커멘트 남겼습니다. 그리고 Mapping 부분들에 공통적으로 반영했으면 좋겠는 부분이 있어서 Mapping 뒤쪽에는 따로 코멘트를 안 적었고 여기 남기겠습니다!
다른 객체로 역할을 분리하거나 메서드를 분리하면 Mapping쪽의 코드들이 많이 줄고 하드 코딩들도 줄어서 가독성도 더 좋아질거 같습니다.
그리고 다음번에 PR할 때는 테스트코드도 있으면 더 좋을 거 같아요!
+없는 path로 들어오면 404.html 띄워주는 것도 해보면 어떨까요??
|
||
outputStream.write(response.getBytes()); | ||
outputStream.flush(); | ||
} catch (IOException | UncheckedServletException e) { | ||
log.error(e.getMessage(), e); | ||
} | ||
} | ||
|
||
private static String parseRequestBody(final HttpMethod httpMethod, final HttpHeaders headers, final BufferedReader bufferedReader) throws IOException { |
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.
static이 붙어있어용
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.
매의 눈이네요!
@@ -28,20 +40,48 @@ public void run() { | |||
public void process(final Socket connection) { | |||
try (final var inputStream = connection.getInputStream(); | |||
final var outputStream = connection.getOutputStream()) { | |||
final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); | |||
final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); | |||
final String firstLine = bufferedReader.readLine(); |
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.
지금 request의 정보가 다 나눠져있고 나눠져있는 걸 그대로 handle에 넘겨서 또 거기서 나눠지고 있는데
요런 정보들을 RequestParser 같은 객체로 분리해보는 건 어떨까요? 응집도도 높아지고 넘기는 매개변수도 줄어들 수 있을 거 같아요!
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.
넵! 3단계에 httprequest와 httpresponse로 변경하기가 있어서 남겨뒀는데, 이번 단계에서는 httpRequest 만들어서 처리하겠습니다!
for (final HandlerMapping mapping : handlerMapping) { | ||
final HttpMethod httpMethod = HttpMethod.from(parsedFirstLine[0]); | ||
final String requestUri = parsedFirstLine[1]; | ||
if (mapping.supports(httpMethod, requestUri)) { | ||
response = mapping.handle(parsedFirstLine[1], headers, requestBody); | ||
break; | ||
} | ||
} |
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.
for (final HandlerMapping mapping : handlerMapping) { | ||
final HttpMethod httpMethod = HttpMethod.from(parsedFirstLine[0]); | ||
final String requestUri = parsedFirstLine[1]; | ||
if (mapping.supports(httpMethod, requestUri)) { |
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.
supports 굉장히 깔끔하네요 👍🏻👍🏻👍🏻
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.
감사합니다!
final Map<String, String> bodyParams = Arrays.stream(requestBody.split("&")) | ||
.map(param -> param.split("=")) | ||
.collect(Collectors.toMap(param -> param[0], param -> param[1])); |
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.
HttpParser로 객체 분리하게 되면 자연스럽게 분리되어 메서드를 호출하면 되는데 만약에 분리 안하신다면 메서드로 분리하셔서 어떤 연산인지 알려주면 더 가독성이 좋을거 같아요!
.orElseThrow(() -> new IllegalArgumentException("잘못된 계정입니다. 다시 입력해주세요.")); | ||
|
||
if (!user.checkPassword(password)) { | ||
throw new IllegalArgumentException("잘못된 비밀번호입니다. 다시 입력해주세요."); |
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.
꼼꼼하시네요 bb
return String.join("\r\n", | ||
"HTTP/1.1 302 Found ", | ||
"Location: /401.html "); |
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.
response 하는 부분들도 하드코딩 되어있는데 response를 생성해주는 객체로 분리해주면 재사용성과 유지보수에 더 좋을거 같아요!
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.
이걸 보고 httpRequest와 httpResponse를 만들었습니다. 살짝 3단계를 첨가했어요...
final String password = bodyParams.get("password"); | ||
final String email = bodyParams.get("email"); | ||
|
||
final User user = new User(account, password, email); |
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.
음... 이번 톰켓 미션과 크게 관련있는지는 모르겠는데 똑같은 걸로 계속 가입이 되더라구요.
요 부분은 에단이 원하면 반영해주세요!
@Override | ||
public boolean supports(final HttpMethod httpMethod, final String requestUri) { | ||
return GET == httpMethod && | ||
("/".equals(requestUri) || |
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.
"/"도 StaticFile에 속할 수 있는지 궁금합니다.
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.
잘못 생각했습니다! 지적 감사합니다
return loginManager.isAlreadyLogined(jSessionId); | ||
} | ||
|
||
protected void setSession(final String jSessionId, final Map<String, String> sessionData) { |
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.
session에 User대신 account(string)를 넣으신 이유가 있나요?
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.
인가가 구현되어 있지 않아 account만으로도 인증만 구별하도록 했습니다
if (Objects.nonNull(SESSIONS.get(id))) { | ||
return true; | ||
} | ||
|
||
return false; |
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.
이 부분 return Objects.nonNull(SESSIONS.get(id)); 한 줄로 줄일 수 있을거 같아요!
Kudos, SonarCloud Quality Gate passed! 0 Bugs 0.0% Coverage The version of Java (11.0.20.1) you have used to run this analysis is deprecated and we will stop accepting it soon. Please update to at least Java 17. |
안녕하세요 무민! 에단입니다. 정성스러운 코드리뷰 감사합니다. 코드리뷰 주신대로 httpRequst와 httpResponse로 Parser를 만들어서 분리해봤습니다. 더 고칠 수 있겠지만, 변경된 사항이 많아서 리뷰하기가 힘드실것 같아서 제출합니다. 테스트는 3 - 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.
이번에 리뷰 할 때 미리 3단계꺼 까지 하도록 해서 약간 죄송했었는데 잘 적용해주셔서 감사합니다!
적용하고 나니 하드코딩이 엄청나게 줄고 역할 분리가 잘 되어서 코드가 매우 깔끔해졌네요 👍🏻
조금의 코멘트 더 남겼고 요건 다음 단계 때 같이 반영해주세요!
아 그리고 테스트 코드까지 추가 해주시면 Best 🙌
고생하셨습니다.
|
||
private final HttpMethod httpMethod; | ||
private final RequestUri requestUri; | ||
|
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.
공백이 하나있네요!
} | ||
} | ||
|
||
final String[] parsedRequestUri = requestUri.split("\\?"); | ||
if (requestUri.contains("?")) { | ||
final String[] parsedRequestUri = httpRequest.getRequestUri().getRequestUri().split("\\?"); |
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.
parsedRequestUri가 아래 if문 안에서만 사용되는 거 같아서 If문 안에 들어가도 될 것 같아요!
final String[] parsedRequestUri = requestUri.split("\\?"); | ||
if (requestUri.contains("?")) { | ||
final String[] parsedRequestUri = httpRequest.getRequestUri().getRequestUri().split("\\?"); | ||
if (httpRequest.getRequestUri().getRequestUri().contains("?")) { | ||
final Map<String, String> queryStrings = Arrays.stream(parsedRequestUri[1].split("&")) | ||
.map(param -> param.split("=")) | ||
.collect(Collectors.toMap(param -> param[0], param -> param[1])); |
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.
이 부분도 HttpRequest안으로 분리해보는 건 어떨까요?
|
||
public class LoginMapping extends LoginFilter implements HandlerMapping { | ||
|
||
public static final String TARGET_URI = "login"; |
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.
접근제어자 private으로 해주면 더 좋을 것 같아요.
SET_COOKIE("Set-Cookie"), | ||
UPGRADE_INSECURE_REQUESTS("Upgrade-Insecure-Requests"), | ||
USER_AGENT("User-Agent"), | ||
; |
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.
와우 👍🏻👍🏻
안녕하세요 무민! 리뷰이 에단입니다.
시간이 촉박해서 깔끔하게 짜지는 못했습니다.
다음번에 리팩토링 할 때 더 예쁘게 해보겠습니다. 리뷰 미리 감사드립니다!