nginx使用前端控制器将特定URI上的_头添加到PHP应用程序

nginx使用前端控制器将特定URI上的_头添加到PHP应用程序,php,symfony,nginx,nginx-location,Php,Symfony,Nginx,Nginx Location,我有一个相当标准的设置,有一个类似symfony2的应用程序,带有一个前端控制器,运行在nginx1.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; }

我有一个相当标准的设置,有一个类似symfony2的应用程序,带有一个前端控制器,运行在nginx1.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;
    }
}
我有一些问题,但主要问题是我需要对匹配
/录制
的URI进行特殊处理,但它仍然必须通过前端控制器。(这是无可争议的,如果URI与
/recording
匹配,它必须通过前端控制器修改响应头)

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

我不能在前控制器块外使用
add_header
,因为任何
add_header
指令都会在内部重定向时被丢弃

显然,如果将
添加到
标题中,我也不能使用
位置


这在apache中很容易,但我发现的唯一远程解决方案使用了第三方lua模块,安装文档在这一点上有点单薄,在centos上从源代码处编译它的想法让我心悸。

如果内部重定向困扰我们,让我们删除内部重定向:)使用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;
    }
}
第二种解决方案只有在您知道所有其他请求的内容类型时才起作用。我们可以使用变量。(顺便说一句,我不建议使用这种解决方案,因为它更难支持,也不可爱:)


在我的例子中,我特别放弃了,它根本不起作用,所以我只是将这段代码现代化,并在响应之前使用文件扩展名设置mime类型。第一种解决方案足够优雅,不是因为我喜欢复制,而是因为我讨厌它。如果我在某些时候需要更多的特殊处理,我还可以巧妙地使用位置匹配和堆栈位置块。这几乎是nginx开发团队的官方观点:复制它!如果重复太多-使用包含或外部模板系统。可能是因为这有助于简化配置解析器。我编辑了我的帖子,是错误的fastcgi_param。如果它是官方的,我会说链接它,因为这是一件非常重要的事情。正如我所说,“几乎是官方的”,因为没有记录,但基于Igor Sysoev、Maxim Dounin在nginx邮件列表中的许多答案。等等,很难把它联系起来。
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;
    }
}