清漆 POST 缓存无法通过 PHP CURL 工作,但是,它似乎与终端 CURL 一起工作



我参考了本文档以在Apache服务器上启用POST缓存。使用的服务端脚本语言是PHP。

如前所述,我使用

curl --data '{"maxresults":2000}' http://localhost/varnishoutput/varnishtest.php

输出

{"1":{"{"maxresults":2000}":""},"2":"NOO"}

输出被缓存,并在"varnishtest.php">中进行任何更改。不要更改POST"ABC">的响应。但是,如果更改了 POST 值,则会显示新更改的响应。因此,终端端的POST 缓存正在工作。

但是,如果我使用 CURL 从其他 PHP 文件调用相同的 URL。不缓存输出。这是我使用的PHP代码。

清漆柱.php

<?php
$data = array();
$data['maxresults'] = 2000;
$api = "http://localhost/varnishoutput/varnishtest.php";
$s = curl_init();
curl_setopt($s,CURLOPT_URL,$api);
curl_setopt($s,CURLOPT_RETURNTRANSFER,true);
curl_setopt($s,CURLOPT_POST,true);
curl_setopt($s,CURLOPT_POSTFIELDS,$data);
curl_setopt($s,CURLINFO_HEADER_OUT,$data);
$response = curl_exec($s);
$header = curl_getinfo($s);
curl_close($s);
$dataArr = json_decode($response);
print_r($dataArr);
echo "nn";
print_r($header);
echo "nn";
echo $api. "nn";
?>

清漆测试.php

<?php
echo json_encode(array("1"=>$_POST,"2"=>"NOO"));
?>

输出

stdClass Object
(
[1] => stdClass Object
(
[maxresults] => 2000
)
[2] => NOO
)

标头输出

Array
(
[url] => http://localhost/varnishoutput/varnishtest.php
[content_type] => text/html; charset=UTF-8
[http_code] => 200
[header_size] => 359
[request_size] => 207
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.005651
[namelookup_time] => 0.004235
[connect_time] => 0.004385
[pretransfer_time] => 0.004474
[size_upload] => 149
[size_download] => 37
[speed_download] => 6547
[speed_upload] => 26367
[download_content_length] => 37
[upload_content_length] => 149
[starttransfer_time] => 0.00478
[redirect_time] => 0
[redirect_url] => 
[primary_ip] => ::1
[certinfo] => Array
(
)
[primary_port] => 80
[local_ip] => ::1
[local_port] => 57130
[request_header] => POST /varnishoutput/varnishtest.php HTTP/1.1
Host: localhost
Accept: */*
Content-Length: 149
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------072b0f786662

)

标头输出在标头信息中不显示任何"X-Varnish"值。此外,每次更改相同的 POST 值的响应文件时,输出都会更改。因此,在这种情况下,后缓存不起作用。

VCL文件代码如下:

#
# This is an example VCL file for Varnish.
#
# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
#
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and http://varnish-cache.org/trac/wiki/VCLExamples for more examples.
# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;
import std;
import bodyaccess;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "192.168.0.108";
.port = "8080";
.connect_timeout = 120s;
.first_byte_timeout = 120s;
.between_bytes_timeout = 120s;
}
sub vcl_recv {
unset req.http.X-Body-Len;
# Happens before we check if we have this in cache already.
# 
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
# Do not cache these paths.
if (req.url ~ "(/userInfo/|gm_internet_testing.php|/abc-wct/|/ren_api/|/book_api/|/eve_api/getEveScore.php|/iptoct_api/|/ct_api/.*bweatherb|/rec_api/.*bopennowb)") {
return (pass);
}
# Replace the parameter &_= which is a random integer passed when jquery ajax cache is false
if (req.url ~ "&_=[0-9]+$") {
set req.url = regsub(req.url,"&_=[0-9]+$","");
}
if (req.method == "POST" ) {
std.log("Will cache POST for: " + req.http.host + req.url);
std.cache_req_body(500KB);
set req.http.X-Body-Len = bodyaccess.len_req_body();
if (req.http.X-Body-Len == "-1") {
return(synth(400, "The request body size exceeds the limit"));
}
return (hash);
}
# Handling to cache pages across browsers / devices
if (req.http.Accept-Encoding) {
if (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} else if (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
unset req.http.Accept-Encoding;
}
}
if (req.http.user-agent ~ "MSIE") {
set req.http.user-agent = "MSIE";
} else {
set req.http.user-agent = "Mozilla";
}
unset req.http.Cookie;
}
sub vcl_hash {
# To cache POST and PUT requests
if (req.http.X-Body-Len) {
bodyaccess.hash_req_body();
} else {
hash_data("");
}
}
sub vcl_backend_fetch {
if (bereq.http.X-Body-Len) {
set bereq.method = "POST";
}
}
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.
}

谁能帮忙?

我注意到命令行上的POST 数据与 PHP 脚本中的数据之间存在差异。

cURL请求中的--data '{"maxresults":2000}'实际上会将JSON 对象作为有效负载发送。

当我查看您的PHP脚本时,$data['maxresults'] = 2000;只是常规的POST数据,这是不一样的。

因为您在vcl_hash中执行bodyaccess.hash_req_body();,所以如果POST 正文不同,查找哈希将不同。这就是为什么你会在你的脚本中错过。

JSON 有效负载

如果您想要相同的结果,我建议您按如下方式设置POST 字段

curl_setopt($s,CURLOPT_POSTFIELDS,json_encode($data));

常规开机自检字段

如果要改用常规POST 字段,可以在命令行上执行以下cURL调用:

curl --data 'maxresults=2000' http://localhost/varnishoutput/varnishtest.php

如果你想使用纯POST 字段,这是你需要在 PHP 文件中进行的更改:

curl_setopt($s,CURLOPT_POSTFIELDS,http_build_query($data));

最新更新