Skip to content

Commit

Permalink
[Tomcat 구현하기 1 - 2단계] 페드로(류형욱) 미션 제출합니다. (#578)
Browse files Browse the repository at this point in the history
* test(FileTest): FileTest 학습 테스트 풀이

* test(IOStreamTest): IOStreamTest 학습 테스트 풀이

* Style(StubSocket): `@Override` 어노테이션 명시

* feat: Http 요청, 응답 메시지를 관리하는 객체 구현

* feat(Http11Processor): 정적 리소스 응답 기능 구현

* feat(Http11Processor): 확장자에 따라 Content-Type을 지정하도록 변경

* feat(ApiRouter): HTTP 메서드와 Path 별 매핑 관리 객체 추가

* refactor(StaticResourceManager): 클래스명 변경

* refactor(HttpResponse): Body 설정 시 Content-Length를 자동으로 계산하도록 변경

* feat(LoginController): GET 메서드를 통한 로그인 기능 구현

* feat(RegisterController): 회원가입 페이지 응답 기능 구현

* feat(HttpRequest): Form 형태의 Body 지원

* feat(Http11Processor): UUID 형태의 JSESSIONID 쿠키 발급 기능 구현

* test: HTTP 활용하기 학습 테스트 풀이

* feat: 세션을 활용한 로그인 유지 기능 구현

* refactor(Http11Processor): Http Message Body 읽는 로직 수정
  • Loading branch information
hw0603 authored Sep 7, 2024
1 parent 7e91356 commit 2983d6f
Show file tree
Hide file tree
Showing 23 changed files with 852 additions and 140 deletions.
2 changes: 1 addition & 1 deletion study/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.apache.commons:commons-lang3:3.14.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1'
implementation 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.4.1'
implementation 'com.github.jknack:handlebars-springmvc:4.4.0'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.assertj:assertj-core:3.26.0'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package cache.com.example.cachecontrol;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand All @@ -9,5 +13,18 @@ public class CacheWebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(new CacheControlInterceptor())
.addPathPatterns("/");
}
}

class CacheControlInterceptor implements HandlerInterceptor {

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
response.setHeader("Cache-Control", "no-cache, private");
}
}

Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
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;

@Configuration
public class EtagFilterConfiguration {

// @Bean
// public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
// return null;
// }
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
ShallowEtagHeaderFilter filter = new ShallowEtagHeaderFilter();
FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<>(filter);
filterRegistrationBean.addUrlPatterns("/etag");
filterRegistrationBean.addUrlPatterns("/resources/*");
return filterRegistrationBean;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cache.com.example.version;

import java.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

Expand All @@ -20,6 +22,7 @@ public CacheBustingWebConfig(ResourceVersion version) {
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler(PREFIX_STATIC_RESOURCES + "/" + version.getVersion() + "/**")
.addResourceLocations("classpath:/static/");
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)).cachePublic());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cache.com.example.version;

import com.github.jknack.handlebars.springmvc.HandlebarsViewResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;

@Configuration
public class HandlebarsConfig {

private final VersionHandlebarsHelper versionHandlebarsHelper;

public HandlebarsConfig(VersionHandlebarsHelper versionHandlebarsHelper) {
this.versionHandlebarsHelper = versionHandlebarsHelper;
}

@Bean
public ViewResolver handlebarsViewResolver() {
HandlebarsViewResolver viewResolver = new HandlebarsViewResolver();
viewResolver.registerHelper("staticUrls", versionHandlebarsHelper);

viewResolver.setPrefix("classpath:/templates/");
viewResolver.setSuffix(".html");

return viewResolver;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package cache.com.example.version;

import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import pl.allegro.tech.boot.autoconfigure.handlebars.HandlebarsHelper;
import org.springframework.stereotype.Component;

@HandlebarsHelper
public class VersionHandlebarsHelper {
@Component
public class VersionHandlebarsHelper implements Helper<Object> {

private static final Logger log = LoggerFactory.getLogger(VersionHandlebarsHelper.class);

Expand All @@ -22,4 +23,9 @@ public String staticUrls(String path, Options options) {
log.debug("static url : {}", path);
return String.format("/resources/%s%s", version.getVersion(), path);
}

@Override
public Object apply(Object context, Options options) {
return staticUrls(context.toString(), options);
}
}
6 changes: 3 additions & 3 deletions study/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
handlebars:
suffix: .html

server:
compression:
enabled: true
min-response-size: 10
tomcat:
accept-count: 1
max-connections: 1
Expand Down
40 changes: 18 additions & 22 deletions study/src/test/java/study/FileTest.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,49 @@
package study;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import java.util.Objects;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
* 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다.
* File 클래스를 사용해서 파일을 읽어오고, 사용자에게 전달한다.
* 웹서버는 사용자가 요청한 html 파일을 제공 할 수 있어야 한다. File 클래스를 사용해서 파일을 읽어오고, 사용자에게 전달한다.
*/
@DisplayName("File 클래스 학습 테스트")
class FileTest {

/**
* resource 디렉터리 경로 찾기
*
* File 객체를 생성하려면 파일의 경로를 알아야 한다.
* 자바 애플리케이션은 resource 디렉터리에 HTML, CSS 같은 정적 파일을 저장한다.
* resource 디렉터리의 경로는 어떻게 알아낼 수 있을까?
* <p>
* File 객체를 생성하려면 파일의 경로를 알아야 한다. 자바 애플리케이션은 resource 디렉터리에 HTML, CSS 같은 정적 파일을 저장한다. resource 디렉터리의 경로는 어떻게 알아낼 수
* 있을까?
*/
@Test
void resource_디렉터리에_있는_파일의_경로를_찾는다() {
final String fileName = "nextstep.txt";

// todo
final String actual = "";

final String actual = Objects.requireNonNull(getClass().getClassLoader().getResource(fileName)).getPath();
// final String actual = Objects.requireNonNull(getClass().getResource("/" + fileName)).getPath(); // 동일 결과
assertThat(actual).endsWith(fileName);
}

/**
* 파일 내용 읽기
*
* 읽어온 파일의 내용을 I/O Stream을 사용해서 사용자에게 전달 해야 한다.
* File, Files 클래스를 사용하여 파일의 내용을 읽어보자.
* <p>
* 읽어온 파일의 내용을 I/O Stream을 사용해서 사용자에게 전달 해야 한다. File, Files 클래스를 사용하여 파일의 내용을 읽어보자.
*/
@Test
void 파일의_내용을_읽는다() {
void 파일의_내용을_읽는다() throws IOException {
final String fileName = "nextstep.txt";

// todo
final Path path = null;
String pathStr = Objects.requireNonNull(getClass().getClassLoader().getResource(fileName)).getPath();
final Path path = Path.of(pathStr);

// todo
final List<String> actual = Collections.emptyList();
final List<String> actual = Files.readAllLines(path);

assertThat(actual).containsOnly("nextstep");
}
Expand Down
Loading

0 comments on commit 2983d6f

Please sign in to comment.