RuntimeException: Unable to boot ApiServiceProvider, configure an API domain or prefix 解决办法和原因所在

in web技术 with 2 comments 访问: 10,880 次

背景描述

问题产生

我自己本地肯定是没这一类问题的,中午的时候学妹说接口500了,我一看,还真他娘的500了,response也没返回错误信息,于是我打开错误日志,发现了这么一条:

production.ERROR: RuntimeException: Unable to boot ApiServiceProvider, configure an API domain or prefix. in E:\fenke-website\vendor\dingo\api\src\Provider\DingoServiceProvider.php:82
Stack trace:
#0 E:\fenke-website\vendor\dingo\api\src\Provider\DingoServiceProvider.php(46): Dingo\Api\Provider\DingoServiceProvider->registerConfig()

当前情况是这样的:

这个时候就有点尴尬了,这种问题是程序员最不想看到的,因为是偶现,你不知道什么原因引起的,排查也无从下手,百度了好久然并卵。

那么原因是什么呢?我是一个刨根问底的人,在我的不懈努力下发现,原来这是php ts 版本会出现的问题。

原因所在

这其实是php的一个已知问题(只是对于我来说是未知 :p)

问题仅仅出现在php ts版本中。下面是php手册对于putenv()函数的解释。

添加 setting 到服务器环境变量。 环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。

设置特定的环境变量也有可能是一个潜在的安全漏洞。 safe_mode_allowed_env_vars 包含了一个以逗号分隔的前缀列表。 在安全模式下,用户可以仅能修改用该指令设定的前缀名称的指令。 默认情况下,用户仅能够修改以 PHP_ 开头的环境变量(例如 PHP_FOO=BAR)。 注意:如果此指令是空的,PHP允许用户设定任意环境变量!

safe_mode_protected_env_vars 指令包含了逗号分隔的环境变量列表,使用户最终无法通过 putenv() 修改。 即使
safe_mode_allowed_env_vars 设置允许修改,这些变量也会被保护。

当PHP是线程安全的时候,putenv()和getenv()存在一个问题:如果在一个请求结束之前调用另一个请求,那么当第一个脚本完成时,它的环境变量将被重置。这对于Ajax请求来说是有问题的,或者仅仅是当用户在新标签中打开多个链接时。

下面我以laravel为例重现此问题。

问题重现

首先,在路由文件中写一个请求,形如

Route::get('litblc111', function()
{
    sleep(5);

    return 'ENV_VALUE:' . env('API_VERSION');
});

当然要在.env文件中加入对应配置 API_VERSION=v1

ok,准备工作结束,接下来开始演示:

111.png

正常等待5s结果:
82512841541395903.png

在第一次请求没有结束之前立刻再次请求的结果:
884140426622628498.png

ok,这就是为什么在学妹本地环境中访问我的接口,会报错的原因,就是因为他ts版本的php没有找到env对应的值。

解决办法

了解了原因,解决办法多做多样,这里我只说明一下我(laravel)开发的解决办法。

找到config / api.php文件,大约第60行

'prefix' => env('API_PREFIX', null)

更改为

'prefix' => env('API_PREFIX', 'api')

大功告成。

参见

赞赏支持
Responses
  1. Hello, I enjoy reading all of your article. I wanted to write a little comment to support you.

    Reply
  2. seo查询www.09seo.cn

    Reply