Laravel 和 Dcat Admin 在使用 Nginx 进行 Uri 二级目录的反向代理时遇到的问题以及解决方法
问题
一般的 Laravel 应用进行 Nginx 的 Uri 二级目录反向代理的时候,Nginx 的配置文件可按如下配置
1 | location /prefix/ { |
由于我们在 proxy_pass
中的 Url 末尾添加了 /
,所以 Laravel 在收到请求时,请求的路径不包含反向代理的前缀 /prefix
,即若用户所见的地址为:
1 | http://xxxx.xxxx/prefix/index |
Laravel 收到的请求地址将会是:
1 | http://xxxx.xxxx/index |
这样就可以让反向代理层对 Laravel 应用透明,但是会出现这样的问题,就是 url()
等函数生成的路径将会是不含反向代理前缀的路径,造成 asset()
等函数均生成错误的地址,为了解决这样的问题,我们可以在 AppServiceProvider
类中的 boot
方法添加以下内容:
1 | app('url')->forceRootUrl(config(app.url)); |
这样的话,url()
将会基于 .env
文件中提供的 APP_URL
值设置所生成的 url 的根路径。我们只需在 .env
中配置 APP_URL
即可
1 | APP_URL=http://xxxx.xxxx/prefix/ |
经过这样的配置,对于一般的 Laravel 应用已经可以实现二级目录的反向代理,但实际上很多项目中生成 url 的地方并非都使用 url()
函数生成,比如今天要说的 Dcat Admin,它的源代码中同时使用了 $request
的 url 和 url()
生成的 url 。如在生成菜单项时使用了 url()
函数而在获取当前资源路径时,当 $request
提供的 url
合法的话又是直接使用请求的地址。
这就导致我们在使用上面的的配置的时候,会出现这样的情况:
- 点击菜单栏跳转到
/prefix/xxx
之后,地址栏会自动变成/xxx
,刷新后变成了 404; - “创建”、“提交”按钮提供的是不带
prefix
的链接,导致 404
解决方法
在上述配置的基础上,在 admin.php
中将后台的路径配置为 /prefix/admin
,然后再在 Nginx 的配置文件中添加:
1 | location /prefix/admin/ { |
注意这里面 proxy_pass
末尾没有添加 /
,Laravel 接收到请求时将会保有 /prefix/admin
当我们这样配置时,Dcat Admin 会生成两种 url,一种是 /prefix/prefix/admin/
(使用 url()
函数生成的),一种是 /prefix/admin/xxx
(直接从请求的 url 中获取的)。
当访问 /prefix/prefix/admin/
时,会被 Nginx 中的 location /prefix/
捕获,Laravel 应用收到的 Uri 不带 /prefix
,即 /prefix/admin
,按照我们在 admin.php
中的配置,此时请求成功被 Dcat Admin 捕获并处理。
当访问 /prefix/admin/xxx
时,会被 Nginx 中的 location /prefix/admin/
中捕获,此时 Laravel 收到的请求会保有 /prefix/admin
,此时请求成功被 Dcat Admin 捕获并处理。
改进
暂时没有改进的思路,还望各位大佬指点。