内容简介:Dingo 扩展包花费了很大的精力来提供从应用内部请求 Dingo API 接口的功能,这意味着,通过 Dingo 扩展包实现的 API 接口不仅可以被客户端和第三方应用消费,还可以为应用内部的 Web 路由和其他 API 路由提供数据和服务支持,这样一来,我们就可以构建一个完全基于 API 驱动的应用,支持内部请求的 API 还有一个好处就是可以返回原生数据对象而不是 HTTP 响应对象,因此,我们可以基于 Laravel 及 Dingo 提供的语法糖来处理返回的结果或者处理抛出的异常。下面我们就来看一下
Dingo 扩展包花费了很大的精力来提供从应用内部请求 Dingo API 接口的功能,这意味着,通过 Dingo 扩展包实现的 API 接口不仅可以被客户端和第三方应用消费,还可以为应用内部的 Web 路由和其他 API 路由提供数据和服务支持,这样一来,我们就可以构建一个完全基于 API 驱动的应用,支持内部请求的 API 还有一个好处就是可以返回原生数据对象而不是 HTTP 响应对象,因此,我们可以基于 Laravel 及 Dingo 提供的语法糖来处理返回的结果或者处理抛出的异常。
下面我们就来看一下如何在 Laravel 应用中通过内部请求消费 Dingo API,要使用内部请求功能,先要获取一个调度器实例:
$dispatcher = app(\Dingo\Api\Dispatcher::class);
快速入门
在 API 路由中请求 API
首先,我们可以在 Dingo API 中消费其它的 API 接口:
$api->version('v3', function ($api) { ... $api->get('task/{id}', function ($id) { $dispatcher = app(\Dingo\Api\Dispatcher::class); $task = $dispatcher->version('v1')->get('dingoapi/task/' . $id); dd($task); }); });
在这个示例中,我们在 Dingo API 的 v3
版本分组中定义一个基于 v1
版本 task/{id}
接口返回数据的路由,在获取到调度器实例后,通过 version
方法指定要消费的 Dingo API 版本,然后通过 get
方法对相应的路由发起 GET 请求返回数据,这样我们就可以获取到对应的任务数据:
在 Web 路由中请求 API
然后,我们可以在 routes/web.php
中定义一个消费上述 Dingo API 的 Web 路由:
$dispatcher = app(\Dingo\Api\Dispatcher::class); Route::get('/task/{id}', function ($id) use ($dispatcher) { $task = $dispatcher->version('v3')->get('dingoapi/task/' . $id); dd($task); });
这次,我们消费的是 v3
版本的 Dingo API 接口,返回数据和上面一样。
内部请求认证 API 接口
在已认证 API 路由中请求
在已认证的 API 路由中请求 Dingo API 的认证接口比较简单,不需要做任何额外的操作,因为已经认证的 API 接口中发起内部请求中会自动带上 Authorization 字段。
在未认证或 Web 路由中请求
在未认证 API 路由或 Web 路由中对 Dingo API 认证接口发起内部请求需要将访问令牌设置到请求头 Authorization
字段中才可以,我们以之前待办任务列表中的 home
路由为例,这是一个 Web 路由,虽然需要认证才能访问,但是 Web 路由认证和 API 路由认证走的是两套体系,之间并不相通,内部请求 的 API 接口需要单独认证,这里我们借助 Passport私人访问令牌来实现该 API 接口的认证,打开 app/Http/Controllers/HomeController.php
,将 index
方法中获取任务列表的逻辑改为基于 Dingo API v3 版本的 tasks.index
接口获取,该接口是需要认证的,我们通过 Passport 私人访问令牌生成访问令牌,然后将其设置到 Authorization
请求头:
public function index(Request $request, Dispatcher $dispatcher) { $params = []; if ($request->has('page')) { $params['page'] = $request->get('page'); } if ($request->has('limit')) { $params['limit'] = $request->get('limit'); } $token = $request->user()->createToken('Internal Request Token')->accessToken; $tasks = $dispatcher->on('todo.test')->header('Authorization', 'Bearer ' . $token)->version('v3')->get('dingoapi/tasks', $params); return view('home', ['tasks' => json_encode($tasks->items())]); }
由于 tasks.index
API 接口还支持分页数据,我们将相应的参数通过调度器实例的 get
方法的第二个参数传递过去。
接口返回的并不是 HTTP 响应实例,而是包含任务列表和分页信息的分页器实例,通过调用该实例上的 items
方法即可返回任务列表数据。
当然为了让 Passport 私人访问令牌生效,还需要通过如下命令创建对应的数据表记录以便用于生成令牌信息:
php artisan passport:client --personal
如果之前已经运行过相关命令或者 oauth_clients
表中已经存在 Laravel Personal Access Client 记录,也可以直接在 AuthServiceProvider
的 boot
方法中通过 Passport 的 personalAccessClientId
方法直接使用该记录:
public function boot() { ... Passport::personalAccessClientId('client-id'); }
将 client_id
替换成相应的数据库主键 ID 即可。
访问 http://todo.test/home
页面,登录成功之后就可以看到任务列表信息了,和之前返回结果一样:
不同的是现在还支持分页功能,这可以通过在请求参数中设置页码和每页显示数量来实现:
更多特性
以上就已经介绍完最常见的通过 GET 方式对 Dingo API 发起的内部请求,此外,Dingo 调度器还支持很多其他方法,通过这些方法,我们可以实现更多更复杂的内部请求,下面我们就一些常见的场景进行介绍。
发起 POST 请求
除了 GET 请求外, Dispatcher
调度器还支持 POST、PUT、PATCH、DELETE 等其它常见的 HTTP 请求方法,以 POST 请求为例,对应的方法名是 post
,我们可以这样通过 POST 请求发送数据:
$dispatcher->with(['name' => '学院君', 'location' => '杭州'])->post('users');
还可以这样:
$dispatcher->post('users', ['name' => '学院君', 'location' => '杭州']);
PUT、PATCH、DELETE 对应的内部请求发送方式也与 POST 一样,这里就不再赘述,详情请看 vendor/dingo/api/src/Dispatcher.php
源码。
上传文件
Dingo API 调度器提供了多种方式来支持上传文件请求,你可以通过传入 Symfony\Component\HttpFoundation\File\UploadedFile
实例到 attach
方法来添加文件到 POST 请求:
$dispatcher->attach(Input::files())->post('photos');
也可以通过数组方式传入文件标识与路径信息来上传文件:
$dispatcher->attach(['photo' => 'photos/me.jpg'])->post('photos');
这种方式还支持一次上传多个文件以及设置多个文件元信息(这种方式避免了服务端计算文件类型和尺寸):
$dispatcher->attach([ 'photo' => [ 'path' => 'photos/me.jpg', 'mime' => 'image/jpeg', 'size' => '49430' ] ])->post('photos');
发送 JSON 格式请求数据
还可以通过调度器上的 json
方法发送 JSON 格式请求数据:
$data = ['name' => 'xueyuanjun', 'password' => '12345678']; $dispatcher->json($data)->post('users');
同时请求头中 Content-Type 字段会被设置为 application/json
。
获取原生响应对象
内部请求默认返回的是未经转化和格式化的原生数据对象,如果你想要获取响应对象,可以调用 raw
方法实现:
$response = $dispatcher->raw()->get('users');
异常及错误处理
通过内部请求调用 Dingo API 时,所有接口处理过程中抛出的异常都需要手动捕获并处理,比如 Api\TaskController
的 store
方法抛出冲突异常:
use Symfony\Component\HttpKernel\Exception\ConflictHttpException; public function store(CreateTaskRequest $request) { throw new ConflictHttpException('we got a conflict!'); }
如果对该方法对应 API 路由发起内部请求,则需要手动捕获抛出的异常:
try { app(\Dingo\Api\Dispatcher::class)->with($payload)->post('dingoapi/tasks'); } catch (Symfony\Component\HttpKernel\Exception\ConflictHttpException $e) { // Do something here, like return with an error. }
如果某个 API 接口返回的是错误响应,比如 show
方法这样:
public function show($id) { if (!is_numeric($id)) { return $this->response->errorBadRequest(); } $task = Task::find($id); if (!$task) { return $this->response->errorNotFound(); } ... }
则在对其发起内部请求的时候,需要捕获 Dingo\Api\Exception\InternalHttpException
异常:
try { $task = $dispatcher->version('v3')->get('dingoapi/tasks/' . $id); } catch (\Dingo\Api\Exception\InternalHttpException $exception) { return $exception->getResponse(); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使⽤用Requests库构建⼀一个HTTP请求
- 基于 Laravel + Vue 构建 API 驱动的 LBS 应用系列教程(八) —— 通过 Axios 库构建 API 请求
- 详解nginx的请求限制(连接限制和请求限制)
- angular请求防抖,以及处理第一次请求失效
- RxHttp 一条链发送请求,新一代Http请求神器(一)
- RxHttp 一条链发送请求,新一代Http请求神器(一)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。