kelemen / api-nette
Nette 框架的 API
Requires
- php: >= 5.6
Requires (Dev)
- nette/nette: ~2.4
- phpunit/phpunit: ^5.3
- squizlabs/php_codesniffer: ^2.6
README
高度可定制且易于设置的 Nette 框架 RESTful API 处理。
安装
composer require kelemen/api-nette
准备使用
-
首先,您需要一个用于处理 API 请求的 API 展示器。您可以使用
Kelemen\ApiNette\Presenter\ApiPresenter
或自己编写。 -
在 config.neon 中注册新的映射
application: mapping: Api: Kelemen\ApiNette\Presenter\*Presenter
-
将 API 路由添加到路由器中。我们使用关键字 api 来识别 API 请求。
$router[] = new Route("api/<params .*>", [ 'presenter' => 'Api', 'action' => 'default' ]);
-
配置 API(示例来自 config.neon)
services: - Kelemen\ApiNette\Logger\Storage\DummyLoggerStorage - Kelemen\ApiNette\Logger\Logger api: class: Kelemen\ApiNette\Api setup: - get('users', 'Custom\Users\ListHandler') - get('users/<id>', 'Custom\Users\DetailHandler') - put('users/<id>', 'Custom\Users\CrateHandler', [middleware: ['Custom\Auth\Bearer']) - post('users/<id>', 'Custom\Users\UpdateHandler', [middleware: ['Custom\Auth\Bearer']])
API 路由
将路由添加到 API
可以使用快捷函数(用于大多数使用的 HTTP 方法)定义 RESTful API 路由。
- get
- post
- put
- patch
- delete
- options
或者,您可以使用 add($method, $pattern, $handler, $params = [])
函数添加任何 HTTP 方法处理。
$api = new Api(...); $api->add('purge', 'purge/urls', 'Handlers\PurgeHandler')
路由模式
在路由定义中,您可以使用正则表达式或定义在 < 和 > 之间的参数。路由按添加的顺序评估。因此,首先定义特定路由。
$api = new Api(...); $api->get('users', 'Handler'); // exact match for (with our route) /api/users $api->get('users/<id>', 'Handler'); // parse parameter id from routes like /api/users/10, /api/users/sdk-2323 etc. $api->get('users/<id>/message/<messageId>', 'Handler'); // parse parameters id and messageId from matched requests // Optional parameters are not supported. If optional parameter is needed we have to define multiple routes. $api->get('users/<id>/message', 'Handler'); $api->get('users/<id>/message/<messageId>', 'Handler'); // In route definition we can use any regular expression. $api->options('.*', 'Handler'); // process OPTIONS call for any incoming URL
路由处理程序
路由定义使用 Nette DI 容器的 延迟加载。处理程序通过 类型 或通过在 config.neon 文件中注册的 名称 定义。对于名称定义,在服务名称前缀加上 #。
$api = new Api(...); $api->get('users', 'Full\Namespace\For\Handler'); // By type $api->get('users/<id>', '#registeredHandlerName'); // By name
路由参数
现在仅接受 中间件 键作为参数。中间件定义使用与处理程序相同的 延迟加载 逻辑。
$api = new Api(...); $api->get('users', 'Full\Namespace\For\Handler', ['middleware' => [ 'Middleware\Auth\Bearer', // By type '#bearerAuthorization' // By name ]]);
处理程序
处理程序提供已解析 API 路由的业务逻辑。
use Nette\Http\Request; use Nette\Http\Response; use Kelemen\ApiNette\Handler\BaseHandler; use Kelemen\ApiNette\Response\JsonApiResponse; use Kelemen\ApiNette\Validator\Validation; class UserGetHandler extends BaseHandler { // Here we can define validation rules for input parameters (see section Validations below). // This function is optional. public function validate() { return [ new Validation('path', 'id', 'required|integer'), new Validation('get', 'page', 'integer:1..100') ]; } // Main function. Process request and return ApiResponse. public function __invoke(Request $request, Response $response, callable $next) { // ... do some business logic as filtering, database requests etc. // All validated values are acessible via $this->values array $id = $this->values['id']; if ($id && isset($this->values['page'])) { ... } return new JsonApiResponse(200, ['data' => [ 'id' => 1, 'name' => 'Samuel' ]]); } }
验证
重要!每个参数都解析为字符串!因此,请使用 数字 验证规则而不是整数或浮点数。
主要验证由 Nette 验证器 处理。验证在处理程序的 validate()
函数中注册。所有已验证输入参数都可通过处理程序的 $this->values
数组访问。
如果任何验证失败,API 会自动发送带有 400 HTTP 代码的响应,并包含所有验证错误。
自定义验证规则
默认情况下,您不需要将新的 Validator 实例注册到 API。但如果您想注册新的验证或覆盖现有的验证,您需要创建并配置自己的 Validator 实例。
$validator = new Kelemen\ApiNette\Validator\Validator(); $validator->setValidator('enum', function ($value, $ruleParams = null) { // $value - contains parameter value // $ruleParams - contains string from parsed rule after ":" return in_array($value, explode(',', $ruleParams)); }); // Usage in validation funciton ... public function validate() { return new Validation('get', 'name', 'required|enum:Samuel,Peter') }
输入
验证器定义了默认的输入集
如果您想添加特殊输入,您可以使用 setInput($name, InputInterface $input)
函数将此输入添加到验证器中。
中间件
可以通过中间件扩展 API 流程。中间件接口只有一个函数 __invoke(Request $request, Response $response, callable $next)
。中间件是如何工作的
use Kelemen\ApiNette\Middleware\Middleware; use Nette\Http\Request; use Nette\Http\Response; class CustomMiddleware implements Middleware { public function __invoke(Request $request, Response $response, callable $next) { // This code is executed before handler (Optional) // Example: provide authentification here. If user is authenticated call $next() if no return new response if ($request->isSecured()) { // Do something ... } // Call next middleware or handler if last middleware (Optional) $resp = $next($request, $response); // This code is executed after handler (Optional) // Example: add CORS headers here $response->setHeader('custom header', 'header value'); // Mandatory! Every middleware has to return response! return $resp; } }
如果我们注册了 3 个中间件
['middleware1', 'middleware2', 'middleware3']
流程将如下所示
- middleware1
- middleware2
- middleware3
- handler (return Nette\Application\IResponse)
- middleware3
- middleware2
- middleware1
流程和异常
库附带默认的 API 展示器 Kelemen\ApiNette\Presenter\ApiPresenter
。此展示器运行 API 并处理所有异常(根据捕获的异常创建响应)。如果您想自定义错误响应,创建并注册自己的展示器。
API 抛出以下异常
基本实现
中间件
CORSMiddleware
设置 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 标头。中间件有 3 种模式
- all - 返回允许源为 "*"。凭据标头通过标准禁用。
- 镜像 - 返回请求头 "Origin",允许源(allow-origin)和凭据(credentials)头可以手动配置。
- 自定义 - 必须配置允许源(allow-origin)头,凭据(credentials)头可以手动配置。
处理程序
OptionsPreflightHandler
可配置的浏览器 CORS 预检请求处理器。可配置的响应头
- Access-Control-Max-Age
- Access-Control-Expose-Headers
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers