-
Notifications
You must be signed in to change notification settings - Fork 311
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[1,2단계 - Tomcat 구현하기] 몰리(김지민) 미션 제출합니다. (#582)
* feat(Http11Processor): 요청 데이터를 HttpRequest 객체로 변경하는 메서드 작성 * feat(Http11Processor): 요청URL과 일치하는 정적 파일을 반환 * feat(Http11Processor): root url로 요청일 경우 특정 문자열 반환 * feat(Http11Processor): html이 아닌 다른 형식의 파일 지원 * refactor(HttpRequestParser): HttpRequest를 처리하는 객체 분리 * feat(RequestHandler): 요청을 처리하는 핸들러 분리 * feat(RequestHandler): login 엔드포인트 접속 시 로직 처리 * fix(RequestHandler): query null인 경우 정적 파일 렌더링하도록 * feat(RequestHandler): 로그인 성공 시 리다이렉트 * refactor(HttpResponseGenerator): response 생성 객체 분리 * fix: remove implementation logback-classic on gradle (#501) * fix: add threads min-spare configuration on properties (#502) * feat(HttpHeader): Header 객체 분리 * feat(HttpReqeust): Request 객체 구현 * feat(HttpRequestParser): Get이 아닌 다른 method여도 Request 객체 파싱 * feat(RequestHandler): queryString이 없는 path일 경우 검증 후 로직 * feat(RequestHandler): 회원가입 post 요청 로직 구현 * feat(HttpCookie): Cookie 객체 구현 * fix(RequestHandler): 회원가입 시 비밀번호, 이메일 파싱 로직 수정 * feat(index.html): login 적용 후 코드 활성화 * feat(RequestHandler): login 을 post method로 변경 * fix(RequestHandler): Set-Cookie 응답에 추가하는 로직 수정 * feat(Session): Session, Manger 구현체 생성 * feat(SessionManager): 싱글톤 적용 * feat(RequestHandler): 이미 로그인 되어있는지 세션으로 검증 및 리다이렉트 * chore: 타임리프 의존성 추가 * feat(CacheWebConfig): 휴리스틱 캐싱 제거 * feat(CacheWebConfig): HTTP Compression 설정 * feat(EtagFilterConfiguration): ETag/If-None-Match 적용 * feat(HttpRequest): Cookie 파싱 로직 변경, Session 파싱 제거 * refactor(HttpCookie): 파일 위치 변경 * refactor(/request): request 관련 객체 위치 이동 * refactor(/response): response 관련 객체 위치 이동 * refactor(HttpMethod): http method 상수로 추출 * refactor(handler): handler 분리 * refactor(handler): 요청을 처리하는 최상위 Handler 추상 클래스 생성 * refactor(HttpHeader): toString 구현 * refactor(RequestHandler): 불필요한 예외 전파 제거 * refactor(mapping): 패키지 구조 변경 * feat(EtagFilterConfiguration): etag 추가 * refactor(CacheBustingWebConfig): busting 추가 * test(Http11ProcessorTest): content-length 수정 * refactor(RequestHandlerAdapter): Adapter로 이름 변경 * refactor(/http): 패키지 구조 개선, http 관련 객체 위치 이동 * refactor(Http11Processor): sout문 제거 * refactor(HttpRequestParser): 중복 정의된 조건문 제거 * refactor: 클래스 시작 줄에 개행 추가 * test(SessionManager): 기본 메서드에 대해 테스트 작성 * refactor(/catalina/session): session 관련 객체들 위치 이동 * refactor(Session): 세션에 속성을 추가하는 메서드의 인자 이름 명확하게 * test(SessionTest): 속성값 조회 테스트 * refactor(ResourceHandlerMapping): concat 메서드를 체이닝처럼 개행 * refactor(UrlHandlerMapping): IllegalCallerException 던지지 않고 404 페이지 반환 * refactor(StaticResourceHandler): Handler 상속 및 파일 위치 변경 * test(StaticResourceHandler): 정적 리소스 처리 테스트 작성 * refactor(LoginHandler): Get 요청 처리 로직 개선 * refactor(LoginHandler): 인증되었는지 로직 개선 및 테스트 작성 * refactor(RootEndPointHandler): 루트 엔드포인트 요청을 처리하는 핸들러 분리 * test(RegisterHandlerTest): 회원가입 테스트 작성 * refactor(HandlerMapping): 요청에 대한 핸들러를 반환하도록 역할 부여 및 테스트 작성 * feat(SessionManager): 특정 아이디인 세션이 존재하는지 반환하는 메서드 추가 * refactor(HttpCookie): 필드와 인자가 다른 생성자를 정팩메로 변경 * test(HttpCookie): 테스트 작성 및 필드를 private하게 변경 * refactor(HttpRequestReader): 객체 책임에 맡게 이름 변경 * refactor(StandardHttpHeader): HTTP 일반적인 헤더를 나타내는 이넘 생성 * refactor(/header): header 관련 객체 패키지로 이동 * refactor(StaticResourceHandler): 확장자가 없는 경우 /static 경로에 있는 html 리소스를 반환 * refactor(NotFoundHandler): NotFoundException에 대한 핸들러 분리 * refactor(UnAuthorizationHandler): UnAuthorization 에 대한 핸들러 분리 * refactor(/test): 변경된 응답 메시지를 규격에 맞게 상태 값 형식 변경 * refactor(InternalServerErrorHandler): 최상위 Exception 에 대한 핸들러 분리 * refactor(HandlerMapping): 에러에 대한 핸들링 처리 * refactor(Http11Processor): 핸들링 도중 에러 발생 시 처리 * refactor(HttpResponseGenerator): 500 변경 * refactor(StaticResourceHandler): 정적 파일 조회 로직 변경 * refactor(Http11ProcessorTest): 각 http request에 따른 통합 테스트 추가 * test(HttpRequest): HttpRequest 객체 테스트 작성 * refactor(HttpRequest): application/x-www-form-urlencoded 형식의 요청인 경우 바디를 key, value로 파싱하는 책임 부 * test(HttpRequestReader): HttpRequestReader 테스트 작성 * test(HttpResponseGenerator): host 고 * refacotr(HttpRequest): 특정 헤더인지 StandardHttpHeader 에게 물어보도록 변경 --------- Co-authored-by: Gyeongho Yang <[email protected]>
- Loading branch information
Showing
44 changed files
with
1,652 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
study/src/main/java/cache/com/example/cachecontrol/CacheWebConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,21 @@ | ||
package cache.com.example.cachecontrol; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.http.CacheControl; | ||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
import org.springframework.web.servlet.mvc.WebContentInterceptor; | ||
|
||
@Configuration | ||
public class CacheWebConfig implements WebMvcConfigurer { | ||
|
||
@Override | ||
public void addInterceptors(final InterceptorRegistry registry) { | ||
CacheControl cacheControl = CacheControl.noCache().cachePrivate(); | ||
|
||
WebContentInterceptor webContentInterceptor = new WebContentInterceptor(); | ||
webContentInterceptor.addCacheMapping(cacheControl, "/**"); | ||
|
||
registry.addInterceptor(webContentInterceptor); | ||
} | ||
} |
16 changes: 12 additions & 4 deletions
16
study/src/main/java/cache/com/example/etag/EtagFilterConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,20 @@ | ||
package cache.com.example.etag; | ||
|
||
import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.filter.ShallowEtagHeaderFilter; | ||
|
||
import cache.com.example.version.CacheBustingWebConfig; | ||
|
||
@Configuration | ||
public class EtagFilterConfiguration { | ||
|
||
// @Bean | ||
// public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() { | ||
// return null; | ||
// } | ||
@Bean | ||
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() { | ||
FilterRegistrationBean<ShallowEtagHeaderFilter> filter = new FilterRegistrationBean<>(); | ||
filter.setFilter(new ShallowEtagHeaderFilter()); | ||
filter.addUrlPatterns("/etag", CacheBustingWebConfig.PREFIX_STATIC_RESOURCES + "/*"); | ||
return filter; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
tomcat/src/main/java/org/apache/catalina/session/Session.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.apache.catalina.session; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class Session { | ||
|
||
private final String id; | ||
private final Map<String, Object> values = new HashMap<>(); | ||
|
||
public Session(final String id) { | ||
this.id = id; | ||
} | ||
|
||
public String getId() { | ||
return id; | ||
} | ||
|
||
public Object getAttribute(final String name) { | ||
return values.entrySet() | ||
.stream() | ||
.filter(entry -> entry.getKey().equals(name)) | ||
.map(Map.Entry::getValue) | ||
.findFirst() | ||
.orElse(null); | ||
} | ||
|
||
public Map<String, Object> getValues() { | ||
return values; | ||
} | ||
|
||
public void setAttribute(String name, Object value) { | ||
values.put(name, value); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
tomcat/src/main/java/org/apache/catalina/session/SessionManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.apache.catalina.session; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class SessionManager implements Manager { | ||
private static final Map<String, Session> SESSIONS = new HashMap<>(); | ||
private static final SessionManager INSTANCE = new SessionManager(); | ||
|
||
private SessionManager() {} | ||
|
||
public static SessionManager getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
public boolean existsById(final String id) { | ||
return SESSIONS.containsKey(id); | ||
} | ||
|
||
@Override | ||
public void add(Session session) { | ||
SESSIONS.put(session.getId(), session); | ||
} | ||
|
||
@Override | ||
public Session findSession(final String id) { | ||
return SESSIONS.get(id); | ||
} | ||
|
||
@Override | ||
public void remove(Session session) { | ||
SESSIONS.remove(session.getId()); | ||
} | ||
} | ||
|
59 changes: 59 additions & 0 deletions
59
tomcat/src/main/java/org/apache/coyote/HandlerMapping.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package org.apache.coyote; | ||
|
||
import org.apache.coyote.handler.Handler; | ||
import org.apache.coyote.handler.LoginHandler; | ||
import org.apache.coyote.handler.RegisterHandler; | ||
import org.apache.coyote.handler.RootEndPointHandler; | ||
import org.apache.coyote.handler.StaticResourceHandler; | ||
import org.apache.coyote.handler.exception.InternalServerErrorHandler; | ||
import org.apache.coyote.handler.exception.NotFoundHandler; | ||
import org.apache.coyote.handler.exception.UnAuthorizationHandler; | ||
import org.apache.http.request.HttpRequest; | ||
|
||
|
||
public class HandlerMapping { | ||
|
||
private static final HandlerMapping INSTANCE = new HandlerMapping(); | ||
private static final String PATH_DELIMITER = "/"; | ||
|
||
private HandlerMapping() { | ||
} | ||
|
||
public static HandlerMapping getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
public Handler getHandler(final HttpRequest httpRequest) { | ||
return getHandlerByEndPoint(httpRequest); | ||
} | ||
|
||
private Handler getHandlerByEndPoint(final HttpRequest httpRequest) { | ||
final String path = httpRequest.getPath(); | ||
|
||
if (path.equals(PATH_DELIMITER)) { | ||
return RootEndPointHandler.getInstance(); | ||
} | ||
|
||
if (path.contains("login")) { | ||
return LoginHandler.getInstance(); | ||
} | ||
|
||
if (path.contains("register")) { | ||
return RegisterHandler.getInstance(); | ||
} | ||
|
||
return StaticResourceHandler.getInstance(); | ||
} | ||
|
||
public Handler getHandlerByException(final Exception exception) { | ||
if (exception instanceof NotFoundException) { | ||
return NotFoundHandler.getInstance(); | ||
} | ||
|
||
if (exception instanceof UnauthorizedException) { | ||
return UnAuthorizationHandler.getInstance(); | ||
} | ||
|
||
return InternalServerErrorHandler.getInstance(); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
tomcat/src/main/java/org/apache/coyote/NotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.apache.coyote; | ||
|
||
public class NotFoundException extends RuntimeException { | ||
public NotFoundException(String message) { | ||
super(message); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
tomcat/src/main/java/org/apache/coyote/UnauthorizedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.apache.coyote; | ||
|
||
public class UnauthorizedException extends RuntimeException { | ||
public UnauthorizedException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.apache.coyote.handler; | ||
|
||
import org.apache.http.request.HttpRequest; | ||
|
||
public abstract class Handler { | ||
// TODO: 반환타입 HttpResponse로 변경 | ||
public abstract String handle(HttpRequest httpRequest); | ||
} |
74 changes: 74 additions & 0 deletions
74
tomcat/src/main/java/org/apache/coyote/handler/LoginHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package org.apache.coyote.handler; | ||
|
||
import java.util.Optional; | ||
import java.util.UUID; | ||
|
||
import org.apache.catalina.session.SessionManager; | ||
import org.apache.http.HttpCookie; | ||
import org.apache.http.HttpMethod; | ||
import org.apache.catalina.session.Session; | ||
import org.apache.http.header.StandardHttpHeader; | ||
import org.apache.http.request.HttpRequest; | ||
import org.apache.http.response.HttpResponseGenerator; | ||
|
||
import com.techcourse.db.InMemoryUserRepository; | ||
import com.techcourse.model.User; | ||
|
||
public class LoginHandler extends Handler { | ||
|
||
private static final LoginHandler INSTANCE = new LoginHandler(); | ||
private final SessionManager sessionManager = SessionManager.getInstance(); | ||
|
||
private LoginHandler() { | ||
} | ||
|
||
public static LoginHandler getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
@Override | ||
public String handle(final HttpRequest httpRequest) { | ||
if (httpRequest.isSameMethod(HttpMethod.GET)) { | ||
return processLoginGetRequest(httpRequest); | ||
} | ||
|
||
if (httpRequest.isSameMethod(HttpMethod.POST)) { | ||
return processLoginPostRequest(httpRequest); | ||
} | ||
|
||
return StaticResourceHandler.getInstance().handle(new HttpRequest("GET", "/404.html", "HTTP/1.1", null, null)); | ||
|
||
} | ||
|
||
private String processLoginGetRequest(final HttpRequest httpRequest) { | ||
HttpCookie httpCookie = httpRequest.getHttpCookie(); | ||
if (httpCookie == null || ! sessionManager.existsById(httpCookie.getValue("JSESSIONID"))) { | ||
return StaticResourceHandler.getInstance().handle(new HttpRequest("GET", "/login.html", "HTTP/1.1", null, null)); | ||
} | ||
|
||
return HttpResponseGenerator.getFoundResponse("/index.html"); | ||
} | ||
|
||
private String processLoginPostRequest(final HttpRequest httpRequest) { | ||
final String account = httpRequest.getFormBody("account"); | ||
final String password = httpRequest.getFormBody("password"); | ||
|
||
final Optional<User> userOptional = InMemoryUserRepository.findByAccount(account); | ||
if (userOptional.isEmpty() || !userOptional.get().checkPassword(password)) { | ||
return StaticResourceHandler.getInstance().handle(new HttpRequest("GET", "/401.html", "HTTP/1.1", null, null)); | ||
} | ||
|
||
final Session session = new Session(UUID.randomUUID().toString()); | ||
session.setAttribute("user", userOptional.get()); | ||
sessionManager.add(session); | ||
return addCookie( | ||
HttpResponseGenerator.getFoundResponse("/index.html"), | ||
HttpCookie.of("JSESSIONID=" + session.getId())); | ||
} | ||
|
||
private String addCookie(final String response, final HttpCookie cookie) { | ||
return response | ||
.concat("\n") | ||
.concat(StandardHttpHeader.SET_COOKIE.getValue() + ": " + cookie.toString()); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
tomcat/src/main/java/org/apache/coyote/handler/RegisterHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package org.apache.coyote.handler; | ||
|
||
import org.apache.http.HttpMethod; | ||
import org.apache.http.request.HttpRequest; | ||
import org.apache.http.response.HttpResponseGenerator; | ||
|
||
import com.techcourse.db.InMemoryUserRepository; | ||
import com.techcourse.model.User; | ||
|
||
public class RegisterHandler extends Handler { | ||
|
||
private static final RegisterHandler INSTANCE = new RegisterHandler(); | ||
|
||
private RegisterHandler() { | ||
} | ||
|
||
public static RegisterHandler getInstance() { | ||
return INSTANCE; | ||
} | ||
|
||
public String handle(final HttpRequest httpRequest) { | ||
if (httpRequest.isSameMethod(HttpMethod.GET)) { | ||
return StaticResourceHandler.getInstance().handle(new HttpRequest("GET", "/register.html", "HTTP/1.1", null, null)); | ||
} | ||
|
||
if (httpRequest.isSameMethod(HttpMethod.POST)) { | ||
return processRegisterPostRequest(httpRequest); | ||
} | ||
|
||
return StaticResourceHandler.getInstance().handle(new HttpRequest("GET", "/401.html", "HTTP/1.1", null, null)); | ||
} | ||
|
||
private String processRegisterPostRequest(final HttpRequest httpRequest) { | ||
String[] body = httpRequest.getBody().split("&"); | ||
String account = body[0].split("=")[1]; | ||
String email = body[1].split("=")[1]; | ||
String password = body[2].split("=")[1]; | ||
InMemoryUserRepository.save(new User(account, password, email)); | ||
return HttpResponseGenerator.getFoundResponse("/index.html"); | ||
} | ||
} |
Oops, something went wrong.