Назад | Перейти на главную страницу

NginX заставляет PHP-файл запускаться дважды

Я между камнем и наковальней пытаюсь понять, почему это происходит. По какой-то причине, когда я открываю свой сайт, выполняется файл index.php. Я смог сузить его до NginX / PHP-FPM, добавив file_put_contents('runs.txt', 'executed'.PHP_EOL, FILE_APPEND); в начало index.php и выполнение его с помощью веб-сайта и командной строки. Если я выполняю его из командной строки, он выводит только один executed, а если я выполняю его с веб-сайта (через NginX), он выводит два executed. Сценарий также не перенаправляет на себя, потому что он просто возвращает код ответа 200. Помимо необходимости использовать больше памяти, выполняя сценарий дважды, он также портит защиту CSRF, поскольку CSRF генерируется второй раз, и поэтому CSRF бесполезен.

Ниже приведены мои файлы конфигурации nginx:

nginx.conf

user  nginx;
worker_processes  2;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    # Upstream to abstract backend connection(s) for PHP.
    upstream php {
        #this should match value of "listen" directive in php-fpm pool
        server unix:/var/lib/php-fpm.sock;
    }

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

php.conf

# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
        #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        include fastcgi_params;

        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_read_timeout 600s;
#       fastcgi_intercept_errors on;
        fastcgi_pass php;
}

website.conf

server {
    listen       80;
    server_name  xyz.com www.xyz.com;
    root         /usr/share/nginx/xyz.com;
    #access_log  /usr/share/nginx/logs/xyz.com-access_log;
    error_log    /usr/share/nginx/logs/xyz.com-error_log;

    index index.php;

    location / {
       index index.php;

       try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    include php.conf;
}

fastcgi_params

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

Если я изменю try_files $uri $uri/ /index.php?q=$uri&$args; к try_files $uri $uri/; и воспитывать http://www.xyz.com/index.php тогда он будет выполняться только один раз, но мне нужен /index.php?q=$uri&$args там. Я использую CentOS 6.5 с nginx 1.4.4 и PHP 5.4.23. Любые идеи?

Я обнаружил проблему. поскольку try_files автоматически перенаправит на index.php если указанный URI не существует, значит изображение отсутствовало, и при его открытии оно открывалось index.php очередной раз.

Мне удалось определить, что отсутствующее изображение было http://example.com/images/google.png поэтому я нашел это изображение и поместил его в нужную папку (вместо того, чтобы перенаправлять обратно на index.php).

Еще одним более правильным решением было бы иметь location /images блок с try_files заявление в website.conf файл (до location / block), что если изображение не существует, отправляется код состояния 404 not found.

location /images {
    try_files $uri =404;
}