nginx add_header在具有前端控制器的PHP应用程序的特定URI上

时间:2016-08-24 17:27:57

标签: php symfony nginx nginx-location

我有一个非常标准的设置与一个类似symfony2的应用程序与前端控制器,在nginx 1.10和Centos7上运行。这一切都按预期工作,阻止预期等。

server {
    listen 80;

    root /opt/my/code/web;
    index app.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /app.php$is_args$args;
    }

    # pass the PHP scripts to php5-fpm
    location ~ ^/app\.php(/|$) {

        # problem here
        location ~ ^/recording {
            add_header Content-Type audio/x-wav;
        }

        fastcgi_split_path_info ^(.+?\.php)(/?.*)$;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index app.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Prevents URIs that include the front controller. This will 404:
        internal;
    }

    # return 404 for all other php files not matching the front controller
    location ~ \.php$ {
        return 404;
    }
}

我有一些问题,但主要的一点是我需要对匹配/recording的URI进行特殊处理,但它仍然需要通过前端控制器。 (这是没有争议的,如果URI匹配/recording,它必须通过前端控制器并修改响应头)

由于try_files重定向到location ~ ^/app\.php(/|$) nginx用于位置匹配的$uri参数更新为/app.php,因此任何嵌套位置都无法正常工作

我无法在前端控制器块之外使用add_header,因为任何add_header指令都会被内部重定向删除。

显然,我无法将location ifadd_header一起使用。

这在apache中很容易,但是我发现的唯一远程解决方案使用了第三方lua模块,安装文档有点薄,并且从centos来源编译的想法给了我心悸。

1 个答案:

答案 0 :(得分:1)

如果内部重定向困扰我们,让我们删除内部重定向:)你可以使用fastcgi配置重复轻松解决它

server {
    listen 80;

    root /opt/my/code/web;
    index app.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /app.php$is_args$args;
    }

    location ~ ^/recording {
        add_header Content-Type audio/x-wav;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_NAME /app.php;
        fastcgi_param SCRIPT_FILENAME $document_root/app.php;
    }    

    # pass the PHP scripts to php5-fpm
    location ~ ^/app\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/?.*)$;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index app.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Prevents URIs that include the front controller. This will 404:
        internal;
    }

    # return 404 for all other php files not matching the front controller
    location ~ \.php$ {
        return 404;
    }
}

仅当您知道所有其他请求的内容类型时,第二个解决方案才有效。我们可以使用变量。 (顺便说一下,我不建议这个解决方案,因为更难以支持而且不可爱:)。

server {
    listen 80;

    root /opt/my/code/web;
    index app.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /app.php$is_args$args;
        set $ct "text/html";
    }

    location ~ ^/recording {
        try_files $uri $uri/ /app.php$is_args$args;
        set $ct "audio/x-wav";
    }    

    # pass the PHP scripts to php5-fpm
    location ~ ^/app\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/?.*)$;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index app.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        add_header "Content-Type $ct;

        # Prevents URIs that include the front controller. This will 404:
        internal;
    }

    # return 404 for all other php files not matching the front controller
    location ~ \.php$ {
        return 404;
    }
}