Lumen 使用踩点之 Dingo
公司有个产品准备使用Laravel或者Lumen,同时希望能够使用RESTful API进行设计开发,来减少对移动端和PC端的功能适配,同样是新手,近来调试配置中也遇到了不少问题,记录些个人理解供大家参考交流,欢迎拍砖:)
Dingo作为第三方API开发组件,针对laravel和lumen都提供了适配的serviceprovider。
ApiServiceProvider作为2个框架服务的基类,注册了用于API处理的dispatcher,auth,response,exception等基本功能。
-
Dingo API路由如何处理
使用Dingo创建的API路由并没有被存储在lumen主容器的routes中,而是被置于Dingo的dispatcher中。当框架中以注册的路由无法处理外部request时,就将该request扔进所有middleware组成的pipeline中进行处理,其中dingo的request就被添加到Lumen的首个中间件队列上,因此该API请求并可通过通过dispatcher进行分发处理。
/** * Add the request middleware to the beginning of the middleware stack on the * Lumen application instance. * * @param \ReflectionClass $reflection * * @return void */ protected function addRequestMiddlewareToBeginning(ReflectionClass $reflection) { $property = $reflection->getProperty('middleware'); $property->setAccessible(true); $middleware = $property->getValue($this->app); array_unshift($middleware, 'Dingo\Api\Http\Middleware\Request'); $property->setValue($this->app, $middleware); $property->setAccessible(false); }
-
API配置和访问
在laravel中使用通过给API_DOMAIN赋值可以实现API专有子域名,比如可以使用api.test.app来请求如下的api服务器
'domain' => env('API_DOMAIN', 'api.test.app'),
但是在lumen中配置后无法访问,需要使用prefix来区分API请求。
原因是Lumen 没有使用 Symfony 的路由模块, 而是采用了速度更加快的 nikic/fast-route。请参考,
而fast-route并没有诸如子域名等高级功能。
Laravel中可以使用artisian的api:routes来查看所有的路由是否建立成功,以及对应的映射关系和URL,比如
+----------------+-------------------------------+------+--------------------------------------------------------------------+------------+-----------+----------+ | Domain | URI | Name | Action | Version(s) | Protected | Scope(s) | +----------------+-------------------------------+------+--------------------------------------------------------------------+------------+-----------+----------+ | api.lvtest.app | GET|HEAD /v1 | | App\Http\Controllers\Api\V1\PerformanceController@text_test | v1 | No | | | api.lvtest.app | GET|HEAD /v1/text_test | | App\Http\Controllers\Api\V1\PerformanceController@text_test | v1 | No |
但是Lumen中缺少该命令。查看ApiServiceProvider时发现该被注册时使用commands方法可以创建命令,尝试主动创建时发现一些依赖文件不存在,因此无法实现。待后面研究下artisan再搞
$this->commands([ 'Dingo\Api\Console\Command\Docs', //'Dingo\Api\Console\Command\Routes' // 无法创建,因为缺少依赖的illuminate组件中的route文件 ]); if (class_exists('Illuminate\Foundation\Application', false)) { $this->commands([ 'Dingo\Api\Console\Command\Cache', 'Dingo\Api\Console\Command\Routes' ]); }
-
API用户身份验证
Lumen虽然没有像laravel一样提供了auth相关的更多服务,但是保留了默认的2种认证驱动,即Eloquent和Database。可在api.php中进行配置修改。
Eloquent驱动中需要指定AUTH_MODEL为一个实现了AuthenticatableContract的模型,可以参考laravel的User模型。
Database驱动中需要指定AUTH_TABLE,且该表属于database中默认的DB_CONNECTION数据库
为了对API进行验证,Dingo自带了HTTP Basic鉴权功能,同时也提供了JWT和OAuth2的验证接口。这里主要尝试了Basic和JWT方法。
通过在api.php中配置auth字段可以声明需要使用的认证服务者,比如
'auth' => [ 'basic' => function ($app) { return new Dingo\Api\Auth\Provider\Basic($app['auth']); }, 'jwt' => function ($app) { return new Dingo\Api\Auth\Provider\JWT($app[‘Tymon\JWTAuth\JWTAuth']); }, ],
指定了Basic和JWTAuth两种方式,因此在lumen中会按照顺序对所需的request进行认证处理,直到成功为止。(在laravel中测试如果增加middleware时指定了provider,则会直接采用对应的认证服务处理)
当前使用MySQL进行2种驱动的验证都可以,使用mongodb还有部分问题未解决。