java - 根据规范,在以毫秒为单位的日期上,evaluatePreconditions 的正确行为是什么?
问题描述
在将我的 JAX-RS 应用程序从 Jersey 迁移到 Quarkus/Resteasy 时,我遇到了使用evaluatePreconditions(Date lastModified)
. 实际上,在我的用例中,最后修改的日期包含毫秒,不幸的是标题的日期格式If-Modified-Since
并且Last-Modified
不支持毫秒,正如我们在RFC 2616中看到的那样。
Jersey 从提供的日期开始修剪毫秒(如我们在此处看到的),而在 Resteasy 中,日期没有被修改,因此它实际上比较了If-Modified-Since
具有不同精度(分别为秒与毫秒)的日期(来自标题的日期和提供的日期),这以不匹配而告终,因此是 HTTP 状态代码200
。
说明问题的代码:
@Path("/evaluatePreconditions")
public class EvaluatePreconditionsResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public Response findData(@Context Request request) {
final Data data = retrieveData();
final Date lastModified = Timestamp.valueOf(data.getLastModified());
final Response.ResponseBuilder responseBuilder =
request.evaluatePreconditions(lastModified);
if (responseBuilder == null) {
// Last modified date didn't match, send new content
return Response.ok(data.toString())
.lastModified(lastModified)
.build();
}
// Sending 304 not modified
return responseBuilder.build();
}
private Data retrieveData() {
// Let's assume that we call a service here that provides this value
// The date time is expressed in GMT+2, please adjust it according
// to your timezone
return new Data(
LocalDateTime.of(2020, 10, 2, 10, 23, 16, 1_000_000),
"This is my content"
);
}
public static class Data {
private final LocalDateTime lastModified;
private final String content;
public Data(LocalDateTime lastModified, String content) {
this.lastModified = lastModified;
this.content = content;
}
public LocalDateTime getLastModified() {
return lastModified;
}
@Override
public String toString() {
return content;
}
}
}
与 Jersey 对应的结果:
curl -H "If-Modified-Since: Fri, 02 Oct 2020 08:23:16 GMT" \
-I localhost:8080/evaluatePreconditions
HTTP/1.1 304 Not Modified
...
Quarkus/Resteasy 对应的结果:
curl -H "If-Modified-Since: Fri, 02 Oct 2020 08:23:16 GMT" \
-I localhost:8080/evaluatePreconditions
HTTP/1.1 200 OK
Last-Modified: Fri, 02 Oct 2020 08:23:16 GMT
...
这种行为已经在 Resteasy 项目中提出,但是对于团队来说,修剪日期会添加一个新错误,因为如果在同一秒内多次修改数据/资源,我们会得到一个304
如果我们修剪日期并且200
如果我们没有,这是一个公平的观点。但是,我可能错了,但根据我对RFC 7232的理解,如果可以在同一秒内发生多项修改,我们也应该依赖ETag,这意味着在 JAX-RS 规范中,我们应该使用evaluatePreconditions(Date lastModified, EntityTag eTag)
反而。
那么根据 JAX-RS 规范关于这种特殊情况的正确行为是什么?
解决方案
我认为没有具体说明evaluatePreconditions
方法是否应该减少一秒钟的时间。但是:以不同的精度比较两个时间戳是“不公平的”。您要么应该舍入更精确的那个,要么将精度截断为相同。特别是因为 RFC 7232 甚至提到了 HTTP 标头的“低”精度问题并提出了解决方案(ETag)。
我还发现了一个 SO question with solutions how to compare timestamps with different precision:Compare Date objects with different levels of precision
推荐阅读
- python - 使用 .index() 查找最小元素会产生意想不到的结果
- javascript - 尝试使用 NodeJS 从 MongoDB 限制我的结果并对我的数据进行排序
- vba - 循环保存并关闭每封打开的电子邮件,留下一封打开的邮件
- javascript - 1个用于更多html文件的javascript文件
- woocommerce - 我想隐藏价格为 € 0,00 的产品
- c - 字符串末尾的空字符“\0”
- python - 如何使用 scapy 过滤已经存在的 pcap 文件?
- c# - 引发未处理的异常时阻止 Microsoft Logging
- bash - 比较 SHA-512 加盐哈希,在执行期间显示文件名
- vue.js - Vue Composition API createComponent 子组件