【问题标题】:Laravel Route Filter not Updating ResponseLaravel 路由过滤器不更新响应
【发布时间】:2014-04-24 22:10:19
【问题描述】:

我在我的 API(一个 Laravel 4.1.* 应用程序)中使用了用于 OAuth 的 lucadegasperi/oauth2-server-laravel 包,它提供了一个过滤器,以便在运行这样的路由之前轻松验证授权:

Route::group(array('prefix' => 'api', 'before' => 'oauth:auth'), function() {
   // My API Routes
});

它返回的 JSON 响应不符合我在 API 中使用的格式,并且希望将其更改为一致。所以我在 filters.php 中创建了一个过滤器,并将其设置为作为 after 过滤器运行。

Route::group(array('prefix' => 'core', 'before' => 'oauth:auth', 'after' => 'oauth.cleanresponse'), function() {
   // My API Routes
)};

还有过滤器:

/**
* OAuth Package returns JSON response in custom format that is not consistent with
* Core API output. We need to alter the output to fit the standard response.
*/
Route::filter('oauth.cleanresponse', function($request, $response) {

   if ($response instanceof Illuminate\Http\JsonResponse)
   {
      $responseData = $response->getData();
      if (isset($responseData->error_message));
      {
        $newResponse = new API\ApiResponse();
        $newResponse->setError($responseData->error_message);
        $newResponse->setCode($responseData->status);
        return Response::json($newResponse->error(), $responseData->status);      
      }
   }

   });

过滤器运行良好,我可以在返回之前var_dump() 删除我的更改。

但是响应中API调用返回的值不是我的新值,它仍然是oauth库在before过滤器中创建的原始值。

TL;DR;为什么 after 过滤器的响应不会覆盖 before 过滤器的响应,我该如何解决这个问题?

注意:我不想编辑 OAuth 包,因为无论何时我执行 composer update,它都可能会覆盖我的更改。

编辑

仔细检查 Laravel 路由器(Illuminate/Routing/Router.php)有这样的:

/**
 * Dispatch the request to a route and return the response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return mixed
 */
public function dispatchToRoute(Request $request)
{
    $route = $this->findRoute($request);

    $this->events->fire('router.matched', array($route, $request));

    // Once we have successfully matched the incoming request to a given route we
    // can call the before filters on that route. This works similar to global
    // filters in that if a response is returned we will not call the route.
    $response = $this->callRouteBefore($route, $request);

    if (is_null($response))
    {
        $response = $route->run($request);
    }

    $response = $this->prepareResponse($request, $response);

    // After we have a prepared response from the route or filter we will call to
    // the "after" filters to do any last minute processing on this request or
    // response object before the response is returned back to the consumer.
    $this->callRouteAfter($route, $request, $response);

    return $response;
}

如果 before 过滤器返回结果然后它调用 after 过滤器,它似乎会阻止分派请求。问题是它没有捕获响应!好像是这样的:

$this->callRouteAfter($route, $request, $response);

应该是这样的(虽然这具体不起作用):

$response = $this->callRouteAfter($route, $request, $response);

谁能想到解决办法?

【问题讨论】:

  • 在我发现你的问题之前,我几乎向 laravel/framework 发送了一个拉取请求。

标签: php laravel laravel-4


【解决方案1】:

你必须在当前实例中设置响应

$json = 'prepare the json here';
// set and return response with new data
return $response->setContent($json);

【讨论】:

  • “在当前实例中”——什么意思?
  • function($request, $response) 中作为参数接收。
  • 它是值的副本(即不通过引用传递)。这行不通。
  • setCOntent() 用于在响应中设置新内容的方法,您尝试过吗?不确定,因为您正在使用另一个API,所以请尝试一下,如果不起作用,那么我将删除我的答案。
  • @cilosis setContent() 之所以有效,是因为在 PHP 5 中对象是通过引用传递(和分配)的。
【解决方案2】:

“After”过滤器有3个参数,而不是2个:路由、请求和响应(“之前”过滤器只有2个:路由和请求,因为那个阶段没有响应)。

在您的代码中,您的后过滤器函数只有两个参数,因此您的$request 包含一个Route,而您的$response 包含一个请求。您需要添加$route 作为第一个参数。

之后,您可以调用$response->header()$response->setContent() 来修改生成的响应。

“After”过滤器不能返回一个新的$response,它们只能修改传递给它们的那个。

示例工作代码:

Route::filter('api_headers', function($route, $request, $response) {
    $response->header('Access-Control-Allow-Origin', '*');
    $response->header('P3P', 'CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
});
Route::group(array('prefix'=>'api', 'after'=>'api_headers'), function()
{
    // ...
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 2017-01-27
    • 2015-08-30
    • 2012-11-19
    相关资源
    最近更新 更多