[ky.kiske] step2 리뷰 요청 드립니다. - #35
Conversation
* Controller 개선 * 다양한 Handler 추가
* 보안 컨트롤러 추가
* HttpRequest 테스트 코드 수정 * Controller 헬퍼 함수 추가
* 쿠키 HttpOnly 추가, 일원화
* 커스텀 에러 추가 * 에러 핸들링 메서드 추가 * 로깅 추가
findstar
left a comment
There was a problem hiding this comment.
안녕하세요. ky 웹서버 리뷰를 맡은 제임스입니다. 😁
전체적으로 요구사항을 충족하는 기능 구현을 잘 해주셨네요!
크게 수정할 부분은 없지만, 조금 더 보완하면 좋을것 같아 코멘트 달아두었습니다.
확인하시고 한번 더 고민해주세요 😄
그럼 화이팅입니다!
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class HttpRequest { |
There was a problem hiding this comment.
HttpRequest 객체가 한꺼번에 너무 많은 일을 하고 있지는 않은가요?
HttpRequestLine, HttpRequestHeader 와 같이 좀 더 세분화 해보면 어떨까요?
|
|
||
| public abstract class Controller { | ||
| private static final Logger log = LoggerFactory.getLogger( Controller.class ); | ||
| protected final Map<PathInfo, Handler> handlers = new LinkedHashMap<>(); |
There was a problem hiding this comment.
handlers 는 굳이 LinkedHashMap 을 사용한 이유가 있을까요?
There was a problem hiding this comment.
Handlers 가 순서를 기반으로 등록되어야 할 필요가 있다면 차후에 실수하기 쉬운 구조 입니다.
path 를 기반으로 동작할 handler 가 다른 방식으로 매칭될 수는 없을지 고민해봐주세요 😄
| private static final String PROTOCOL = "HTTP/1.1"; | ||
|
|
||
| private final DataOutputStream dos; | ||
| private final Map<String, String> headers = new HashMap<>(); |
There was a problem hiding this comment.
HttpHeader 를 별도의 객체로 분리해보면 좋겠습니다.
마참가지로 ContentType , HttpStatus 로 분리할 수 있습니다.
| log.info("{}", startLine); | ||
| } | ||
|
|
||
| public void sendView(byte[] body) throws IOException { |
There was a problem hiding this comment.
IOException 을 그대로 던지지 말고 try / catch 구문으로 처리한 뒤에
좀 더 의미있는 exception 을 던지는 방향으로 개선해보면 어떨까요?
|
|
||
| import java.util.Objects; | ||
|
|
||
| public class PathInfo { |
| @@ -0,0 +1,10 @@ | |||
| <!DOCTYPE html> | |||
| package exception.utils; | ||
|
|
||
| public class NoFileException extends Exception { | ||
| public NoFileException() { |
There was a problem hiding this comment.
NoFIleException 과 같은 경우에는 어떤 파일을 찾을 수 없는지 표시될 수 있게 개선되면 더 좋겠습니다.
| setBasePath(""); | ||
| putHandler("/js/.*", "GET", this::handleFile); | ||
| putHandler("/css/.*", "GET", this::handleFile); | ||
| putHandler("/fonts/.*", "GET", this::handleFile); |
| System.out.println("Running Test3"); | ||
| } | ||
| } | ||
| //package study.reflection; |
| String postMsg = "POST /api HTTP/1.1\n" + | ||
| "Host: localhost:8080\n" + | ||
| "Connection: keep-alive\n" + | ||
| "Content-Length: 33\n" + | ||
| "Accept: */*\n" + | ||
| "\r\n" + | ||
| "userId=javajigi&password=password"; | ||
| postRequest = makeRequest(postMsg); | ||
|
|
||
| String getMsg = "GET /index.html HTTP/1.1\n" + | ||
| "Host: localhost:8080\n" + | ||
| "Connection: keep-alive\n" + | ||
| "Accept: */*\n" + | ||
| ""; | ||
| getRequest = makeRequest(getMsg); | ||
|
|
||
| String queryMsg = "GET /user/create?" + | ||
| "userId=jack&password=password&name=jackwon&email=jackwon%40kakaocorp.com HTTP/1.1\n" + | ||
| "Host: localhost:8080\n" + | ||
| "Connection: keep-alive\n" + | ||
| "Accept: */*\n" + | ||
| ""; | ||
| queryRequest = makeRequest(queryMsg); |
There was a problem hiding this comment.
Http 요청에 대한 raw String 을 이렇게 관리하지 말고
test/resources/ 디렉터리에 파일 형태로 관리하면 어떨까요?
다음처럼 FileInputStream 을 사용하면 Socket connection 에서 획득하는 InputStream 과 같이 테스트 할 수 있습니다.
InputStream in = new FileInputStream(new File(http_request_example_test_case)); - 이후 스텝에서 쓰일 테스트 코드 주석 제거 및 패키지 변경
- test 내 resources에서 Http 요청 코드를 관리하도록 변경
- 기존의 단순 throws Exception을 try / catch를 사용하도록 개선
- HttpRequestLine, HttpRequestHeader로 역할을 분리
- DB에 직접 접근하는 로직을 Service로 이관
- 기존의 OutputStream 에서 HttpResponse를 받도록 변경
|
리뷰 감사합니다!! 코멘트를 참고하다보니 조금 더 섬세하게 작업했어야함을 느꼈습니다 ㅎㅎ.. |
findstar
left a comment
There was a problem hiding this comment.
안녕하세요 제임스입니다.
피드백 드린 사항 잘 반영해주셨네요 👏
질문에 답변드리면
Handlers 가 순서를 기반으로 등록되어야 할 필요가 있다면 차후에 실수하기 쉬운 구조 입니다.
path 를 기반으로 동작할 handler 가 다른 방식으로 매칭될 수는 없을지 고민해봐주세요 😄
그럼 코멘트 확인하시고 계속 화이팅입니다.
|
|
||
| public abstract class Controller { | ||
| private static final Logger log = LoggerFactory.getLogger( Controller.class ); | ||
| protected final Map<PathInfo, Handler> handlers = new LinkedHashMap<>(); |
There was a problem hiding this comment.
Handlers 가 순서를 기반으로 등록되어야 할 필요가 있다면 차후에 실수하기 쉬운 구조 입니다.
path 를 기반으로 동작할 handler 가 다른 방식으로 매칭될 수는 없을지 고민해봐주세요 😄
| public HttpRequest(InputStream in) throws IOException { | ||
| this(new BufferedReader(new InputStreamReader(in))); | ||
| } | ||
|
|
||
| public HttpRequest(BufferedReader br) throws IOException { | ||
| String line = br.readLine(); | ||
| httpRequestLine = new HttpRequestLine(line); | ||
| httpRequestHeader = new HttpRequestHeader(br); | ||
| setBody(br); | ||
| } |
There was a problem hiding this comment.
InputStream 을 받아서 HttpRequest 인스턴스를 생성하는 static method 로 변경해보는건 어떨까요?
| ControllerManager.registerController(new UserController()); | ||
| ControllerManager.registerController(new ViewController()); |
There was a problem hiding this comment.
Webserver 가 ControllerManager 를 알고 있어야할 까요?
RequestHandler 의 static 으로 처리할 수도 있습니다.
- HttpStatus ENUM 클래스로 변환 - ContentType ENUM 클래스로 변환
- defaultHandle 메소드를 통해 순서에 의존하지 않도록 변경

안녕하세요 카이입니다!!
이번 미션 리뷰 잘 부탁드립니다. 감사합니다!!