-
-
Save Mevrael/6855dd47d45fa34ee7161c8e0d2d0e88 to your computer and use it in GitHub Desktop.
| <?php | |
| // add this to web routes | |
| Route::get('/websocket/open', 'WebSocketController@onOpen'); | |
| Route::get('/websocket/message', 'WebSocketController@onMessage'); | |
| Route::get('/websocket/close', 'WebSocketController@onClose'); | |
| Route::get('/websocket/error', 'WebSocketController@onError'); |
| <?php | |
| namespace App\Http\Controllers; | |
| use Illuminate\Http\Request; | |
| use Illuminate\Support\Facades\Auth; | |
| use Illuminate\Support\Facades\Cookie; | |
| use Illuminate\Support\Facades\Mail; | |
| use Illuminate\Support\Facades\Session; | |
| use Ratchet\WebSocket\Version\RFC6455\Connection; | |
| class WebSocketController | |
| { | |
| /** | |
| * @var Connection | |
| */ | |
| protected $connection = null; | |
| /** | |
| * @var array|mixed | |
| */ | |
| protected $data = []; | |
| /** | |
| * @var Connection | |
| */ | |
| protected $currentClient = null; | |
| /** | |
| * @var Connection[] | |
| */ | |
| protected $otherClients = []; | |
| public function __construct(Request $request) | |
| { | |
| $this->connection = $request->get('connection'); | |
| $this->data = $request->get('data'); | |
| $this->currentClient = $request->get('current_client'); | |
| $this->otherClients = $request->get('other_clients'); | |
| } | |
| public function sendToOthers(array $data) { | |
| foreach ($this->otherClients as $client) { | |
| $client->send(json_encode($data)); | |
| } | |
| } | |
| public function onOpen(Request $request) | |
| { | |
| if (!Auth::check()) { | |
| $this->currentClient->close(); | |
| return; | |
| } | |
| echo 'Opened' . PHP_EOL; | |
| echo $request->ip() . PHP_EOL; | |
| $this->sendToOthers([ | |
| 'type' => 'USER_CONNECTED', | |
| ]); | |
| } | |
| public function onMessage(Request $request) | |
| { | |
| if (!Auth::check()) { | |
| $this->currentClient->close(); | |
| return; | |
| } | |
| echo 'New message' . PHP_EOL; | |
| echo $request->ip() . PHP_EOL; | |
| $this->sendToOthers([ | |
| 'type' => 'MESSAGE_RECEIVED', | |
| 'data' => [ | |
| 'user' => Auth::user()->name, | |
| 'message' => $this->data->message, | |
| ] | |
| ]); | |
| } | |
| public function onClose(Request $request) | |
| { | |
| echo 'Closed' . PHP_EOL; | |
| echo $request->ip() . PHP_EOL; | |
| $this->sendToOthers([ | |
| 'type' => 'USER_DISCONNECTED', | |
| ]); | |
| } | |
| public function onError(Request $request) | |
| { | |
| echo 'Error' . PHP_EOL; | |
| } | |
| } |
| <?php | |
| // in Laravel project root create also wsserver.php | |
| // use 'php wsserver' to launch Web Socket server | |
| // Make sure composer dependencies have been installed | |
| require __DIR__ . '/vendor/autoload.php'; | |
| use App\User; | |
| use Illuminate\Support\Facades\Auth; | |
| use Illuminate\Support\Facades\Session; | |
| use Ratchet\MessageComponentInterface; | |
| use Ratchet\ConnectionInterface; | |
| /** | |
| * chat.php | |
| * Send any incoming messages to all connected clients (except sender) | |
| */ | |
| class WebSocketLaravelServer implements MessageComponentInterface | |
| { | |
| protected $clients; | |
| public function __construct() { | |
| echo 'Creating app...' . PHP_EOL; | |
| $this->clients = new \SplObjectStorage; | |
| } | |
| protected function handleLaravelRequest(ConnectionInterface $con, $route, $data = null) | |
| { | |
| /** | |
| * @var \Ratchet\WebSocket\Version\RFC6455\Connection $con | |
| * @var \Guzzle\Http\Message\Request $wsrequest | |
| * @var \Illuminate\Http\Response $response | |
| */ | |
| $params = [ | |
| 'connection' => $con, | |
| 'other_clients' => [], | |
| ]; | |
| if ($data !== null) { | |
| if (is_string($data)) { | |
| $params = ['data' => json_decode($data)]; | |
| } else { | |
| $params = ['data' => $data]; | |
| } | |
| } | |
| foreach ($this->clients as $client) { | |
| if ($con != $client) { | |
| $params['other_clients'][] = $client; | |
| } else { | |
| $params['current_client'] = $client; | |
| } | |
| } | |
| $wsrequest = $con->WebSocket->request; | |
| $app = require __DIR__.'/bootstrap/app.php'; | |
| $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); | |
| $response = $kernel->handle( | |
| $request = Illuminate\Http\Request::create($route, 'GET', $params, $wsrequest->getCookies()) | |
| ); | |
| //var_dump(Auth::id()); | |
| $controllerResult = $response->getContent(); | |
| $kernel->terminate($request, $response); | |
| return json_encode($controllerResult); | |
| } | |
| public function onOpen(ConnectionInterface $con) | |
| { | |
| $this->clients->attach($con); | |
| $this->handleLaravelRequest($con, '/websocket/open'); | |
| } | |
| public function onMessage(ConnectionInterface $con, $msg) | |
| { | |
| $this->handleLaravelRequest($con, '/websocket/message', $msg); | |
| } | |
| public function onClose(ConnectionInterface $con) | |
| { | |
| $this->handleLaravelRequest($con, '/websocket/close'); | |
| $this->clients->detach($con); | |
| } | |
| public function onError(ConnectionInterface $con, \Exception $e) | |
| { | |
| $this->handleLaravelRequest($con, '/websocket/error'); | |
| echo 'Error: ' . $e->getMessage() . PHP_EOL; | |
| $con->close(); | |
| } | |
| } | |
| // Run the server application through the WebSocket protocol on port 8080 | |
| $app = new Ratchet\App('localhost', 8080); | |
| $app->route('/echo', new WebSocketLaravelServer); | |
| $app->run(); |
as mentioned at http://socketo.me/docs/migration-3 Guzzle Http API changed, so, getting cookies could be smth like
$wsrequest = $con->httpRequest ;
$cookies = Cookies::fromRequest($wsrequest)->getAll();
$allCookies = array();
foreach ($cookies as $cookie){
$allCookies[$cookie->getName()] = $cookie->getValue();
}
$request = \Illuminate\Http\Request::create($route, 'GET', $params, $allCookies);
This kind of code didn't work for me immediately. BUT!
There are few changes to make it working with Bearer token.
Change handleLaravelRequest() method to:
`$params = [
'connection' => $con,
'other_clients' => [],
];
if ($data !== null) {
if (is_string($data)) {
$params = ['data' => json_decode($data)];
} else {
$params = ['data' => $data];
}
}
foreach ($this->clients as $client) {
if ($con != $client) {
$params['other_clients'][] = $client;
} else {
$params['current_client'] = $client;
}
}
$wsrequest = $con->httpRequest;
$cookies = $wsrequest->getHeader("Cookie");
$cookies = \GuzzleHttp\Psr7\parse_header($cookies)[0];
$app = App::getInstance();
$kernel = $app->make(\Illuminate\Contracts\Http\Kernel::class);
$request = \Illuminate\Http\Request::create($route, 'GET', $params, $cookies);
$request->headers->set('Authorization', 'Bearer '.$cookies['X-Authorization'],);
$response = $kernel->handle(
$request
);
$response->getContent();
$controllerResult = $response->getContent();
// var_dump($controllerResult);
$kernel->terminate($request, $response);
return json_encode($controllerResult);`
X-Authorization Cookie on the client side must contain actual Bearer token given by Laravel during auth.
Without this line $request->headers->set('Authorization', 'Bearer '.$cookies['X-Authorization'],); it's unable to make working 'auth:api' middleware properly. If header "Authorization" isn't present, you'll continiously get "Unauthorized". You'll even have no ability to use Auth::user()->id inside controller, because you'll get "Unauthorized message" before.
I've used this code and added few changes, but whatever I do, code
$response = $kernel->handle( $request );
is causing memory leak.
I've used this code and added few changes, but whatever I do, code
$response = $kernel->handle( $request );is causing memory leak.
Yes, it causes memory leak.
Does anyone has solution?
I've used this code and added few changes, but whatever I do, code
$response = $kernel->handle( $request );
is causing memory leak.Yes, it causes memory leak.
Does anyone has solution?
Maybe this code will help you
<?php
use \League\OAuth2\Server\ResourceServer;
use \Laravel\Passport\TokenRepository;
use \Laravel\Passport\Guards\TokenGuard;
use \Laravel\Passport\ClientRepository;
use \Illuminate\Support\Facades\Auth;
use \Illuminate\Http\Request;
class UserGetter
{
public static function getUser($bearerToken)
{
$tokenguard = new TokenGuard(
\App::make(ResourceServer::class),
\Auth::createUserProvider('users'),
\App::make(TokenRepository::class),
\App::make(ClientRepository::class),
\App::make('encrypter')
);
$request = Request::create('/');
$request->headers->set('Authorization', $bearerToken);
return $tokenguard->user($request);
}
}
Also you have to use garbage collector like:
gc_collect_cycles();
after all because it still takes a lot of memory
Think that
wssocket.phpcan be migrated into a Artisan command instead of executed by itself?