从代码中调用Laravel控制器,并将HTTP标头传递给它 [英] Call Laravel controller from code and pass HTTP headers to it
问题描述
要调用控制器,我使用如下CURL请求:
To call a controller I use a CURL request like this:
curl -kX POST https://site/method -H 'Authorization: Bearer ACCESS_TOKEN\
Content-Type:application/json' -d '
{
"param1":"value 1",
"param2":"value 2",
"param3":"value 3"
}'
该路由调用UserController @ method.
The route calls UserController@method.
如何从Laravel代码(内部请求,不发送CURL)中做同样的事情?
How can I do the same from Laravel code (internal request, not sending CURL)?
我找到了使用这样的东西的建议
I've found an advice to use something like this
$controller = app()->make($controllerName);
$response = app()->call([$controller, 'method'], []);
echo $response;
最后一个[]应该包含一些参数.但是如果这样,我将无法弄清数组在我的情况下的外观.
where the last [] should contain some parameters. But if this is the way, I cannot figure out how the array should look in my case.
P.S.请不要回答这是一种不好的做法",而不是给出如何实现我所需要的建议.
P.S. Please, don't answer "it's a bad practice" instead of giving an advice how to implement what I need.
推荐答案
这是我的解决方案(Laravel 5.4).受 https://stackoverflow.com/a/40366119/518704 的启发,但需要大量时间来深入研究代码才能找到如何通过我的 Authorization:Bearer 令牌
Here is my solution (Laravel 5.4). Inspired by https://stackoverflow.com/a/40366119/518704 but needed much time to dig into the code to find how to pass my Authorization: Bearer token
我需要这种方法来在没有运行JS代码的无浏览器套接字连接(Ratchet)中进行授权.因此,我不能使用Ratchet WebSocket,只能使用简单的套接字Ratchet IoServer .我的API控制器返回JSON,因此可以轻松地进一步处理响应.我主要需要这种方法来验证套接字连接,假设客户端在打开套接字时就知道访问令牌(登录时由REST获取).
I need this approach to authorize in a browser-less socket connection (Ratchet), where JS code is not running. So I could not use Ratchet WebSocket, only simple socket Ratchet IoServer. My API controller returns JSON so it's easy to work with the response further. I need this approach mainly to authenticate the socket connection assuming the client knows the access token when one opens the socket (got by REST on login).
首先,我需要使用测试中使用的特征
First of all I need to use a trait, used in Tests
下一步,在 onMessage 代码中,我假设使用访问令牌传递了JSON消息.为了简化这里,我不编写JSON有效性检查等.
Next in onMessage code I assume a JSON message is passed with the access token. To simplify here I don't write JSON validity check etc.
namespace App;
use Ratchet\ConnectionInterface;
use Askedio\LaravelRatchet\RatchetServer as RatchetServerBase;
class RatchetServer extends RatchetServerBase
{
...
public function onMessage(ConnectionInterface $conn, $input)
{
$input = json_decode($input);
$token = $input->token;
// Some data (may be taken from JSON $input)
$data = [
"param1" => "value 1",
"param2" => "value 2",
"param3" => "value 3"
];
// Prepare the server headers
$server = ['HTTP_AUTHORIZATION' => 'Bearer ' . $token];
// This way! If calling app() here, it reuses the same Auth::user()
$app = require __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(\Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = \Illuminate\Http\Request::create('/user', 'GET', $data, [], [], $server)
);
// ~ var_dump(Auth::id());
$controllerResult = $response->getContent();
$kernel->terminate($request, $response);
// My controller hidden under /user route is an API one and returns JSON string
echo $controllerResult;
}
...
}
我以前的解决方案不起作用. Auth :: user()始终返回 首次登录的用户(app()似乎使用单例).所以我离开了 先前的代码仅供参考.
My previous solution didn't work. The Auth::user() always returned the first logged in user (app() seemed to use singleton). So I leave the previous code for reference purpose.
namespace App;
use Ratchet\ConnectionInterface;
use Askedio\LaravelRatchet\RatchetServer as RatchetServerBase;
class RatchetServer extends RatchetServerBase
{
use \Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
...
public function onMessage(ConnectionInterface $conn, $input)
{
$input = json_decode($input);
$token = $input->token;
$data = [
"param1" => "value 1",
"param2" => "value 2",
"param3" => "value 3"
];
// The 2 lines below can me moved to the __constructor method
$this->baseUrl = request()->getSchemeAndHttpHost();
$this->app = app();
// Prepare the server headers
$server = ['HTTP_AUTHORIZATION' => 'Bearer ' . $token];
// Call my controller by route (this seems to be internal call)
$response = $this->call('GET','/method', $data, [], [], $server)->json();
}
...
}
P.S.稍后我来这里时,只为给我自己一个便条.看不到可用的标头和正确的命名,我在$this->parameters
./vendor/symfony/http-foundation//ServerBag.php
P.S. Just a note for myself when I come here later. Too see available headers and proper naming I did a var_dump in for $this->parameters
./vendor/symfony/http-foundation//ServerBag.php
这篇关于从代码中调用Laravel控制器,并将HTTP标头传递给它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!