Skip to content

Refactor ETag-related logic for improved readability #33770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public boolean checkNotModified(String etag) {

@Override
public boolean checkNotModified(@Nullable String etag, long lastModifiedTimestamp) {
if (this.notModified) {
if (isNotModified()) {
return true;
}

Expand All @@ -213,6 +213,8 @@ public boolean checkNotModified(@Nullable String etag, long lastModifiedTimestam

// Evaluate conditions in order of precedence.
// See https://datatracker.ietf.org/doc/html/rfc9110#section-13.2.2

// 1) If-Match
if (validateIfMatch(etag)) {
updateResponseStateChanging(etag, lastModifiedTimestamp);
return this.notModified;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private void updateResponse(HttpServletRequest request, HttpServletResponse resp
Assert.notNull(wrapper, "ContentCachingResponseWrapper not found");
HttpServletResponse rawResponse = (HttpServletResponse) wrapper.getResponse();

if (isEligibleForEtag(request, wrapper, wrapper.getStatus(), wrapper.getContentInputStream())) {
if (isEligibleForEtag(request, wrapper)) {
String eTag = wrapper.getHeader(HttpHeaders.ETAG);
if (!StringUtils.hasText(eTag)) {
eTag = generateETagHeaderValue(wrapper.getContentInputStream(), this.writeWeakETag);
Expand All @@ -142,12 +142,10 @@ private void updateResponse(HttpServletRequest request, HttpServletResponse resp
* </ul>
* @param request the HTTP request
* @param response the HTTP response
* @param responseStatusCode the HTTP response status code
* @param inputStream the response body
* @return {@code true} if eligible for ETag generation, {@code false} otherwise
*/
protected boolean isEligibleForEtag(HttpServletRequest request, HttpServletResponse response,
int responseStatusCode, InputStream inputStream) {
protected boolean isEligibleForEtag(HttpServletRequest request, HttpServletResponse response) {
int responseStatusCode = response.getStatus();

if (!response.isCommitted() &&
responseStatusCode >= 200 && responseStatusCode < 300 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,19 +300,25 @@ public boolean checkNotModified(String etag) {

@Override
public boolean checkNotModified(@Nullable String eTag, Instant lastModified) {
if (isNotModified()) {
return true;
}

HttpStatusCode status = getResponse().getStatusCode();
if (this.notModified || (status != null && !HttpStatus.OK.equals(status))) {
return this.notModified;
if (status != null && !HttpStatus.OK.equals(status)) {
return false;
}

// Evaluate conditions in order of precedence.
// See https://datatracker.ietf.org/doc/html/rfc9110#section-13.2.2

// 1) If-Match
if (validateIfMatch(eTag)) {
updateResponseStateChanging(eTag, lastModified);
return this.notModified;
}
// 2) If-Unmodified-Since
else if (validateIfUnmodifiedSince(lastModified)) {
if (validateIfUnmodifiedSince(lastModified)) {
updateResponseStateChanging(eTag, lastModified);
return this.notModified;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package org.springframework.web.filter;

import java.io.InputStream;

import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -49,18 +47,17 @@ void isEligibleForEtag() {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();

assertThat(filter.isEligibleForEtag(request, response, 200, InputStream.nullInputStream())).isTrue();
assertThat(filter.isEligibleForEtag(request, response, 300, InputStream.nullInputStream())).isFalse();
assertThat(filter.isEligibleForEtag(request, response)).isTrue();

request = new MockHttpServletRequest("HEAD", "/hotels");
assertThat(filter.isEligibleForEtag(request, response, 200, InputStream.nullInputStream())).isFalse();
assertThat(filter.isEligibleForEtag(request, response)).isFalse();

request = new MockHttpServletRequest("POST", "/hotels");
assertThat(filter.isEligibleForEtag(request, response, 200, InputStream.nullInputStream())).isFalse();
assertThat(filter.isEligibleForEtag(request, response)).isFalse();

request = new MockHttpServletRequest("POST", "/hotels");
request.addHeader("Cache-Control","must-revalidate, no-store");
assertThat(filter.isEligibleForEtag(request, response, 200, InputStream.nullInputStream())).isFalse();
assertThat(filter.isEligibleForEtag(request, response)).isFalse();
}

@Test
Expand Down Expand Up @@ -172,7 +169,7 @@ void filterWriter() throws Exception {
}

@Test // SPR-12960
public void filterWriterWithDisabledCaching() throws Exception {
void filterWriterWithDisabledCaching() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType(TEXT_PLAIN_VALUE);
Expand Down Expand Up @@ -257,7 +254,7 @@ void filterSendRedirect() throws Exception {
}

@Test // SPR-13717
public void filterFlushResponse() throws Exception {
void filterFlushResponse() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();

Expand Down
Loading