Spring MVC响应标头:ETag对GET请求有双引号,但对PUT请求没有



我们在服务中将Spring MVC从4.0升级到4.3。它导致"GET"方法的响应标头中的ETag格式发生更改。进行"GET"调用的客户端将获得在响应标头中带有双引号的ETag。以前,响应标头中的ETag没有"GET"方法的双引号。

例如:

Now: etag →"TVMzTWFpbmxpbmVEZXZvLTI5ODIxMQ" 
Previously: etag →TVMzTWFpbmxpbmVEZXZvLTI5ODIxMQ

和以前一样,"PUT"请求的响应在Headers中的ETag周围没有双引号。

有人知道为什么吗?

在Spring 4.2.x之前,没有对ETag标头进行管理。从那时起,它就被引入了HttpEntityMethodProcessor中。该类随着时间的推移而发展,并且ETag报头的管理尊重RFC(或者足够接近)。

正如您在本次提交中看到的,Spring团队修复了其管理层的一个问题:

修复响应中丢失的ETag/LastModified标头

在此提交之前,HttpEntityMethodProcessor将避免在调用前写入ETag/Last Modified响应标头CCD_ 2来处理条件请求。这样做是为了避免由于标头已存在而导致响应标头值重复写入底层servlet响应。

这对于GET/HEAD请求仍然是必要的,因为这是正确的由CCD_ 3处理。但是HttpEntityMethodProcessor不应为PUT/PATCH/POST响应,因为开发人员正在目的,并且应该控制局势——而CCD_ 5在这些情况下不写入这些报头。

修改后的代码的相关部分在这里。

因此,基本上,当手动添加ETag标头时,如果GETHEAD方法的状态为200框架会删除它,然后重新创建它。这就是为什么使用PUT时没有双引号的原因。

在HttpEntityMethodProcessor:中

if (inputMessage.getMethod() == HttpMethod.GET || inputMessage.getMethod() == HttpMethod.HEAD) {
responseHeaders.remove(HttpHeaders.ETAG);
responseHeaders.remove(HttpHeaders.LAST_MODIFIED);
}

然后在Servlet WebRequest中:

private String padEtagIfNecessary(String etag) {
if (!StringUtils.hasLength(etag)) {
return etag;
}
if ((etag.startsWith(""") || etag.startsWith("W/"")) && etag.endsWith(""")) {
return etag;
}
return """ + etag + """;
}

正如您所看到的,这尊重RFC:的第2.4章

2.4.何时使用实体标签和最后修改日期

在对GET或HEAD的200(OK)响应中,原始服务器:

o应发送实体标记验证器,除非不可行生成一个。

o如果性能考虑支持使用弱实体标记,或者如果发送强实体标记是不可行的。

o如果可行,则应发送"上次修改"值。

换句话说,源服务器的首选行为是成功发送强实体标记和Last Modified值对检索请求的响应。

但我发现它不向后兼容,并破坏了开发人员在这些版本之前可以使用的内容,而不可能跳过/覆盖他们所做的内容。

以下是MDN对ETag的描述(更清晰)。

希望它有助于理解。

最新更新