Browse Source

some bug fixed for RESTFul controller

inhere 2 years ago
parent
commit
7cc1ce0633

+ 1 - 12
README.md

@@ -14,7 +14,7 @@ Some Feature :
 - Monolog
 - Pimple Dependency Injection Container
 - Controller layer for MVC
-- REST Controller
+- RESTFul Controller
 - Model layer, database query builder.
 - Tracy Errors Handler(by whoops)
 
@@ -30,17 +30,6 @@ _require_ add
 "inhere/slim-extend": "dev-master",
 ```
 
-_repositories_ add 
-
-```
-"repositories": [
-        {
-            "type": "git",
-            "url": "https://github.com/inhere/slim-extend"
-        }
-    ]
-```
-
 run: `composer update`
 
 ## Usage

+ 5 - 2
doc/restful.md

@@ -16,6 +16,8 @@
 
 ## controller 
 
+> default RESTFul action name equals to `REQUEST_METHOD`
+
 if use controller layer. the controller class is must be extends the `slimExt\rest\Controller`
 
 ```
@@ -56,7 +58,8 @@ class Test extends Controller
 
         return $this->response->withJson(['list' => $list]);
     }
-
+    
+    // 这里的id 可以是 int|string
     public function getAction($id)
     {
         // can also return array. it will be translate to json.
@@ -80,4 +83,4 @@ class Test extends Controller
         ]);
     }
 }
-```
+```

+ 29 - 28
src/filters/AccessFilter.php

@@ -8,16 +8,14 @@
 
 namespace slimExt\filters;
 
-use inhere\libraryPlus\auth\User;
-use Slim;
-use inhere\library\helpers\ArrayHelper;
+use inhere\library\helpers\Arr;
 
 /**
  * Class AccessFilter
  * auth/permission check
  * @package slimExt\filters
  */
-class AccessFilter extends ObjectFilter
+class AccessFilter extends BaseFilter
 {
     /**
      * access rules
@@ -35,9 +33,12 @@ class AccessFilter extends ObjectFilter
                 // false - deny access
                 'allow' => true,
 
-                // use defined mark char: '?' guest user '@' logged user '*' all user.
-                // use custom role name. like 'member', 'admin' (the role name is must be unique, and it is save on dabatase.)
-                // can also use role id: 12 43 (it is not recommend)
+                // 1. use defined mark char:
+                //     '?' guest user
+                //     '@' logged user
+                //     '*' all user.
+                // 2. use custom role name. like 'member', 'admin' (the role name is must be unique, and it is save on dabatase.)
+                // 3. can also use role id: 12 43 (it is not recommend)
                 // Notice: there are role relation is OR.
                 'roles' => ['*'],
 
@@ -51,39 +52,42 @@ class AccessFilter extends ObjectFilter
     ];
 
     /**
-     * the role filed name in the user(Slim::$app->user).
+     * the role filed name in the user(\Slim::$app->user).
      * @var string
      */
     public $userRoleField = 'role';
 
     /**
+     * on access denied
+     * @var callable
+     */
+    public $onDenied;
+
+    /**
      * {@inheritDoc}
      */
     protected function doFilter($action)
     {
-        /**
-         * current user
-         * @var User
-         */
-        $user = Slim::$app->user;
+        /** @var \inhere\libraryPlus\auth\User */
+        $user = \Slim::$app->user;
         $allow = true;
 
         foreach ($this->rules as $rule) {
             // no limit
             if (
                 !$rule
-                || ($actions = (array)ArrayHelper::get($rule, 'actions'))
-                || ($roles = (array)ArrayHelper::get($rule, 'roles'))
+                || !($actions = (array)Arr::get($rule, 'actions'))
+                || !($roles = (array)Arr::get($rule, 'roles'))
             ) {
                 continue;
             }
 
             // don't match current action
-            if (self::MATCH_ALL !== $actions[0] || !in_array($action, $actions, true)) {
+            if (self::MATCH_ALL !== $actions[0] && !in_array($action, $actions, true)) {
                 continue;
             }
 
-            $allow = ArrayHelper::get($rule, 'allow', false);
+            $allow = Arr::get($rule, 'allow', false);
 
             // find match all user, char: *
             if (in_array(self::MATCH_ALL, $roles, true)) {
@@ -106,21 +110,18 @@ class AccessFilter extends ObjectFilter
             if ($userRoles && array_intersect((array)$userRoles, $roles)) {
                 break;
             }
-        }
 
-        // deny access
-        if (!$allow) {
-            // when is xhr
-            if ($this->request->isXhr()) {
-                $data = ['redirect' => $user->loginUrl];
-
-                return $this->response->withJson($data, __LINE__, slim_tl('http:403'), 403);
+            // use custom callback
+            if (($cb = Arr::get($role, 'callback')) && $cb($action, $user)) {
+                break;
             }
+        }
 
-            return $this->response->withRedirect($user->loginUrl, 403)->withMessage(slim_tl('http403'));
+        // deny access
+        if (!$allow && ($cb = $this->onDenied)) {
+            return call_user_func($cb, $action, $user);
         }
 
-        // allow access
-        return true;
+        return (bool)$allow;
     }
 }

+ 10 - 5
src/filters/ObjectFilter.php

@@ -16,8 +16,9 @@ use slimExt\web\Response;
  * Class BaseFilter
  * @package slimExt\filters
  */
-abstract class ObjectFilter extends StdObject
+abstract class BaseFilter extends StdObject
 {
+    // all user
     const MATCH_ALL = '*';
 
     // logged user
@@ -40,7 +41,7 @@ abstract class ObjectFilter extends StdObject
      * @param Request $request
      * @param Response $response
      * @param $action
-     * @return bool
+     * @return mixed
      */
     public function __invoke(Request $request, Response $response, $action)
     {
@@ -52,10 +53,14 @@ abstract class ObjectFilter extends StdObject
     }
 
     /**
-     * how to get controller instance?
-     *  `Slim::get('controller')`
+     * how to get controller instance? use `\Slim::get('controller')`
      * @param string $action
-     * @return bool
+     * @return mixed
+     *
+     * Return:
+     *     bool     True is allow access, False is Deny
+     *     string   Deny, is the error message
+     *     Response Deny, A Response instance
      */
     abstract protected function doFilter($action);
 }

+ 3 - 3
src/filters/VerbFilter.php

@@ -9,12 +9,12 @@
 namespace slimExt\filters;
 
 /**
- * Class VerbFilter
+ * Class VerbsFilter
  *
  * filter the request method
  * @package slimExt\filters
  */
-class VerbFilter extends ObjectFilter
+class VerbsFilter extends BaseFilter
 {
     /**
      * in Controller:
@@ -23,7 +23,7 @@ class VerbFilter extends ObjectFilter
      * {
      *     return [
      *       'verbs' => [
-     *           'handler' => VerbFilter::class,
+     *           'filter' => VerbsFilter::class,
      *           'actions' => [
      *               'index' => ['get'],
      *               'add'   => ['post', 'put'],

+ 22 - 9
src/web/AbstractController.php

@@ -10,7 +10,7 @@ namespace slimExt\web;
 
 use inhere\exceptions\NotFoundException;
 use Psr\Http\Message\ResponseInterface;
-use slimExt\filters\ObjectFilter;
+use slimExt\filters\BaseFilter;
 
 /**
  * Class AbstractController
@@ -102,6 +102,12 @@ abstract class AbstractController
     abstract protected function processInvoke(array $args);
 
     /**
+     * @param mixed $result
+     * @return ResponseInterface
+     */
+    abstract protected function onSecurityFilterFail($result);
+
+    /**
      * @param array $args
      * @param ResponseInterface $response
      * @return void
@@ -121,7 +127,7 @@ abstract class AbstractController
     {
         return [
             'access' => [
-                // 'filter' => AccessFilter::class,
+                // 'filter' => AccessFilter::class, // 过滤器类
                 'rules' => [
 //                    [
 //                        'actions' => ['login', 'error'],
@@ -137,7 +143,7 @@ abstract class AbstractController
                 ],
             ],
 //            'verbs' => [
-//                'filter' => VerbFilter::class,
+//                'filter' => VerbsFilter::class,
 //                'actions' => [
 //                    //'logout' => ['post'],
 //                ],
@@ -146,8 +152,15 @@ abstract class AbstractController
     }
 
     /**
+     * do Security Filter
      * @param $action
      * @return mixed
+     *
+     * Return:
+     *     bool     True is allow access, False is Deny
+     *     string   Deny, is the error message
+     *     Response Deny, A Response instance
+     *
      * @throws NotFoundException
      */
     protected function doSecurityFilter($action)
@@ -167,19 +180,19 @@ abstract class AbstractController
             }
 
             if (!class_exists($filter)) {
-                throw new NotFoundException("Filter class [$filter] not found.");
+                throw new NotFoundException("The filter class [$filter] not found.");
             }
 
             $filter = new $filter($settings);
 
-            if (!$filter instanceof ObjectFilter) {
-                throw new NotFoundException('Filter class must be instanceof ' . ObjectFilter::class);
+            if (!$filter instanceof BaseFilter) {
+                throw new NotFoundException('The filter class must be instanceof ' . BaseFilter::class);
             }
 
-            $result = $filter($this->request, $this->response, $action);
+            $resp = $filter($this->request, $this->response, $action);
 
-            if (true !== $result) {
-                return $result;
+            if (true !== $resp) {
+                return $resp;
             }
         }
 

+ 19 - 0
src/web/App.php

@@ -39,6 +39,25 @@ class App extends \Slim\App
     }
 
     /**
+     * Add route for RESTFul resource
+     *
+     * ```php
+     *  $this->rest('/users', controllers\User::class);
+     *  // Equals to:
+     *  // $this->any('/users[/{resource}]', controllers\User::class);
+     * ```
+     *
+     * @param  string $name  The resource name e.g '/users'
+     * @param  string $class The resource controller class
+     *
+     * @return \Slim\Interfaces\RouteInterface
+     */
+    public function rest($name, $class)
+    {
+        return $this->any($name . '[/{resource}]', $class);
+    }
+
+    /**
      * @param $id
      * @return \Interop\Container\ContainerInterface|mixed
      */

+ 20 - 1
src/web/Controller.php

@@ -446,7 +446,7 @@ abstract class Controller extends AbstractController
 
         // if enable request action security filter
         if (true !== ($result = $this->doSecurityFilter($action))) {
-            return $result;
+            return $this->onSecurityFilterFail($result);
         }
 
         $resp = $this->$actionMethod($args);
@@ -460,6 +460,25 @@ abstract class Controller extends AbstractController
     }
 
     /**
+     * @inheirtdoc
+     */
+    protected function onSecurityFilterFail($result)
+    {
+        if ($resp instanceof ResponseInterface) {
+            return $resp;
+        }
+
+        $msg = $resp && is_string($resp) ? $resp : 'Access is not allowed';
+
+        // when is xhr
+        if ($this->request->isXhr()) {
+            return $this->response->withJson(-403, $msg , 403);
+        }
+
+        return $this->response->withGoBack('/')->withMessage($msg);
+    }
+
+    /**
      * when route have been setting action name:
      * ```
      * $app->get('/users/{id}', controllers\User::class . ':view');

+ 2 - 5
src/web/Response.php

@@ -10,7 +10,6 @@ namespace slimExt\web;
 
 use inhere\slimExt\components\JsonMessage;
 use Slim;
-use Slim\Http\Response as SlimResponse;
 
 /**
  * extension Slim's Response class
@@ -18,7 +17,7 @@ use Slim\Http\Response as SlimResponse;
  * Class Response
  * @package slimExt\web
  */
-class Response extends SlimResponse
+class Response extends \inhere\http\Response
 {
     /**
      * @param mixed $data
@@ -27,10 +26,8 @@ class Response extends SlimResponse
      * @param int $status
      * @return \Psr\Http\Message\ResponseInterface
      */
-    public function withJson($data, $code = null, $msg = '', $status = 200)
+    public function withJson($data, $code = 0, $msg = '', $status = 200)
     {
-        $code = null === $code ? 0 : (int)$code;
-
         if ($data instanceof JsonMessage) {
             return parent::withJson($data, $status);
         }

+ 145 - 113
src/web/RestController.php

@@ -9,6 +9,7 @@
 namespace slimExt\web;
 
 use inhere\exceptions\UnknownMethodException;
+use Psr\Http\Message\ResponseInterface;
 
 /**
  * Class RestFulController
@@ -19,15 +20,15 @@ use inhere\exceptions\UnknownMethodException;
  * ```
  * class Book extends slimExt\web\RestController
  * {
- *     public function getsAction($args)
+ *     public function getsAction()
  *     {}
- *     public function getAction($args)
+ *     public function getAction($id)
  *     {}
- *     public function postAction($args)
+ *     public function postAction()
  *     {}
- *     public function putAction($args)
+ *     public function putAction($id)
  *     {}
- *     public function deleteAction($args)
+ *     public function deleteAction($id)
  *     {}
  *     ... ...
  * }
@@ -36,15 +37,15 @@ use inhere\exceptions\UnknownMethodException;
  * in routes
  *
  * ```
- * $app->any('/api/test[/{action}]', api\Book::class);
+ * $app->any('/api/books[/{resource}]', Book::class);
  * ```
  */
 abstract class RestController extends AbstractController
 {
     const DEFAULT_ERR_CODE = 2;
 
-    // $app->any('/api/test[/{action}]', api\Book::class);
-    const RESOURCE_ARG_KEY = 'action';
+    // $app->any('/api/test[/{resource}]', api\Book::class);
+    const RESOURCE_KEY = 'resource';
 
     // match request like GET /users (get all resource)
     const MARK_MORE = '*';
@@ -65,6 +66,12 @@ abstract class RestController extends AbstractController
     private $actionSuffix = 'Action';
 
     /**
+     * @see self::parseRequestMethod()
+     * @var string|int
+     */
+    private $resourceId;
+
+    /**
      * @var array
      */
     protected $except = [];
@@ -83,7 +90,7 @@ abstract class RestController extends AbstractController
     public function headsAction()
     {
         return $this->response
-            ->withHeader('X-Welcome', 'Hi, Welcome to the network.')
+            ->withHeader('X-Welcome', 'Hi, Welcome to the network world.')
             ->withHeader('X-Request-Method', 'method heads');
     }
 
@@ -94,7 +101,7 @@ abstract class RestController extends AbstractController
     public function headAction($id = 0)
     {
         return $this->response
-            ->withHeader('X-Welcome', 'Hi, Welcome to the network.')
+            ->withHeader('X-Welcome', 'Hi, Welcome to the network world.')
             ->withHeader('X-Request-Method', 'method head')
             ->withHeader('X-Request-Param', $id);
     }
@@ -116,18 +123,15 @@ abstract class RestController extends AbstractController
     {
         return [
 //            'access' => [
-//                'filter' => AccessFilter::class,
-//                'rules' => [
-//                    [
-//                        'actions' => ['login', 'error'],
-//                        'allow' => true,
-//                    ],
-//                    [
-//                        'actions' => ['logout', 'index'],
-//                        'allow' => true,
-//                        'roles' => ['@'],
-//                    ],
-//                ],
+//                'filter' => AccessFilter::class, // 过滤器类
+//                'rules' => [ [
+//                    'actions' => ['login', 'error'],
+//                    'allow' => true,
+//                 ], [
+//                    'actions' => ['logout', 'index'],
+//                    'allow' => true,
+//                    'roles' => ['@'],
+//                ]],
 //            ]
         ];
     }
@@ -138,25 +142,28 @@ abstract class RestController extends AbstractController
 
     /**
      * method mapping - the is default mapping.
-     * supported method:
-     *     CONNECT DELETE GET HEAD OPTIONS PATCH POST PUT TRACE
+     * supported method: CONNECT DELETE GET HEAD OPTIONS PATCH POST PUT TRACE SEARCH
+     * you can override it. e.g:
      *
-     * you can change it. e.g:
+     * ```php
      * protected function methodMapping()
      * {
      *     return [
-     *         'get*'   => 'index',   # GET /users
-     *         'get'      => 'view',    # GET /users/1
-     *         'post'     => 'create',  # POST /users
-     *         'put'      => 'update',  # PUT /users/1
-     *         'delete'   => 'delete',  # DELETE /users/1
+     *         'get*'   => 'index',   // GET /users
+     *         'get'    => 'view',    // GET /users/1
+     *         'post'   => 'create',  // POST /users
+     *         'put'    => 'update',  // PUT /users/1
+     *         'delete' => 'delete',  // DELETE /users/1
      *         // ...
      *     ];
+     *
      *     // or
      *     // $mapping = parent::methodMapping();
      *     // $mapping['get'] = 'xxx';
      *     // return $mapping;
      * }
+     * ```
+     *
      * @return array
      */
     protected function methodMapping()
@@ -164,60 +171,135 @@ abstract class RestController extends AbstractController
         return [
             //REQUEST_METHOD => method name(no suffix)
             // 'gets' is special key.
-            'get*' => 'gets',      # GET /users
-            'get' => 'get',       # GET /users/1
-            'post' => 'post',      # POST /users
-            'put' => 'put',       # PUT /users/1
-            # usually PUT == PATCH
-            'patch' => 'patch',     # PATCH /users/1
-            'delete' => 'delete',    # DELETE /users/1
-            'head' => 'head',      # HEAD /users/1
-            'head*' => 'heads',     # HEAD /users
-            'options' => 'option',    # OPTIONS /users/1
-            'options*' => 'options',   # OPTIONS /users
-
-            'connect' => 'connect',   # CONNECT /users
-            'trace' => 'trace',     # TRACE /users
+            'get*' => 'gets',      // GET /users
+            'get' => 'get',        // GET /users/1
+            'post' => 'post',      // POST /users
+            'put' => 'put',        // PUT /users/1
+            // usually PUT == PATCH
+            'patch' => 'patch',      // PATCH /users/1
+            'delete' => 'delete',    // DELETE /users/1
+            'head' => 'head',        // HEAD /users/1
+            'head*' => 'heads',      // HEAD /users
+            'options' => 'option',    // OPTIONS /users/1
+            'options*' => 'options',   // OPTIONS /users
+
+            'connect' => 'connect',   // CONNECT /users
+            'search' => 'search',     // SEARCH /users
+            'trace' => 'trace',       // TRACE /users
 
             // multi REQUEST_METHOD match
             // 'get|post' => 'index'
 
             // extra method mapping
             // 'get.search' => search
-            // 'post.save'  => save
+            // 'post.create'  => create
+            // 'post|put.save'  => save
         ];
     }
 
+    /**********************************************************
+     * call the controller method
+     **********************************************************/
+
+    /**
+     * e.g.
+     * define route:
+     *
+     * ```
+     *   $app->any('/test[/{resource}]', controllers\api\Test::class);
+     * ```
+     *
+     * @param array $args
+     * @return \Psr\Http\Message\ResponseInterface
+     * @throws \Exception
+     */
+    protected function processInvoke(array $args)
+    {
+        // default restFul action name
+        list($action, $error) = $this->parseRequestMethod($this->request, $args);
+
+        if ($error) {
+            return $this->errorHandler($error);
+        }
+
+        $actionMethod = $action . ucfirst($this->actionSuffix);
+
+        if (!method_exists($this, $actionMethod)) {
+            // throw new NotFoundException('Error Processing Request, Action [' . $action . '] don\'t exists!');
+            $msg = 'Error Processing Request, resource method [' . $action . '] don\'t exists!';
+
+            return $this->response->withJson([], -404, $msg, 404);
+        }
+
+        // if enable request action security filter
+        if (true !== ($result = $this->doSecurityFilter($action))) {
+            return $this->onSecurityFilterFail($result);
+        }
+
+        /** @var Response $response */
+        $resp = $this->$actionMethod(array_shift($args));
+
+        // if the action return is array data
+        if (is_array($resp)) {
+            $resp = $this->response->withJson($resp);
+        }
+
+        return $resp;
+    }
+
+    /**
+     * @inheirtdoc
+     */
+    protected function onSecurityFilterFail($result)
+    {
+        if ($resp instanceof ResponseInterface) {
+            return $resp;
+        }
+
+        $msg = $resp && is_string($resp) ? $resp : 'Resources not allowed for access';
+
+        return $this->response->withJson([], -403, $msg, 403);
+    }
+
     /**
-     * handleMethodMapping -- return real controller method name
+     * parseRequestMethod -- return real controller method name
      * @param  Request $request
      * @param array $args
      * @return string
      * @throws UnknownMethodException
      */
-    private function handleMethodMapping($request, array $args)
+    private function parseRequestMethod($request, array $args)
     {
         // default restFul action name, equals to REQUEST_METHOD
-        $method = strtolower($request->getMethod());
         $mapping = $this->methodMapping();
 
         if (!$mapping || !is_array($mapping)) {
-            throw new UnknownMethodException('No any accessible resource method!');
+            return [null, 'No any accessible resource method!'];
         }
 
-        $argument = !empty($args[self::RESOURCE_ARG_KEY]) ? trim($args[self::RESOURCE_ARG_KEY]) : '';
+        // 值可能是:
+        // 1. 是资源名/资源ID
+        //  e.g GET `/users/12`
+        //  - $resourceId = 12
+        //  e.g GET `/blog/a-post-name`
+        //  - $resourceId = 'a-post-name'
+        // 2. 是扩展资源方法
+        //  e.g GET `/users/search` 同时 `methodMapping()` 配置了 `'get.search' => search`
+        //  - $resourceId = 'search'
+        $resourceId = !empty($args[self::RESOURCE_KEY]) ? trim($args[self::RESOURCE_KEY]) : '';
 
         // convert 'first-second' to 'firstSecond'
-        if ($argument && strpos($argument, '-')) {
-            $argument = ucwords(str_replace('-', ' ', $argument));
-            $argument = str_replace(' ', '', lcfirst($argument));
+        if ($resourceId && strpos($resourceId, '-')) {
+            $resourceId = ucwords(str_replace('-', ' ', $resourceId));
+            $resourceId = str_replace(' ', '', lcfirst($resourceId));
         }
 
         $map = $this->parseMethodMapping($mapping);
+        $method = strtolower($request->getMethod());
 
-        // match like 'get.search' extra method
-        if ($argument) {
-            $extraKey = $method . self::M2A_CHAR . $argument;
+        // 是扩展资源方法 e.g 'get.search'
+        if ($resourceId && !is_numeric($resourceId)) {
+            $extraKey = $method . self::M2A_CHAR . $resourceId;
 
             if (isset($map[$extraKey])) {
                 return [$map[$extraKey], null];
@@ -226,14 +308,16 @@ abstract class RestController extends AbstractController
 
         $action = $error = '';
         $moreKey = $method . self::MARK_MORE;
+        $this->resourceId = $resourceId;
 
+        // 根据请求方法 匹配 资源方法
         foreach ($map as $key => $value) {
-            // like 'get*' 'head*'
-            if (!$argument && $key === $moreKey && in_array($method, self::$allowMore, true)) {
+            // want get resources. like 'get*' 'head*'
+            if (!$resourceId && $key === $moreKey && in_array($method, self::$allowMore, true)) {
                 $action = $value;
 
-                // have argument. like '/users/1' '/users/username'
-            } else if ($key === $method) {
+                // is a resource. like '/users/1' '/users/username'
+            } elseif ($key === $method) {
                 $action = $method === 'options' ? 'option' : $value;
             }
 
@@ -262,7 +346,7 @@ abstract class RestController extends AbstractController
             $key = str_replace(' ', '', $key);
             $item = trim($item);
 
-            // get.search get|post.search
+            // `get.search = search` `get|post.search = search`
             if (strpos($key, '.')) {
                 list($m, $a) = explode('.', $key);
 
@@ -293,58 +377,6 @@ abstract class RestController extends AbstractController
         return $map;
     }
 
-    /**********************************************************
-     * call the controller method
-     **********************************************************/
-
-    /**
-     * e.g.
-     * define route:
-     *
-     * ```
-     *   $app->any('/test[/{resource}]', controllers\api\Test::class);
-     * ```
-     *
-     * @param array $args
-     * @return mixed
-     * @throws \Exception
-     */
-    protected function processInvoke(array $args)
-    {
-        // default restFul action name
-        list($action, $error) = $this->handleMethodMapping($this->request, $args);
-
-        if ($error) {
-            return $this->errorHandler($error);
-        }
-
-        $actionMethod = $action . ucfirst($this->actionSuffix);
-
-        if (!method_exists($this, $actionMethod)) {
-            // throw new NotFoundException('Error Processing Request, Action [' . $action . '] don\'t exists!');
-            $error = 'Error Processing Request, Action [' . $action . '] don\'t exists!';
-
-            return $this->response->withJson([], 330, $error, 403);
-//          return $this->errorHandler($error);
-        }
-
-        // if enable request action security filter
-        if (true !== ($result = $this->doSecurityFilter($action))) {
-            return $result;
-        }
-
-        /** @var Response $response */
-        $resp = $this->$actionMethod(array_shift($args));
-
-        // if the action return is array data
-        if (is_array($resp)) {
-            $resp = $this->response->withJson($resp);
-        }
-
-        return $resp;
-    }
-
-
     /**
      * @param string $error
      * @param int $code