Laravel - 所有路由上的 NGINX + Apache 反向代理 404

Posted

技术标签:

【中文标题】Laravel - 所有路由上的 NGINX + Apache 反向代理 404【英文标题】:Laravel - NGINX + Apache reverse proxy 404 on all routes 【发布时间】:2018-06-14 08:11:16 【问题描述】:

我正在 Laravel 中建立一个项目,它使用基于 Ubuntu 14.04 的自定义 vagrant box,并在典型的反向代理设置中运行 nginx 和 Apache。

现在,问题是沿途的某些东西没有注册 URL 路径,所以当我输入 http://mydomain.test/hello 时,我最终得到的只是另一端的 http://mydomain.test/index.php,它似乎完全忘记了路线参数。

我正在使用带有 Mod PHP 的 Apache 2.4.7,Apache 配置如下。

<VirtualHost 127.0.0.1:8080>
    ServerName application.test
    ServerAlias www.application.test
    DocumentRoot "/home/vagrant/application/public"

    ErrorLog /var/log/apache2/error.log
    CustomLog /var/log/apache2/access.log combined

    <Directory "/home/vagrant/application/public">
        Require all granted
        AllowOverride all
    </Directory>
</VirtualHost>

如图所示,Apache 正在监听 8080 端口,而 NGINX 正在使用以下配置监听 80 端口。

server 
    listen 80;
    server_name application.test www.application.test;

    root /home/vagrant/application/public;
    index index.php index.html;

    location / 
        try_files $uri $uri/ /index.php?$is_args$args;
    

    location ~ \.php$ 
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    

    location ~ /\. 
      deny all;
    

我可以确认所有 Laravel 要求都得到满足,所以我有 MBString、OpenSSL 等...我还可以确认重写模块正在工作,因为我可以向我的 .htaccess 添加重定向子句,它确实如此按预期执行。

这是我的.htaccess 文件。

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %HTTP:Authorization .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%HTTP:Authorization]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %REQUEST_FILENAME !-d
    RewriteCond %REQUEST_URI (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %REQUEST_FILENAME !-d
    RewriteCond %REQUEST_FILENAME !-f
    RewriteRule ^ index.php [L]
</IfModule>

我可能在这里遗漏了什么吗?我之前配置过 NGINX 和 PHP-FPM,但这是我第一次使用 Apache,我遇到了多个类似的问题,但没有一个建议的修复对我有用,这就是我问这个问题的原因。

提前感谢您的帮助

编辑

一些进展。

如果我为 NGINX 设置位置配置如下

location / 
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

然后它可以工作,但据我所知,这意味着即使是静态文件请求最终也会被代理到 Apache。

location ~ \.php$ 似乎不起作用,因为我猜 laravel 漂亮的 url 不以“.php”后缀结尾。但是如何才能让这两个玩得很好呢?

我猜的想法是您有一个指向index.php 的默认位置,当触发该 index.php 文件时,nginx 会收到另一个与您的php 位置块匹配的 HTTP 请求,并将请求代理到 Apache .

问题在于,在第二次请求期间,所有关于 URI 的知识都丢失了,并且 URI 现在只是“index.php”,因此就 Apache 所知,您总是向 /index.php 发出请求。

我仍然不知道如何解决它。

【问题讨论】:

顺便说一下,我使用 Apache 的原因是服务器是这样配置的,我需要我的 Vagrant 配置与服务器紧密匹配。这就是为什么我要做整个 Apache 反向代理的事情,所以请不要只告诉我使用 PHP-FPM,因为我不能。 【参考方案1】:

所以我想我已经想通了,如果你有类似的问题,一个可能的解决方案是将 $uri 变量添加到 try_files 指令

server 
    listen 80;
    server_name application.test www.application.test;

    root /home/vagrant/application/public;
    index index.php index.html;

    location / 
        try_files $uri $uri/ /index.php$uri;
    

    location ~ \.php 
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    

    location ~ /\. 
      deny all;
    

这样,当 nginx 调用你的 index.php 时,它会像 http://application.test/index.php/hello 一样调用它,这是 Apache 最终通过 PHP 接收和处理的 URL。

那么,.htaccess 开始发挥作用,Laravel 做到了,一切正常,这仍然只影响 PHP 文件,你的静态文件仍然应该由 NGINX 直接提供。

如果您发现此方法有任何问题,请告诉我。

更新


我后来犯了一个愚蠢的错误,让我相信还有其他问题,每条路由似乎都显示了我的“/”根路由的内容。 在尝试使用 Homestead 而不是我的自定义设置后,我惊讶地发现它也影响了 Homestead,因此它必须与我的应用程序本身相关,而不是与服务器相关。

基本上它是返回根视图的异常处理程序,因为我的请求丢失了我的 FormRequests 所需的一些数据,在更改我的异常处理程序类以处理 JSON 响应后,它按预期工作。

如果你落入这种陷阱,请尝试确保你的应用与 Homestead 兼容,如果可以,则说明你的 vagrant 设置有问题,如果没有,那就是你的 Laravel 应用有问题。

如果您的异常处理程序只是进行典型的渲染,那么请注意它会尝试重定向到上一个路由,如果您使用 Postman 开发 API,则该路由将是“/”。

【讨论】:

以上是关于Laravel - 所有路由上的 NGINX + Apache 反向代理 404的主要内容,如果未能解决你的问题,请参考以下文章

laravel开发网站实例-----2

如何在 Laravel 4 中将一个路由重定向到 HTTPS,将所有其他路由重定向到 HTTP?

Laravel + AngularJS Nginx 路由

Laravel 5 - 发布路由上的 htaccess HTTPS 重定向不起作用。

laravel路由不工作nginx服务器

Nginx 总是将 Laravel 路由重定向到默认的根 index.php 页面