ESI清漆不一样的iframe或链接标签在工作中的一个浏览器,它不连接到您提供的任何网址。 ESI只是在清漆内启动一个新的请求,并通过工作流程(vcl_recv等)。
你期望varnish的行为像一个http客户端,解析url,设置授权头,设置一个主机头为api.dev:8081并启动一个新的http连接/请求,它不会。在这种情况下,我猜想它会启动一个新的req,将req.url设置为/app.php/next,继承父资源(包含esi标记)的请求中的标头,或者可能完全忽略esi标记。
来完成你想做的事情的方式是(在vcl_recv):
if (req.esi_level > 0 && req.url == "/app.php/next") {
set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]"
return (pass);
}
然后ESI标记看起来应该<esi:include src="/app.php/next" />
如果您需要ESI要求打一个不同的后端服务器,则需要到该服务器添加为不同的命名后端:
backend authorization_needed {
.host = "api.dev";
.port = "8081";
}
和vcl_recv,告诉清漆用它来ESI要求:
if (req.esi_level > 0 && req.url == "/app.php/next") {
set req.http.Authorization = "BASIC [base64 encoded admin:adminpass]"
set req.backend = authorization_needed;
return (pass);
}
您可能还需要设置req.http.Host,如果后端响应的虚拟主机不是“api.dev”则阻止。
更新:
由于基本授权从客户端来了,你在呼唤回报(通)时req.http.Authorization存在,清漆不会ESI过程的页面。您必须在vcl_fetch()中明确启用esi,而通过时不会调用它。
所以要通过授权的ESI片段而不是父页面,改变vcl_rev:
if (req.http.Authorization && req.esi_level == 0) {
set req.http.X-Esi-Authorization = req.http.Authorization;
unset req.http.Authorization;
}
else if (req.http.X-Esi-Authorization && req.esi_level > 0) {
set req.http.Authorization = req.http.X-Esi-Authorization;
return (pass);
}
,并加入到vcl_fetch:
if (req.http.X-Esi-Authorization) {
set beresp.do_esi = true;
}
的净效应是父母响应可缓存并将处理esi,esi片段本身将始终通过客户端的授权标头传递到后端。
你好,谢谢你的回答。如果我试图在标记中这样做,那是因为用户和密码会有_many_用户和密码用于同一个URL。所以,我不能直接在Varnish的conf中设置它。那么,你认为不可能做到这一点? –
Peekmo
这是一个非常典型的用例。我已经更新了答案。 –
非常感谢!有用 ! – Peekmo