我们正在开发一个使用React和Redux的网站。我们刚刚在我们的API上添加了一个Varnish缓存,虽然在Postman上测试API时一切似乎都运行良好,但这在我们的网站上运行不正常。
出于某种原因,所有API查询在第一次完成时都会失败并显示401状态代码,但是,它们在第一次失败后工作正常。
一旦我们添加了Varnish缓存,这种行为就开始发生了,但是,我们无法找到错误。
Varnish配置文件如下:
vcl 4.0;
backend default {
.host = ...;
.port = ...;
}
sub vcl_backend_response {
set beresp.ttl = 5m;
# Don't cache non-200 responses
if ( beresp.status != 200 ) {
set beresp.ttl = 0s;
}
# Don't cache if "no-cache" or "private" on cache control
if (beresp.http.cache-control ~ "(no-cache|private)" ||
beresp.http.pragma ~ "no-cache") {
set beresp.ttl = 0s;
}
}
sub vcl_recv {
# Do not cache Healthcheck call
if (req.url == "/api/healthcheck") {
return (pass);
}
# Do not cache POST methods
if (req.method == "POST") {
return (pass);
}
# Do not cache users' calls as each user will be different
if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
return (pass);
}
# Ensure that cache is enabled to any call to the API
if (req.url ~ "/api/*") {
return (hash);
}
}
sub vcl_deliver {
if (req.url ~ "/api/*") {
set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
return (deliver);
}
}
可能会发生什么?
非常感谢
答案 0 :(得分:1)
我终于找到了我的问题,我的配置文件中缺少一个返回(哈希)。
正确的配置文件如下:
vcl 4.0;
backend default {
.host = ...;
.port = ...;
}
sub vcl_backend_response {
set beresp.ttl = 5m;
# Don't cache non-200 responses
if ( beresp.status != 200 ) {
set beresp.ttl = 0s;
}
# Don't cache if "no-cache" or "private" on cache control
if (beresp.http.cache-control ~ "(no-cache|private)" ||
beresp.http.pragma ~ "no-cache") {
set beresp.ttl = 0s;
}
}
sub vcl_recv {
# Do not cache Healthcheck call
if (req.url == "/api/healthcheck") {
return (pass);
}
if (req.method != "GET" && req.method != "HEAD") {
# We only deal with GET and HEAD by default
return (pass);
}
# Do not cache users' calls as each user will be different
if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
return (pass);
}
return (hash);
}
sub vcl_deliver {
if (req.url ~ "/api/*") {
set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
return (deliver);
}
}
答案 1 :(得分:0)
我想我还会发布将Varnish应用于需要某种授权的API请求的人(即使你说你解决了你的问题)。
如果您碰巧需要对 {/ 1>}范围之外的路径进行授权,那么401可能仍会发生,因为这些请求可能仍会被缓存。
此外,您也可以(并且出于性能原因)缓存经过身份验证的请求。对此和401错误的简单解决方案是通过令牌标头的值来改变您的缓存。
您可以更改应用程序代码,只需发送额外的HTTP标头:dbMetadataWriter.writeMetadata(successReports);
。这足以指示Varnish缓存在API的不同用户之间应该有所不同。
如果你无法调整你的应用程序,那么一些VCL可以提供帮助:
\/api\/v[a-zA-Z0-9\.]+\/users\/.*
P.S。通常不建议将"尾随" Vary: X-Token
中的sub vcl_backend_response {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-Token";
} elsif (beresp.http.Vary !~ "X-Token") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-Token";
}
...
}
以确保builtin vcl_recv例程仍然可以运行。