Skip to content

[logging] 본문 캐싱 후 form 요청 파라미터가 사라지는 문제 수정 - #6

Merged
ZaMan0806 merged 5 commits into
masterfrom
fix/form-parameters-after-body-caching
Nov 12, 2026
Merged

ZaMan0806 merged 5 commits into
masterfrom
fix/form-parameters-after-body-caching

Conversation

@ZaMan0806

@ZaMan0806 ZaMan0806 commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

개요

LoggingFilter를 거친 application/x-www-form-urlencoded POST 요청에서 본문 파라미터가 사라지는 문제를 수정하고, 버전을 2.0.1로 올립니다.

원인

CachedRequestBodyWrapper는 생성될 때 request.inputStream을 끝까지 읽어 본문을 캐시합니다. 그런데 getParameter*()는 다시 구현하지 않아 원본 요청으로 위임됩니다. Tomcat은 getInputStream()이 이미 호출된 요청의 form 본문을 파라미터로 해석하지 않으므로, 컨트롤러의 @RequestParam에는 쿼리스트링 값만 들어옵니다.

JSON 요청은 캐시한 본문을 Jackson이 getInputStream()으로 다시 읽기 때문에 영향이 없습니다. 1.5와 2.0 모두 같은 코드라서 두 버전 모두 해당합니다.

변경 사항

  • CachedRequestBodyWrapper가 getParameter, getParameterMap, getParameterNames, getParameterValues를 직접 구현합니다.
    • form POST이면 원본 요청의 쿼리스트링 파라미터 뒤에 캐시한 본문의 파라미터를 붙입니다. 같은 이름이면 컨테이너와 같이 쿼리 값이 앞에 옵니다.
    • 본문은 요청의 문자 인코딩(없으면 UTF-8)으로 디코딩합니다. 잘못 인코딩된 쌍은 컨테이너와 같이 건너뜁니다.
    • 서블릿 명세상 form 본문이 파라미터가 되는 것은 POST뿐입니다. PUT/PATCH/DELETE는 Spring FormContentFilter가 캐시한 본문을 다시 읽어 처리하므로 기존 동작을 그대로 둡니다.
  • 버전을 2.0.1로 올리고 README의 설치 예시를 맞췄습니다.

테스트

  • LoggingFilterFormRequestTest를 추가했습니다. MockMvc는 form 본문을 미리 파라미터로 채워 주기 때문에 이 버그를 재현하지 못합니다. 그래서 RANDOM_PORT로 실제 Tomcat을 띄워 검증합니다.
    • form 본문 파라미터(+, %2B 디코딩 포함)와 쿼리 파라미터가 모두 컨트롤러에 전달되는지
    • 같은 이름의 쿼리 값과 본문 값이 쿼리 → 본문 순서로 모두 유지되는지
    • 한글 쿼리 값과 본문 값이 같은 인코딩(UTF-8)으로 디코딩되는지
    • PUT form 본문을 FormContentFilter가 정확히 한 번 채우는지
    • 모든 요청이 실제로 CachedRequestBodyWrapper를 거쳤는지(sdk.logging.enabled=true를 명시해 전제가 조용히 깨지지 않게 함)
  • 수정 전에는 본문 파라미터 테스트가 실패하고 수정 후에는 통과하는 것을 확인했습니다.
  • ./gradlew build (ktlint 포함, 전체 42개 테스트) 통과

리뷰 반영

  • 파라미터 배열을 복사해 반환해서, 호출자가 배열을 고쳐도 캐시가 오염되지 않습니다.
  • 잘못 인코딩되어 건너뛴 파라미터는 이름만 DEBUG 로그로 남깁니다.
  • README 로깅 절에 form 파라미터 복원 동작을 적었습니다. 컨테이너의 maxPostSize/maxParameterCount가 적용되지 않는다는 점과 not-logging-urls 권장 사항도 함께 적었습니다.

배포

머지 후 master에서 2.0.1 태그로 릴리즈를 게시하면 CD가 Maven Central에 배포합니다.

@pr-agent-demo pr-agent-demo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This PR fixes a bug where application/x-www-form-urlencoded POST request parameters were lost after LoggingFilter cached the request body.

Key changes:

  • CachedRequestBodyWrapper now implements getParameter, getParameterMap, getParameterNames, and getParameterValues.
  • For form POST requests, it merges query-string parameters with parameters parsed from the cached request body.
  • Query parameters remain first for duplicate names, matching servlet-container behavior.
  • Form body parsing uses the request charset, falling back to UTF-8, and skips malformed encoded pairs rather than failing the request.
  • PUT/PATCH/DELETE behavior is left unchanged because Spring’s FormContentFilter handles those bodies.
  • Adds integration tests using a real Tomcat server to verify that form body parameters reach the controller after body caching.
  • Bumps version from 2.0 to 2.0.1 and updates README install examples.

6 inline comment(s)

@ZaMan0806
ZaMan0806 merged commit 81721ed into master Nov 12, 2026
1 check passed
@ZaMan0806
ZaMan0806 deleted the fix/form-parameters-after-body-caching branch November 12, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants