我正在寻找一种方法来配置 Varnish 以处理 Varnish 内的 HTTP 请求。
更具体地说,对于特定路径(例如在 */foo/** 下),我希望 Varnish 以 200 HTTP 状态代码和空(或固定消息)正文进行响应,而不是将请求转发到后端服务器。
答案1
我同意 Michael 对滥用/使用 vcl_error 的简短回应,并想在下面的示例代码中向您展示我们的意思。
为了滥用 vcl_error,我在这里使用了 HTTP 标准之外的错误代码并对此类错误实施了特殊处理。
VCL_RECV 中的示例:
sub vcl_recv {
...
# respond HTTP 200 to /ping requests
if (req.url ~ "^/ping") {
error 700;
}
# return a 301 redirect
if (req.url ~ "^/wrong-target") {
error 751 "http://www.example.com/correct-target";
}
}
VCL_ERROR中的示例:
sub vcl_error {
# send response "Pong" (HTTP 200)
if (obj.status == 700) {
set obj.status = 200;
set obj.response = "OK";
set obj.http.Content-Type = "text/plain";
synthetic {"Pong"};
return (deliver);
}
# send empty response (HTTP 204)
if (obj.status == 701) {
set obj.status = 204;
set obj.response = "No Content";
synthetic {""};
return (deliver);
}
# redirect 301
if (obj.status == 751) {
set obj.http.Location = obj.response;
set obj.status = 301;
set obj.response = "Moved Permanently";
return (deliver);
}
# redirect 302
if (obj.status == 752) {
set obj.http.Location = obj.response;
set obj.status = 302;
set obj.response = "Found";
return (deliver);
}
# Fall through to default behavior for all other exceptions
}
答案2
对于这个问题的未来读者,我将@jens-bradler 的 vcl 移植到了 Varnish 4。(Serverfault 不允许我将多行代码作为评论发布,因此我在这里发布作为另一个答案)
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
if (req.url ~ "^/ping") {
return (synth(700, "Ping"));
}
if (req.url ~ "^/wrong-target") {
return (synth(751, "http://www.example.com/correct-target"));
}
}
sub vcl_synth {
set resp.http.Retry-After = "5";
if (resp.status == 700) {
set resp.status = 200;
set resp.reason = "OK";
set resp.http.Content-Type = "text/plain;";
synthetic( {"Pong"} );
return (deliver);
}
if (resp.status == 701) {
set resp.status = 204;
set resp.reason = "No Content";
set resp.http.Content-Type = "text/plain;";
synthetic( {""} );
return (deliver);
}
if (resp.status == 751) {
set resp.http.Location = resp.reason;
set resp.status = 301;
set resp.reason = "Moved Permanently";
return (deliver);
}
if (resp.status == 752) {
set resp.http.Location = resp.reason;
set resp.status = 302;
set resp.reason = "Found";
return (deliver);
}
return (deliver);
}
sub vcl_backend_response {
# Happens after we have read the response headers from the backend.
#
# Here you clean the response headers, removing silly Set-Cookie headers
# and other mistakes your backend does.
}
sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
}