Accessing Laravel session from Ratchet

Laravel plus Ratchet

Ratchet is an awesome PHP-based websocket server framework. A good choice when you want to add real-time websocket-based features to your PHP-based web application without adding any additional technology. I personally use it on my (personal) MVP Laravel-based web application to keep it as monolithic as possible 😝

Since Ratchet has been around for awhile, there are some good tutorials about it. If you just want to have a simple standalone websocket server, the example in its README is enough. To “loosely” integrate Ratchet with Laravel by creating an php artisan command to start the websocket server which can access most Laravel features, this and this articles help a lot. But in my case, I want to access Laravel session despite of driver being used.

After digging answers in StackOverflow, exploring issues in Github and conducting trials and errors. I use code below to access Laravel session (and get authenticated user) in Ratchet (version 0.4.1). I also use Guzzle to handle the PSR-7 request.

namespace App\Http\Controllers;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Illuminate\Session\SessionManager;

class WebSocketController extends Controller implements MessageComponentInterface
{
    protected $clients;

    public function __construct() {
        $this->clients = [];
    }

    private function auth_user($conn)
    {
        $conn->session->start();
        $user_id = $conn->session->get(\Auth::getName());
        return !empty($user_id) ? \App\User::find($user_id) : null;
    }

    public function onOpen(ConnectionInterface $conn)
    {
        // Create a new session handler for this client
        $session = (new SessionManager(\App::getInstance()))->driver();
        // Get the cookies
        $cookies_header = $conn->httpRequest->getHeader('Cookie');
        $cookies = \GuzzleHttp\Psr7\parse_header($cookies_header)[0];
        // Get the laravel's one
        $cookie = urldecode($cookies[\Config::get('session.cookie')]);
        // get the user session id from it
        $session_id = \Crypt::decryptString($cookie);
        // Set the session id to the session handler
        $session->setId($session_id);
        // Bind the session handler to the client connection
        $conn->session = $session;  

        // Get Auth user
        $user = $this->auth_user($conn);
        // echo "{$user->email} connected\n";

        // Store one connection per user
        $this->clients[$user->id] = $conn;
    }

// more code ..

}

Alternatively, you can also use Laravel memcache or database session store driver instead of the file driver (default) so you can utilize Ratchet’s SessionProvider. I haven’t try it myself but it seems quite convenient

Leave a Reply

Your email address will not be published. Required fields are marked *