犯蠢日记(二)本地环境,A 项目通过 guzzle 请求 B 项目某个接口时,返回 404 响应

背景

  • A 项目和 B 项目均是 Laravel + dingo/api 构建的项目
  • A 项目通过 API_DOMAIN 配置了 API 接口的域名,B 项目没有
  • 本地开发时两个项目在同一环境下,通过域名区分虚拟主机,域名用 hosts 指向 127.0.0.1

正文

由于某个原因,A 项目需要调用到 B 项目的某个接口,于是我使用 guzzle 去调用 B 项目的接口。
但是!!guzzle 却一直返回 404 响应!

通过本地使用 Postman 调用接口,我可以肯定 B 项目的该接口是肯定存在并且可以正常使用的。
这就非常奇怪了,为什么偏偏使用 guzzle 调用就会返回 404 响应?没有办法,只能根据 debug 信息里的 trace 一步步追查下去了。

追查过程非常曲折,就不在此赘述了,最终调试发现原因是路由的 host 验证没通过(\Illuminate\Routing\Matching\HostValidator)。
Request对象里的 host 是 B 项目的域名,但是HostValidator里的 host 却要求是 A 项目的 API_DOMAIN 域名,这就非常诡异了,初步怀疑是不是 Laravel 项目读取 .env 文件时会把里面的值都设置到环境变量里。
验证猜想,为了不读取 .env 文件,在 B 项目缓存配置:

$ php artisan config:cache

再次在 A 项目里使用 guzzle 调用 B 项目接口,接口返回成功!真是绝了,这特么都行,这 .env 文件加载看样子有坑啊。

可是本地调试终不能一直缓存配置啊,尝试寻找其他解决方案。
先清除 B 项目配置缓存,并使用 API_DOMAIN 配置 API 接口的域名,Postman 直接调用 B 项目接口,返回正常。
在 A 项目里使用 guzzle 调用 B 项目接口(对应修改了 url ),这次更牛逼了,返回虽然也是 404 响应,但不是 dingo/api 的 json 返回值,而是 Laravel 的 web 路由返回的 404 页面!这次直接进入不了 B 项目的 dingo/api 路由。。。在 B 项目缓存配置,guzzle 请求响应正常。

越来越有意思了,继续尝试,清除所有缓存,把 A 、B 项目都配置成 API_PREFIX 模式,Postman 直接调用 B 项目接口,返回正常,在 A 项目里使用 guzzle 调用 B 项目接口果然也返回正常,看样子真的是 .env 文件加载有坑啊。

衍生

想到 .env 文件加载有坑,突然就是一激灵,这不就意味着其实不仅仅是 API_DOMAIN 的值会有问题,所有 .env 文件里配置的变量其实全都会有问题!!比如数据库 DB_DATABASE !!哇,贼恐怖,立马写测试接口进行尝试,B 项目接口直接返回config('database.connections.mysql')的值。
果然,在 A 项目里使用 guzzle 调用 B 项目接口时,B 项目接口里config('database.connections.mysql')返回的是 A 项目的数据库配置。。。。在 B 项目缓存了配置之后,返回的就是正常的 B 项目数据库配置了。
哇,贼恐怖,简直无解了啊,这是逼我本地开发也要缓存 B 项目的配置了。

结论

折腾了这么久,最终只能妥协,缓存 B 项目的配置进行开发,希望过后我还会记得我在本地缓存过 B 项目的配置。。。
还有,线上环境也要注意部署在一台主机上的 Laravel 项目一定要缓存配置!!不然搞不好要出人命的 T_T

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 3

如果 B 的接口为 api.test.com,B 的 env 配置应该为 API_DOMAIN=api.test.com ,前面不可以加http://,否则会404

5年前 评论

@HI 这个没影响的,我这里出现 404 不是这个原因,并且其实加上了 http:// 也并不会报 404,亲测

5年前 评论

@xinhuo 噢,那可能我和你遇到的情况不一样。当用户访问我的api地址的时候,我的中间件会根据用户访问的域名主体匹配env的api_domain,当我的env配置api_domain前面加了http的时候,对方在postman或接口调用我的地址加了http或不加http,laravel自带的获取域名主体会将http省略,所以导致匹配不到404,我遇到过的是这样

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!