Я действительно не знаю, где еще искать ответ. В каждом руководстве или вопросе в Интернете говорится, что нужно проверить client_max_body_size
и это решает проблему.
Что касается меня, то я пытаюсь сделать большой PUT
запрос к файлу PHP, который находится на моем собственном сервере.
У меня есть... client_max_body_size 32M;
в серверном блоке nginx.conf. Я знаю, что это работает, потому что wordpress правильно установил размер загрузки 32 МБ.
Помимо этого, я обнаружил, что мне нужно, возможно, проверить 3 переменные PHP, я не помню точно, что они были, но все они достаточно велики (в сотнях МБ).
Может надо что то с буферами делать? Я понятия не имею :(
Скрипт, который я использую, представляет собой прокси-скрипт для связи со сторонней службой. Он регистрирует все данные для вывода, и это пока журнал ... не уверен, может ли это указывать на проблему.
Я думаю, что ниже это сервер пытаясь для отправки (потому что он находится в файле журнала и записывается в STDOUT, поэтому я предполагаю, что сценарий прокси-сервера php пытается записать файл журнала заголовков, которые он хочет отправить).
Однако, когда я использую инструменты разработчика Chrome, я не вижу 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.conf
client_max_body_size 32M;
не могли бы вы добавить свой nginx-conf?
знаете ли вы, доходит ли запрос до php-location или он остановлен @ nginx?
Значит, вы можете загружать через POST, но не через PUT? Я бы начал расследование по этому поводу; Что произойдет, если вы измените PUT на POST?
при поиске в Google PUT 413: Request Entity Too Large nginx
наиболее часто упоминаемый совет - это то, что вы уже сделали, и я бы не стал возиться с client _ * _ temp - vars и temp_caching (atm).