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

[톰캣 구현하기 - 1,2단계] 에단(김석호) 미션 제출합니다. #372

Merged
merged 34 commits into from
Sep 7, 2023

Conversation

cookienc
Copy link

@cookienc cookienc commented Sep 4, 2023

안녕하세요 무민! 리뷰이 에단입니다.
시간이 촉박해서 깔끔하게 짜지는 못했습니다.
다음번에 리팩토링 할 때 더 예쁘게 해보겠습니다. 리뷰 미리 감사드립니다!

@cookienc cookienc self-assigned this Sep 4, 2023
@cookienc cookienc changed the title [톰캣 구현하기 - 1,2단계] 에단 미션 제출합니다. [톰캣 구현하기 - 1,2단계] 에단(김석호) 미션 제출합니다. Sep 4, 2023
Copy link
Member

@parkmuhyeun parkmuhyeun left a 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 {
Copy link
Member

Choose a reason for hiding this comment

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

static이 붙어있어용

Copy link
Author

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();
Copy link
Member

Choose a reason for hiding this comment

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

지금 request의 정보가 다 나눠져있고 나눠져있는 걸 그대로 handle에 넘겨서 또 거기서 나눠지고 있는데
요런 정보들을 RequestParser 같은 객체로 분리해보는 건 어떨까요? 응집도도 높아지고 넘기는 매개변수도 줄어들 수 있을 거 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

넵! 3단계에 httprequest와 httpresponse로 변경하기가 있어서 남겨뒀는데, 이번 단계에서는 httpRequest 만들어서 처리하겠습니다!

Comment on lines 31 to 38
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;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

image

위처럼 하게되면 메서드로 꺼내 쓸 수 있어서 parseFirstLine[0], parsedFirstLine[1] 이런 것들도 이름이 좀 더 명확해질 거 같아요.

for (final HandlerMapping mapping : handlerMapping) {
final HttpMethod httpMethod = HttpMethod.from(parsedFirstLine[0]);
final String requestUri = parsedFirstLine[1];
if (mapping.supports(httpMethod, requestUri)) {
Copy link
Member

Choose a reason for hiding this comment

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

supports 굉장히 깔끔하네요 👍🏻👍🏻👍🏻

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다!

Comment on lines 29 to 31
final Map<String, String> bodyParams = Arrays.stream(requestBody.split("&"))
.map(param -> param.split("="))
.collect(Collectors.toMap(param -> param[0], param -> param[1]));
Copy link
Member

@parkmuhyeun parkmuhyeun Sep 4, 2023

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("잘못된 비밀번호입니다. 다시 입력해주세요.");
Copy link
Member

Choose a reason for hiding this comment

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

꼼꼼하시네요 bb

Comment on lines 47 to 49
return String.join("\r\n",
"HTTP/1.1 302 Found ",
"Location: /401.html ");
Copy link
Member

@parkmuhyeun parkmuhyeun Sep 4, 2023

Choose a reason for hiding this comment

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

response 하는 부분들도 하드코딩 되어있는데 response를 생성해주는 객체로 분리해주면 재사용성과 유지보수에 더 좋을거 같아요!

Copy link
Author

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);
Copy link
Member

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) ||
Copy link
Member

Choose a reason for hiding this comment

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

"/"도 StaticFile에 속할 수 있는지 궁금합니다.

Copy link
Author

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) {
Copy link
Member

Choose a reason for hiding this comment

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

session에 User대신 account(string)를 넣으신 이유가 있나요?

Copy link
Author

Choose a reason for hiding this comment

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

인가가 구현되어 있지 않아 account만으로도 인증만 구별하도록 했습니다

Comment on lines 18 to 22
if (Objects.nonNull(SESSIONS.get(id))) {
return true;
}

return false;
Copy link
Member

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)); 한 줄로 줄일 수 있을거 같아요!

@sonarcloud
Copy link

sonarcloud bot commented Sep 6, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 7 Code Smells

0.0% 0.0% Coverage
0.0% 0.0% Duplication

warning 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.
Read more here

@cookienc
Copy link
Author

cookienc commented Sep 6, 2023

안녕하세요 무민! 에단입니다. 정성스러운 코드리뷰 감사합니다. 코드리뷰 주신대로 httpRequst와 httpResponse로 Parser를 만들어서 분리해봤습니다. 더 고칠 수 있겠지만, 변경된 사항이 많아서 리뷰하기가 힘드실것 같아서 제출합니다. 테스트는 3 - 4단계에서 진행하겠습니다

Copy link
Member

@parkmuhyeun parkmuhyeun left a 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;

Copy link
Member

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("\\?");
Copy link
Member

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]));
Copy link
Member

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";
Copy link
Member

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"),
;
Copy link
Member

Choose a reason for hiding this comment

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

와우 👍🏻👍🏻

@parkmuhyeun parkmuhyeun merged commit b6e02c7 into woowacourse:cookienc Sep 7, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants