Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
caae46a
이슈 템플릿 생성
zangsu Sep 4, 2024
fed02f6
fix: remove implementation logback-classic on gradle (#501)
geoje Sep 5, 2024
7e91356
fix: add threads min-spare configuration on properties (#502)
geoje Sep 5, 2024
04921cb
Merge branch 'woowacourse:main' into main
zangsu Sep 6, 2024
a7f5de9
Merge branch 'woowacourse:zangsu' into zangsu
zangsu Sep 8, 2024
24c9787
fix: content 가 null 일 경우 응답이 생성되지 않도록 변경
zangsu Sep 8, 2024
d4b32a0
refactor: 학습테스트를 무시하도록 변경
zangsu Sep 8, 2024
0742e5a
fix: 로그인 페이지를 보여주도록 변경
zangsu Sep 8, 2024
1e0aba2
refactor: 응답 전체 로깅 삭제
zangsu Sep 8, 2024
400605f
refactor: 사용하지 않는 핸들러 삭제
zangsu Sep 8, 2024
c93ad34
fix: 로그인 요청에서 로그인 페이지 응답으로 변경
zangsu Sep 8, 2024
7cff4d7
refactor: 파일에 따라 MIME TYPE 을 결정하는 메서드 사용
zangsu Sep 8, 2024
002f558
refactor: handle 메서드에서 null 반환 제거
zangsu Sep 9, 2024
0d23bab
refactor: Resource -> StaticResource 로 이름 및 역할 변경
zangsu Sep 9, 2024
708b765
refactor: 정적 파일 응답을 분리
zangsu Sep 9, 2024
42adfa3
test: 로그인 시도에 대한 요청 테스트
zangsu Sep 9, 2024
82885c1
feat: 로그인 결과에 따라 응답 분기
zangsu Sep 9, 2024
5b141fc
refactor: 메서드 이름 변경
zangsu Sep 9, 2024
917529e
test: 회원가입 테스트 작성
zangsu Sep 9, 2024
fabed9b
test: 회원가입 로직 작성
zangsu Sep 9, 2024
a84d977
test: 테스트에 @Nested 사용
zangsu Sep 9, 2024
6197946
refactor: ResourceHandler 구현체 이름 변경
zangsu Sep 9, 2024
264a24e
refactor: 필요없는 MethodRequest 삭제
zangsu Sep 9, 2024
a8f1971
refactor: MethodQueryParameters 이름 변경
zangsu Sep 9, 2024
554a8b0
refactor: 전체 요청을 읽는 메서드의 구현 변경
zangsu Sep 10, 2024
fc085e7
refactor: 쿼리 파라미터 파싱을 존재할 때만 수행하도록 변경
zangsu Sep 10, 2024
bd88159
test: 회원가입 로직 테스트 변경
zangsu Sep 10, 2024
f93b392
feat: 회원가입 기능 구현
zangsu Sep 10, 2024
5213bd4
refactor: 요청을 읽는 방식 변경
zangsu Sep 10, 2024
6ad41a6
refactor: 핸들러 하나만을 사용하도록 변경
zangsu Sep 10, 2024
b385ea7
test: body 가 존재하는 요청에 Content-Length 헤더 추가
zangsu Sep 10, 2024
7431593
test: 요청 생성 메서드 변경
zangsu Sep 10, 2024
857470c
test: 확인 로직을 헤더 순서와 관련 없이 확인하도록 변경
zangsu Sep 10, 2024
439599d
refactor: 지정된 응답만 생성하는 대신 응답이 상태를 가지도록 변경
zangsu Sep 10, 2024
c711c0e
refactor: Response 를 생성하는 책임을 스스로 가지고, builder 패턴을 사용하도록 변경
zangsu Sep 10, 2024
165077f
chore: 패키지 변경
zangsu Sep 10, 2024
39d24d2
refactor: 필요없는 로그 제거
zangsu Sep 10, 2024
291d24f
refactor: 필드 순서 변경
zangsu Sep 10, 2024
97af4f1
refactor: 필요없는 출력 삭제
zangsu Sep 10, 2024
7079e5d
refactor: 로그인을 POST 방식으로 변경
zangsu Sep 10, 2024
c5265b3
feat: 쿠키 클래스 생성
zangsu Sep 10, 2024
6cb90a6
feat: LMS 에 명시된 Session 관련 객체들 구현
zangsu Sep 10, 2024
8f55340
feat: 로그인 기능에서 세션을 유지하도록 변경
zangsu Sep 10, 2024
d4589cd
refactor: 유저 조회시 해당 유저가 존재하지 않으면 예외를 반환하는 메서드 구현
zangsu Sep 10, 2024
f0d694a
feat: 로그인, 회원가입시 세션을 생성하도록 구현
zangsu Sep 10, 2024
95283ac
refactor: Http 헤더 이름 상수화
zangsu Sep 10, 2024
7392038
refactor: 사용되지 않는 import 문 제거
zangsu Sep 10, 2024
71b373c
refactor: final 필드로 변경
zangsu Sep 10, 2024
ca76404
refactor: 상수화
zangsu Sep 10, 2024
0bab601
refactor: 쿠키 관련 값 상수화
zangsu Sep 10, 2024
24d9b85
test: 루트 요청에 대한 테스트 추가
zangsu Sep 12, 2024
ec3bf84
fix: 정적 리소스 요청 확인을 path 전체에서 파일 확장자를 찾도록 변경
zangsu Sep 12, 2024
93bfcd9
test: 로그인 로직을 POST 로 보내도록 변경
zangsu Sep 12, 2024
37ba30a
refactor: QueryParameters -> RequestParameters 클래스 이름 변경
zangsu Sep 12, 2024
f97d75d
refactor: 파라미터 명 변경
zangsu Sep 12, 2024
3523cda
test: Content-Length 를 실제 읽은 값을 사용하도록 변경
zangsu Sep 12, 2024
9e86016
refactor: login 요청에 대해 정확하게 매핑하도록 변경
zangsu Sep 12, 2024
b7fa7e1
test: 로그인이 되어 있을 경우 로그인 뷰 조회 테스트
zangsu Sep 12, 2024
e7f61e3
fix: 로그인이 된 경우 로그인 페이지로 접근하면 index.html 로 리다이렉트 하도록 변경
zangsu Sep 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions study/src/test/java/study/FileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand Down
1 change: 0 additions & 1 deletion study/src/test/java/study/IOStreamTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package study;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.in;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.coyote.http11.exception.NoSuchUserException;

import com.techcourse.model.User;

public class InMemoryUserRepository {
Expand All @@ -19,6 +21,11 @@ public static void save(User user) {
database.put(user.getAccount(), user);
}

public static User fetchByAccount(String account) {
return findByAccount(account)
.orElseThrow(() -> new NoSuchUserException(account + " 에 해당하는 유저를 찾을 수 없습니다."));
}

public static Optional<User> findByAccount(String account) {
return Optional.ofNullable(database.get(account));
}
Expand Down
8 changes: 4 additions & 4 deletions tomcat/src/main/java/org/apache/catalina/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.io.IOException;

import jakarta.servlet.http.HttpSession;
import org.apache.coyote.http11.session.Session;

/**
* A <b>Manager</b> manages the pool of Sessions that are associated with a
Expand All @@ -29,7 +29,7 @@ public interface Manager {
*
* @param session Session to be added
*/
void add(HttpSession session);
void add(Session session);

/**
* Return the active Session, associated with this Manager, with the
Expand All @@ -43,12 +43,12 @@ public interface Manager {
* @throws IOException if an input/output error occurs while
* processing this request
*/
HttpSession findSession(String id) throws IOException;
Session findSession(String id) throws IOException;

/**
* Remove this Session from the active Sessions for this Manager.
*
* @param session Session to be removed
*/
void remove(HttpSession session);
void remove(String session);
}
35 changes: 6 additions & 29 deletions tomcat/src/main/java/org/apache/coyote/http11/Http11Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.coyote.Processor;
import org.apache.coyote.http11.exception.NoHandlerException;
import org.apache.coyote.http11.handler.MethodHandler;
import org.apache.coyote.http11.handler.StaticResourceHandler;
import org.apache.coyote.http11.request.Request;
import org.apache.coyote.http11.handler.DefaultResourceHandler;
import org.apache.coyote.http11.httpmessage.request.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -21,15 +16,12 @@
public class Http11Processor implements Runnable, Processor {

private static final Logger log = LoggerFactory.getLogger(Http11Processor.class);
private final List<RequestHandler> requestHandlers;
private final RequestHandler requestHandler;
private final Socket connection;

public Http11Processor(Socket connection) {
this.connection = connection;
this.requestHandlers = List.of(
new MethodHandler(),
new StaticResourceHandler()
);
this.requestHandler = new DefaultResourceHandler();
}

@Override
Expand All @@ -45,7 +37,7 @@ public void process(Socket connection) {
BufferedReader requestBufferedReader = new BufferedReader(inputStreamReader);
var outputStream = connection.getOutputStream()) {

Request request = Request.parseFrom(getPlainRequest(requestBufferedReader));
Request request = Request.readFrom(requestBufferedReader);
log.info("request : {}", request);
String response = getResponse(request);

Expand All @@ -57,21 +49,6 @@ public void process(Socket connection) {
}

private String getResponse(Request request) throws IOException {
for (RequestHandler requestHandler : requestHandlers) {
String response = requestHandler.handle(request);
if (response != null) {
return response;
}
}
throw new NoHandlerException("핸들러가 존재하지 않습니다. request : " + request);
}

private List<String> getPlainRequest(BufferedReader requestBufferedReader) throws IOException {
List<String> plainRequest = new ArrayList<>();
while (requestBufferedReader.ready()) {
String line = requestBufferedReader.readLine();
plainRequest.add(line);
}
return Collections.unmodifiableList(plainRequest);
return requestHandler.handle(request);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.io.IOException;

import org.apache.coyote.http11.request.Request;
import org.apache.coyote.http11.httpmessage.request.Request;

@FunctionalInterface
public interface RequestHandler {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.apache.coyote.http11.exception;

public class CanNotHandleRequest extends RuntimeException {
public CanNotHandleRequest(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.apache.coyote.http11.exception;

public class NoSuchUserException extends RuntimeException {
public NoSuchUserException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.apache.coyote.http11.exception;

public class NotCompleteResponseException extends RuntimeException {
public NotCompleteResponseException(String message) {
Copy link
Member

Choose a reason for hiding this comment

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

클래스명이 되게 상세한데, 이렇게 여러 Exception을 분리한 이유, 기준이 궁금합니다.

Copy link
Author

Choose a reason for hiding this comment

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

Exception 을 하나로 두지 않고 지금처럼 여러개의 Exception 을 둔 것은 단순한 취향이었던 것 같아요.
아직까지 필요한 Exception 이 많지 않기 때문에 하나의 Exception 을 두고 예외 메시지로 구분하는 것 보다 각각의 명확한 Exception 을 사용하고 싶었어요.

super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package org.apache.coyote.http11.handler;

import java.io.IOException;
import java.util.Objects;

import org.apache.coyote.http11.RequestHandler;
import org.apache.coyote.http11.exception.CanNotHandleRequest;
import org.apache.coyote.http11.exception.NoSuchUserException;
import org.apache.coyote.http11.httpmessage.request.Request;
import org.apache.coyote.http11.httpmessage.response.Response;
import org.apache.coyote.http11.httpmessage.response.StaticResource;
import org.apache.coyote.http11.session.Session;
import org.apache.coyote.http11.session.SessionManager;

import com.techcourse.db.InMemoryUserRepository;
import com.techcourse.model.User;

public class DefaultResourceHandler implements RequestHandler {

@Override
public String handle(Request request) throws IOException {
if (request.isStaticResourceRequest()) {
return Response.builder()
.versionOf(request.getHttpVersion())
.ofStaticResource(new StaticResource(request.getTarget()))
.toHttpMessage();
}
if (request.getTarget().equals("/")) {
return Response.builder()
.versionOf(request.getHttpVersion())
.ofStaticResource(new StaticResource("/index.html"))
Copy link
Member

Choose a reason for hiding this comment

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

root 요청이 여기오기도전에 에러터지네요. 한번 확인 해봐야할 것 같아요

Copy link
Author

Choose a reason for hiding this comment

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

static resource 요청을 판단할 때 문제가 있었네용..ㅎㅎ
수정 했습니다!

.toHttpMessage();
}
if (request.getTarget().equals("/login")) {
return loginResponse(request);
Copy link
Member

Choose a reason for hiding this comment

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

contains로 분기해도 괜찮을까요?
localhost:8080/registerlogin 해도 login 페이지가 나오고있어요!

Copy link
Author

Choose a reason for hiding this comment

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

오! 이젠 로그인 요청이 POST 로 변경되어서 쿼리 파라미터가 포함된 요청이 존재하지 않는군요!
equals() 로 비교하도록 변경하였습니다!

}
if (request.getTarget().contains("register")) {
return registerResponse(request);
}
throw new CanNotHandleRequest("처리할 수 없는 요청입니다. : " + request.getTarget());
}

private String loginResponse(Request request) throws IOException {
if (request.isPost()) {
return login(request).toHttpMessage();
}
if (isLoggedIn(request)) {
return Response.builder()
.versionOf(request.getHttpVersion())
.found("/index.html")
.toHttpMessage();
}
return Response.builder()
.versionOf(request.getHttpVersion())
.ofStaticResource(new StaticResource("/login.html"))
.toHttpMessage();
}

private boolean isLoggedIn(Request request) {
return Objects.nonNull(request.getSession(false));
}

private Response login(Request request) throws NoSuchUserException {
RequestParameters requestParams = RequestParameters.parseFrom(request.getBody());
String account = requestParams.getParam("account");
String password = requestParams.getParam("password");
User user = InMemoryUserRepository.fetchByAccount(account);
if (user.checkPassword(password)) {
Session session = request.getSession(true);
session.setAttribute("user", user);
SessionManager.getInstance().add(session);
return Response.builder()
.versionOf(request.getHttpVersion())
.addCookie("JSESSIONID", session.getId())
.found("/index.html");
}

return Response.builder()
.versionOf(request.getHttpVersion())
.found("/401.html");
}

private String registerResponse(Request request) throws IOException {
if (request.isPost()) {
RequestParameters methodRequest = RequestParameters.parseFrom(request.getBody());
User user = register(methodRequest);
Session session = request.getSession(true);
session.setAttribute("user", user);
SessionManager.getInstance().add(session);
return Response.builder()
.versionOf(request.getHttpVersion())
.addCookie("JSESSIONID", session.getId())
.found("/index.html")
.toHttpMessage();
}

return Response.builder()
.versionOf(request.getHttpVersion())
.ofStaticResource(new StaticResource("/register.html"))
.toHttpMessage();
}

private User register(RequestParameters requestParams) {
String account = requestParams.getParam("account");
User user = new User(
account,
requestParams.getParam("password"),
requestParams.getParam("email")
);
InMemoryUserRepository.save(user);
return InMemoryUserRepository.fetchByAccount(account);
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading