Eu realmente não tenho certeza onde mais procurar a resposta. Cada guia ou pergunta on-line diz para verificar client_max_body_size
e isso resolve.
Para mim, no entanto, estou tentando fazer uma grande solicitação PUT
para um arquivo PHP que está em meu próprio servidor.
Eu tenho ... client_max_body_size 32M;
no bloco do servidor nginx.conf. Eu sei que funciona porque o wordpress corretamente tem o tamanho do upload definido para 32MB.
Além disso, descobri que preciso verificar 3 variáveis PHP, não me lembro exatamente o que elas eram, mas elas são grandes o bastante (em centenas de MB).
Talvez eu precise fazer algo com buffers? Eu não tenho ideia: (
O script que estou usando é um script de proxy para se comunicar com o serviço de terceiros. Ele registra todos os seus dados para a saída, e este é o log até agora ... não tenho certeza se isso poderia aludir a um problema.
Acho que isso abaixo é o que o servidor está tentando para enviar (porque está no arquivo de log e está gravando em STDOUT, então presumo que o script do proxy php esteja tentando gravar um arquivo de log de os cabeçalhos que está querendo enviar).
No entanto, quando uso as ferramentas de desenvolvimento do Chrome, não vejo Expect: 100-continue
. Isso poderia ter alguma coisa a ver com isso?
Editar: Depois de ver o código fonte do PHP, parece que foi um 'bug' com 100-continue e isso estava bagunçando o script do proxy ... Então ignore toda a saída abaixo. Eu suponho que vou colocá-lo de qualquer maneira apenas no caso de ter outros bits úteis.
"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 "
Não tenho certeza se isso ajuda ... mas aqui está o script de proxy.
<?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("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/*;
}
")', 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
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;
}
}
staging.site.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;
}
php.conf
client_max_body_size 32M;
wordpress.conf
"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 "