- mysql
- nginx
- string
- select
- Django
- jpa
- 프로그래머스
- SSL
- spring mvc
- Docker
- spring
- springboot
- sql
- 자바
- hibernate
- DI
- ORM
- 스프링부트
- 문자열
- @transactional
- join
- PYTHON
- spring security 6
- 스프링
- java
- spring boot
- AWS
- 1차원 배열
- static
- 데이터베이스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
개발하는 자몽
[Spring Boot / Error] Required request body is missing 본문
[Spring Boot / Error] Required request body is missing
jaamong 2024. 7. 13. 09:26상황
@RestController
public class RestController {
@PostMapping("/aaa")
public ResponseEntity<Void> aaa(@RequestBody @Valid final RequestDto dto) {
...
return ResponseEntity.status(HttpStatus.CREATED).build();
}
...
}
해당 메서드에
원인
디버깅을 진행했을 때 직접 작성한 코드 내에서는 반환값이 정상적으로 201로 저장되었다. 그러다가 신기하게도 컨트롤러 전에 이미 거쳤을
계속 디버깅을 하다 보니
Spring에서 모든 요청들은 컨트롤러에 도달하기 전에 Filter, Interceptor 등을 거친다. 직접 정의한 필터도 예외는 아니다.
아래 코드는 직접 정의한 필터이다.
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
if(특정 조건) {
filterChain.doFilter(request, response); //first doFilter
}
String token = getJwtFromRequest(request);
if (StringUtils.hasText(token)) {
...
}
filterChain.doFilter(request, response); //second doFilter
}
특정 조건인 경우에 토큰 검증 로직을 수행하지 않도록 바로
실제로 아래와 같이 로깅을 해놓고 문제가 되는 API를 호출하면 다음과 같이 콘솔창에 출력되는 것을 확인할 수 있다.
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
if (특정 조건) {
log.info("before first doFilter");
filterChain.doFilter(request, response); //first doFilter
log.info("after first doFilter");
}
log.info("here");
String token = getJwtFromRequest(request);
if (StringUtils.hasText(token)) { //특정 조건의 경우 토큰이 필요없는 요청이므로 통과 못함
...
}
log.info("before second doFilter");
filterChain.doFilter(request, response); //second doFilter
}
...
before first doFilter
after first doFilter
here
before second doFilter
...
첫 번째
따라서 그다음 로직을 수행하게 되어 가장 아래에 있는
해결
해결방법은 간단하다. 필터를 두 번 거치지 않도록 하면 되므로 특정 조건의 경우
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
String token = getJwtFromRequest(request);
if (StringUtils.hasText(token)) {
...
}
filterChain.doFilter(request, response); //second doFilter
}
기존에 특정 조건을 확인했던 코드는 쓸데없이 검증하지 않도록 작성했던 것이다. 그러나 이미 아래에
이후 원하는 대로 정상 작동했다!
🔖참고
https://upcurvewave.tistory.com/614
'Java & Kotlin > Spring' 카테고리의 다른 글
[JPA Error] No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call (0) | 2024.10.23 |
---|---|
[JPA] 임베디드 타입(@Embeddable, @Embedded)에 관하여 (0) | 2024.08.23 |
[Spring Security] 예외 처리하기 (0) | 2024.06.21 |
[Spring Security] 역할/권한 구현하기 (0) | 2024.06.14 |
[Spring Security] 토큰 기반 로그인/로그아웃 구현하기 (0) | 2024.06.08 |