使用非常简单的缓存语义:如果参数相同(当然URL相同),那么它就是一个命中。那可能吗?推荐?
答案 0 :(得分:90)
如果使用适当的标题,则第9.5节(POST)中的相应RFC 2616允许将响应缓存到POST消息。
除非响应,否则对此方法的响应不可缓存 包括适当的Cache-Control或Expires头字段。然而, 303(请参阅其他)响应可用于指导用户代理 检索可缓存的资源。
请注意,相同的RFC在第13节(在HTTP中缓存)中明确指出缓存必须在POST 请求之后使相应的实体无效。
某些HTTP方法必须导致 缓存以使实体无效。这是 无论是由...提到的实体 请求URI,或由位置或 内容 - 位置标题(如果存在)。 这些方法是:
- PUT - DELETE - POST
我不清楚这些规范如何允许有意义的缓存。
答案 1 :(得分:63)
根据RFC 2616第9.5节:
“对POST方法的响应不是 可缓存,除非响应 包括适当的Cache-Control或 过期标题字段。“
所以,是的,你可以缓存POST请求响应,但只有它到达时才有适当的头。在大多数情况下,您不希望缓存响应。但在某些情况下 - 例如,如果您没有在服务器上保存任何数据 - 这是完全合适的。
请注意,无论标头如何,许多浏览器(包括当前的Firefox 3.0.10)都不会缓存POST响应。在这方面,IE表现得更聪明。
现在,我想澄清一些关于RFC 2616 S. 13.10的混淆。对于URI的POST方法不会“使用于缓存的资源无效”,正如一些人在此处所述。它使该URI的先前缓存版本过时,即使其缓存控制标题指示较长持续时间的新鲜度。
答案 2 :(得分:31)
<强>总体:强>
基本上POST is not an idempotent operation。所以你不能用它来缓存。 GET应该是幂等操作,因此它通常用于缓存。
请参阅HTTP 1.1 RFC 2616 S. 9.1的第9.1节。
除了GET方法的语义之外:
POST方法本身在语义上意味着向资源发布内容。 POST无法缓存,因为如果你做了一次vs两次而不是三次,那么你每次都在改变服务器的资源。每个请求都很重要,应该发送到服务器。
PUT方法本身在语义上意味着放置或创建资源。它是一个幂等操作,但它不会用于缓存,因为在此期间可能发生了DELETE。
DELETE方法本身在语义上意味着删除资源。它是一个幂等操作,但它不会用于缓存,因为PUT可能同时发生。
关于客户端缓存:
即使Web浏览器具有先前POST操作的响应,它也会始终转发您的请求。例如,您可以在几天内发送带有Gmail的电子邮件。它们可能是相同的主题和正文,但两封电子邮件都应该发送。
关于代理缓存:
将邮件转发到服务器的代理HTTP服务器永远不会缓存除GET或HEAD请求之外的任何内容。
关于服务器缓存:
默认情况下,服务器不会通过检查其缓存自动处理POST请求。但是当然可以将POST请求发送到您的应用程序或加载项,并且您可以拥有自己的缓存,这些缓存可以在参数相同时读取。
资源无效:
检查HTTP 1.1 RFC 2616 S. 13.10表明POST方法应该使资源无效以进行缓存。
答案 3 :(得分:6)
如果您确实缓存了POST响应,那么它必须位于Web应用程序的方向上。这就是&#34;对此方法的响应是不可缓存的,除非响应包含适当的Cache-Control或Expires头字段。&#34;
可以安全地假设知道POST结果是否是幂等的应用程序决定是否附加必要和适当的缓存控制头。如果存在允许缓存的标题,则应用程序会告诉您POST实际上是超级GET;只需要使用POST,因为执行幂等操作所需的数据(使用URI作为缓存键)是不必要的和不相关的。
在这个假设下,可以从缓存中提供GET&#39;
无法附加必要且正确的标头以区分可缓存和不可缓存的POST响应的应用程序因任何无效的缓存结果而出错。
也就是说,每个命中缓存的POST都需要使用条件头进行验证。这是刷新缓存内容所必需的,以避免在对象的生命周期到期之前,POST的结果不会反映在对请求的响应中。
答案 4 :(得分:4)
如果它实际上并未改变您网站上的数据,则应该是GET请求。即使它是一个表单,您仍然可以将其设置为get请求。虽然像其他人指出的那样,你可以缓存POST的结果,但它不具有语义意义,因为POST定义正在改变数据。
答案 5 :(得分:2)
Mark Nottingham分析了何时可以缓存POST的响应。请注意,希望利用缓存的后续请求必须是GET或HEAD请求。另请参阅httpbis
POST不会处理已识别州的陈述,100次中有99次。 但是,有一种情况是这样的;当服务器退出时 它的方式是说这个POST响应是它的URI的表示, 通过设置与请求相同的Content-Location标头 URI。当发生这种情况时,POST响应就像GET响应一样 到相同的URI;它可以被缓存和重用 - 但仅限于未来 GET请求。
答案 6 :(得分:2)
如果您想知道是否可以缓存帖子请求,并尝试研究该问题的答案,那么您可能不会成功。当搜索“缓存发布请求”时,第一个结果就是这个StackOverflow问题。
答案是混淆的,其中包括缓存应如何工作,缓存如何根据RFC工作,缓存应如何根据RFC工作以及缓存在实践中如何工作。让我们从RFC开始,逐步演示浏览器的实际工作方式,然后讨论CDN,GraphQL和其他令人关注的领域。
根据RFC,POST请求必须使缓存无效:
13.10 Invalidation After Updates or Deletions
..
Some HTTP methods MUST cause a cache to invalidate an entity. This is
either the entity referred to by the Request-URI, or by the Location
or Content-Location headers (if present). These methods are:
- PUT
- DELETE
- POST
这种语言建议POST请求不可缓存,但这不是正确的(在这种情况下)。缓存仅对先前存储的数据无效。 RFC(似乎)明确说明是的,您可以缓存POST
个请求:
9.5 POST
..
Responses to this method are not cacheable, unless the response
includes appropriate Cache-Control or Expires header fields. However,
the 303 (See Other) response can be used to direct the user agent to
retrieve a cacheable resource.
尽管使用此语言,但设置Cache-Control
不得将后续的POST
请求缓存到同一资源。 POST
请求必须发送到服务器:
13.11 Write-Through Mandatory
..
All methods that might be expected to cause modifications to the
origin server's resources MUST be written through to the origin
server. This currently includes all methods except for GET and HEAD.
A cache MUST NOT reply to such a request from a client before having
transmitted the request to the inbound server, and having received a
corresponding response from the inbound server. This does not prevent
a proxy cache from sending a 100 (Continue) response before the
inbound server has sent its final reply.
这有什么意义?好吧,您不是在缓存POST
请求,而是在缓存资源。
POST响应正文只能为后续对同一资源的GET请求进行缓存。在POST响应中设置Location
或Content-Location
标头,以传达正文表示的资源。因此,缓存POST请求的唯一技术上有效的方法是将后续GET转移到同一资源。
正确答案都是:
尽管RFC允许将请求缓存到同一资源,但实际上,浏览器和CDN并没有实现此行为,也不允许您缓存POST请求。
来源:
给出以下示例JavaScript应用程序(index.js):
const express = require('express')
const app = express()
let count = 0
app
.get('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.send(msg)
})
.post('/asdf', (req, res) => {
count++
const msg = `count is ${count}`
console.log(msg)
res
.set('Access-Control-Allow-Origin', '*')
.set('Cache-Control', 'public, max-age=30')
.set('Content-Location', 'http://localhost:3000/asdf')
.set('Location', 'http://localhost:3000/asdf')
.status(201)
.send(msg)
})
.set('etag', false)
.disable('x-powered-by')
.listen(3000, () => {
console.log('Example app listening on port 3000!')
})
并给出以下示例网页(index.html):
<!DOCTYPE html>
<html>
<head>
<script>
async function getRequest() {
const response = await fetch('http://localhost:3000/asdf')
const text = await response.text()
alert(text)
}
async function postRequest(message) {
const response = await fetch(
'http://localhost:3000/asdf',
{
method: 'post',
body: { message },
}
)
const text = await response.text()
alert(text)
}
</script>
</head>
<body>
<button onclick="getRequest()">Trigger GET request</button>
<br />
<button onclick="postRequest('trigger1')">Trigger POST request (body 1)</button>
<br />
<button onclick="postRequest('trigger2')">Trigger POST request (body 2)</button>
</body>
</html>
安装NodeJS,Express,然后启动JavaScript应用程序。在浏览器中打开网页。尝试几种不同的方案来测试浏览器的行为:
这表明,即使您可以设置Cache-Control
和Content-Location
响应标头,也无法使浏览器缓存HTTP POST请求。
浏览器的行为不是可配置的,但是如果您不是浏览器,则不一定受RFC规则的约束。
如果您正在编写应用程序代码,则不会阻止您显式缓存POST请求(伪代码):
if (cache.get('hello')) {
return cache.get('hello')
} else {
response = post(url = 'http://somewebsite/hello', request_body = 'world')
cache.put('hello', response.body)
return response.body
}
CDN,代理和网关也不一定必须遵循RFC。例如,如果您将Fastly用作CDN,则Fastly允许您将custom VCL逻辑写入cache POST requests。
是否应缓存POST请求取决于上下文。
例如,您可以使用POST查询Elasticsearch或GraphQL,其中基础查询是幂等的。在这种情况下,根据用例来缓存响应可能有意义,也可能没有意义。
在RESTful API中,POST请求通常会创建资源,因此不应进行缓存。这也是RFC对POST的理解,即它不是幂等操作。
如果您使用的是GraphQL,并且需要跨CDN和浏览器进行HTTP缓存,请考虑使用GET method而不是POST发送查询是否满足您的要求。需要注意的是,不同的浏览器和CDN可能具有不同的URI长度限制,但是操作安全列表(查询白名单)作为面向外部生产GraphQL应用程序的最佳实践,可以缩短URI。
答案 7 :(得分:1)
当然有可能。如果你想捕获发送到服务器的POST请求,并缓存发回的数据,以后再发送 - 没有汗水。
棘手的部分涉及“状态”。您如何确定要发送回用户的数据真的应该是相同的?如果他的cookie发生了变化怎么办 - 这会改变你想要发回的数据吗?
如果用户向您的主页发出了POST请求,并且自上次他这样做以来,另一位用户向他发送了一条消息(使用您网站内的某个系统。)您必须将其识别为更改 - 状态,并发送新版本的主页,并在下次加载主页时向用户发送有关该消息的通知。即使POST参数相同。
答案 8 :(得分:-1)
使用firefox 27.0&amp;使用httpfox,2014年5月19日,我看到了一行: 00:03:58.777 0.488 657(393)POST(缓存)text / html https://users.jackiszhp.info/S4UP
显然,post方法的响应是缓存的,它也是https。 令人难以置信!
答案 9 :(得分:-2)
POST用于有状态的Ajax。返回POST的缓存响应会破坏通信通道和接收消息的副作用。这非常非常糟糕。追踪也是一种真正的痛苦。强烈推荐反对。
一个简单的例子就是一个消息,作为副作用,本周支付你的工资10,000美元。你不想得到“好的,它经历了!”上周缓存的页面。其他更复杂的现实案例导致类似的欢闹。