我真的不知道还能在哪里找到答案。网上的每一个指南或问题都说要检查client_max_body_size
,这样就可以解决问题。
PUT
然而对我来说,我正在尝试对我自己的服务器上的 PHP 文件发出大量请求。
我已经client_max_body_size 32M;
在 nginx.conf 服务器块中设置了...我知道它有效,因为 wordpress 正确地将上传大小设置为 32MB。
除此之外,我发现我可能需要检查 3 个 PHP 变量,我不记得它们到底是什么,但它们都足够大(数百 MB)。
也许我需要对缓冲区做些什么?我不知道 :(
我使用的脚本是用于与第三方服务通信的代理脚本。它将所有数据记录到输出中,这是迄今为止的日志。不确定这是否暗示存在问题。
我认为下面是服务器试发送(因为它在日志文件中并且正在写入 STDOUT,所以我假设 php 代理脚本正在尝试写入它想要发送的标头的日志文件)。
但是当我使用 chrome dev tools 时,我看不到Expect: 100-continue
。这和它有什么关系吗?
编辑:查看 PHP 源代码后,似乎 100-continue 是一个“错误”,它搞乱了代理脚本……因此请忽略下面的所有输出。我想我还是会把它放上去,以防它有其他有用的部分。
"PUT /rest/cart HTTP/1.1"
"HOST: staging.site.com"
"CONNECTION: keep-alive"
"CONTENT-LENGTH: 2695"
"ACCEPT: application/json, text/javascript, */*; q=0.01"
"CACHE-CONTROL: no-cache"
"ORIGIN: http://staging.site.com"
"X-REQUESTED-WITH: XMLHttpRequest"
"USER-AGENT: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.37 Safari/537.36 "
"CONTENT-TYPE: application/json; charset=UTF-8 "
"REFERER: http://staging.site.com/order/ "
"ACCEPT-ENCODING: gzip,deflate,sdch "
"ACCEPT-LANGUAGE: en-US,en;q=0.8 "
"COOKIE: XXX"
"Content-Type: application/json; charset=UTF-8 "
"Content-Length: 2695 "
"X-UC-Forwarded-For: XXX "
"Expect: 100-continue "
不确定这是否有帮助...但这是代理脚本。
<?php
// Version 0.7. 08/15/2013
// Some of the PUT/POST requests were returning back 100 Continues. That was wrecking havoc with the parser below causing aborted calls.
// Version 0.6. 06/22/2013
// Headers weren't being handled correctly. Server http status wasn't being passed along.
// Headers with multiple values weren't iterated correctly and were being mangled (think multiple 'Set-Cookie')
// Version 0.5. 02/07/2013 Initial Version.
function http_parse_headers($header)
{
$retVal = array();
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
foreach ($fields as $field) {
if (preg_match('/([^:]+): (.+)/m', $field, $match)) {
$match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
if (isset($retVal[$match[1]])) {
$retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
} else {
$retVal[$match[1]] = trim($match[2]);
}
}
}
return $retVal;
}
function gzdecode($data)
{
$g = tempnam('/tmp', 'ff');
@file_put_contents($g, $data);
ob_start();
readgzfile($g);
$d = ob_get_clean();
unlink($g);
return $d;
}
if (isset($_GET["_url"])) {
$path = $_GET["_url"]; // get the url parameter
} else {
die("UltraCart rest proxy script called incorrectly. _url query parameter is required.");
}
$path = preg_replace('#[^a-z0-9/]#i', '', $path); // strip off any junk
$path = preg_replace('#/+#', '/', $path); // remove duplicate slashes if any
if (strncmp($path, '/', 1) != 0) { // if the path doesn't start with a slash, add one.
$path = '/' . $path;
}
$additional_parameters = '';
foreach ($_GET as $k => $v) {
if ($k != '_url') {
if ($additional_parameters) {
$additional_parameters = $additional_parameters . '&' . $k . "=" . urlencode($v);
} else {
$additional_parameters = $additional_parameters . '?' . $k . "=" . urlencode($v);
}
}
}
// the above filtering should remove any malicious attempts, but no worries, UltraCart has some insane firewalls to boot.
$server_get_url = "https://secure.ultracart.com" . $path . $additional_parameters;
$post_data = file_get_contents('php://input');
foreach ($_SERVER as $i => $val) {
if (strpos($i, 'HTTP_') === 0) {
if ($i == 'HTTP_X_UC_MERCHANT_ID') {
$header[] = "X-UC-Merchant-Id: $val";
} else if ($i == 'HTTP_X_UC_SHOPPING_CART_ID') {
$header[] = "X-UC-Shopping-Cart-Id: $val";
} else {
$name = str_replace(array('HTTP_', '_'), array('', '-'), $i);
$header[] = "$name: $val";
}
}
}
if (isset($_SERVER['CONTENT_TYPE'])) {
$content_type = $_SERVER['CONTENT_TYPE'];
} else {
$content_type = 'application/json';
}
$header[] = "Content-Type: " . $content_type;
$header[] = "Content-Length: " . strlen($post_data);
$header[] = "X-UC-Forwarded-For: " . $_SERVER['REMOTE_ADDR'];
$ch = curl_init($server_get_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_ENCODING, 1);
if (strlen($post_data) > 0) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
$response = curl_exec($ch);
//error_log("start response ===========================================");
//error_log("start raw response ===============");
//error_log($response);
//error_log("end raw response ===============");
// grab the status code and set the proxy request result to that.
$first_line = '';
$beginning_of_real_http_status = 0; // a index marker for the second http status if the server returns 100 Continue (PUTS/POSTS)
if (strlen($response) > 0) {
$first_line = substr($response, 0, strpos($response, "\n") - 1);
$first_line = trim($first_line);
// Is the first line an HTTP/1.1 100 Continue?
// If so, search for the next empty line and begin there.
preg_match("/100\s+Continue/i", $first_line, $output_array);
if (count($output_array) > 0) {
// we have an HTTP Continue. Skip down to the next status code.
if (preg_match('#^\s*$#m', $response, $matches, PREG_OFFSET_CAPTURE)) {
$beginning_of_real_http_status = $matches[0][1] + 2;
}
$real_headers = explode("\n", substr($response, $beginning_of_real_http_status));
$first_line = $real_headers[0];
// $first_line = substr($response, $beginning_of_real_http_status, strpos($response, "\n", $beginning_of_real_http_status) - 1);
$first_line = trim($first_line);
}
//error_log('$first_line:[' . $first_line . ']');
header($first_line);
}
//error_log('$beginning_of_real_http_status:' . $beginning_of_real_http_status);
if (curl_errno($ch)) {
print curl_error($ch);
} else {
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, $beginning_of_real_http_status, $header_size - $beginning_of_real_http_status);
$response_headers = http_parse_headers($header);
foreach ($response_headers as $header_key => $header_value) {
if ($header_key != 'Content-Encoding' && $header_key != 'Vary' && $header_key != 'Connection' && $header_key != 'Transfer-Encoding') {
if ($header_key == 'Content-Length' && $header_value == "0") {
/* ignore this, it's from an HTTP 1.1 100 Continue and will destroy the result if passed along. */
} else {
if (is_array($header_value)) {
foreach ($header_value as $val) {
//error_log("$header_key: $val");
header("$header_key: $val", false);
}
} else {
//error_log("$header_key: $header_value");
header("$header_key: $header_value", false);
}
}
}
}
$body = substr($response, $header_size);
echo $body;
curl_close($ch);
}
//error_log("end response ===========================================");
?>
nginx.conf
user www www;
worker_processes 4;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 200000;
events {
worker_connections 32768;
use epoll;
multi_accept on;
}
http {
#auth_basic "Restricted";
#auth_basic_user_file /home/www/.htpasswd;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log off;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
ssl_prefer_server_ciphers on;
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:20m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
gzip on;
gzip_http_version 1.0;
gzip_disable "msie6";
gzip_comp_level 1;
gzip_buffers 16 8k;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
# text/html is always compressed by HttpGzipModule
text/css
text/plain
text/x-component
application/javascript
application/json
application/xml
application/xhtml+xml
application/x-font-ttf
application/x-font-opentype
application/vnd.ms-fontobject
image/svg+xml
image/x-icon;
include sites-enabled/*;
}
staging.site.conf
server {
listen 80 deferred;
server_name staging.site.com;
root /var/www/html/site.com;
index index.html index.htm index.php;
charset utf-8;
access_log /var/log/nginx/site.com-access_log;
include conf/wordpress.conf;
include conf/bwp-security.conf;
include conf/base.conf;
include conf/php.conf;
location / {
include conf/allowed-ips.conf;
try_files $uri $uri/ /index.php?$args;
}
}
php.conf
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffers 32 32k;
fastcgi_buffer_size 32k;
fastcgi_intercept_errors off;
fastcgi_pass unix:/tmp/php5-fpm.sock;
}
wordpress配置文件
client_max_body_size 32M;
答案1
您能附加相关的 nginx-conf 吗?
您是否知道请求是否已到达 php 位置或是否已在 nginx 停止?
所以你可以通过 POST 上传,但不能通过 PUT 上传?我会开始调查这个问题;当你将 PUT 改为 POST 时会发生什么?
当谷歌搜索时,PUT 413: Request Entity Too Large nginx
最受引用的建议就是您已经做过的事情,并且我不会开始弄乱 client_*_temp - vars 和 temp_caching (atm)。