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 捕获并处理。
改进
暂时没有改进的思路,还望各位大佬指点。