Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symfony: Default SESSION does not work (no cookie is set in Response) #18

Closed
Richard87 opened this issue Jun 22, 2018 · 108 comments
Closed
Labels
A-docs Area: documentation help-heeded-medium Call for participation: Experience needed to fix: Medium / intermediate

Comments

@Richard87
Copy link

Hi!

I have this code:

<?php
/**
 * Created by PhpStorm.
 * User: richard
 * Date: 22.06.18
 * Time: 11:59
 */

require __DIR__ . '/vendor/autoload.php';

use App\Kernel;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\Request;

if (getenv('APP_ENV') === false) {
    (new Dotenv())->load(__DIR__.'/.env');
}
$env = getenv('APP_ENV') ?: 'dev';
$debug = getenv('APP_DEBUG') ? ((bool) getenv('APP_DEBUG')) : !in_array($env, ['prod', 'k8s']);

if ($debug) {
    umask(0000);
    Debug::enable();
}
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
    Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
    Request::setTrustedHosts(explode(',', $trustedHosts));
}
$kernel = new Kernel($env, $debug);
$httpFoundationFactory = new HttpFoundationFactory();




$relay = new Spiral\Goridge\StreamRelay(STDIN, STDOUT);
$psr7 = new Spiral\RoadRunner\PSR7Client(new Spiral\RoadRunner\Worker($relay));


while ($req = $psr7->acceptRequest()) {
    try {
        $request = $httpFoundationFactory->createRequest($req);
        $response = $kernel->handle($request);

        $psr7factory = new DiactorosFactory();
        $psr7response = $psr7factory->createResponse($response);
        $psr7->respond($psr7response);

        $kernel->terminate($request, $response);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    }
}

It's slighly modified Symfony code to handle env-variables :)
(Also, it's stunningly fast!!!!)

But I don't get any cookies returned, so I can see my logg inn is accepted, and I'm redirected to the dashboard, but there I get a permission denied and redirect to login (because no cookies have been set)...

Any tips on how to troubleshoot, or what might be wrong?

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Check if you actually have cookies in PSR7 request, dump $r->getCookieParams() somewhere (do not dump them into STDOUT since it used for communication).

If you don't have cookies: make sure your cookies are not set on the different domain
If you do have cookies in PSR7: most likely PSR-Symfony wrapper is incorrect.

We know for sure that cookies work (we have multiple application use them + there are a bunch of tests https://github.com/spiral/roadrunner/blob/master/service/http/handler_test.go#L113).

If you still have no idea what is going on try to download rr repository and run make test.

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Also check if your cookies are being returned in response (Chome Developer Console will help).

@Richard87
Copy link
Author

Strange... I Rebooted the computer because I couldn't get RoadRunner to start again, and it works perfect... Maybe it have some issues shutting down cleanly?

And wow, this is insanely fast!!! I just hope I don't get any memory issues since StreamedResponses haven't been impleneted yet...

Anyway, this is my latest version of the worker script:

<?php
/**
 * Created by PhpStorm.
 * User: richard
 * Date: 22.06.18
 * Time: 11:59
 */

require __DIR__ . '/vendor/autoload.php';

use App\Kernel;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
use Symfony\Component\Debug\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\Request;

if (getenv('APP_ENV') === false) {
    (new Dotenv())->load(__DIR__.'/.env');
}
$env = getenv('APP_ENV') ?: 'dev';
$debug = getenv('APP_DEBUG') ? ((bool) getenv('APP_DEBUG')) : !in_array($env, ['prod', 'k8s']);

if ($debug) {
    umask(0000);
    Debug::enable();
}
if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
    Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
    Request::setTrustedHosts(explode(',', $trustedHosts));
}

$relay = new Spiral\Goridge\SocketRelay(__DIR__ . "/var/roadrunner.sock",null,\Spiral\Goridge\SocketRelay::SOCK_UNIX);
$worker = new Spiral\RoadRunner\Worker($relay);
$psr7 = new Spiral\RoadRunner\PSR7Client($worker);


$kernel = new Kernel($env, $debug);
$httpFoundationFactory = new HttpFoundationFactory();
$cacheDir = $kernel->getCacheDir();
while ($req = $psr7->acceptRequest()) {
    try {
        $request = $httpFoundationFactory->createRequest($req);
        $response = $kernel->handle($request);

        $psr7factory = new DiactorosFactory();
        $psr7response = $psr7factory->createResponse($response);
        $psr7->respond($psr7response);

        $kernel->terminate($request, $response);
        $kernel->reboot($cacheDir);
    } catch (\Throwable $e) {
        $worker->error((string)$e);
    }
}

@Richard87
Copy link
Author

(Also I changed to sockets because I don't want any errors if something is printed to STDOUT by accident ;) )

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Maybe it have some issues shutting down cleanly?

Can you please post your .rr file and name of your OS?

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

And wow, this is insanely fast!!! I just hope I don't get any memory issues since StreamedResponses haven't been impleneted yet...

Output buffer will be cleared on every response, so you only risking using more memory during one request (no leaks is expected). Streaming responses are something we are closing looking to implement in next update.

@Richard87
Copy link
Author

Well this is embarasing :( after restart, I ran docker-compose up to get mysql and redis back online ,also starteed php (I didn't notice), and everytime I ran roadrunner I thought I was using that, but actually I was working via docker...

So, Cookies are still not sent... (but atleast ./rr http:workers is workign again!)

@Richard87 Richard87 reopened this Jun 22, 2018
@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Have you tried to debug using instructions attached earlier?

@Richard87
Copy link
Author

yup, just finished, seems like Symfony is not setting the cookies at all suddenly... (the same code works perfectly in Docker with Apache+mod-php and Apache + Php-fpm in production...

First it hits login_check, which is successful (if I check profiler, and by looking at the Location in the return header, next it hits /dashboard, but it fails, because it doesn't have any cookies :(

Check this out:

{
    "url": "\/login_check",
    "sf_response_headers": {
        "cache-control": [
            "max-age=0, must-revalidate, private"
        ],
        "date": [
            "Fri, 22 Jun 2018 13:26:47 GMT"
        ],
        "location": [
            "\/dashboard\/"
        ],
        "content-type": [
            "text\/html; charset=UTF-8"
        ]
    }
}
{
    "url": "\/dashboard\/",
    "sf_response_headers": {
        "cache-control": [
            "max-age=0, must-revalidate, private"
        ],
        "date": [
            "Fri, 22 Jun 2018 13:26:47 GMT"
        ],
        "location": [
            "\/"
        ],
        "content-type": [
            "text\/html; charset=UTF-8"
        ]
    }
}
{
    "url": "\/",
    "sf_response_headers": {
        "cache-control": [
            "max-age=0, must-revalidate, private"
        ],
        "date": [
            "Fri, 22 Jun 2018 13:26:47 GMT"
        ],
        "content-type": [
            "text\/html; charset=UTF-8"
        ]
    }
}

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Hmmmmm. Try to set host in request uri to the localhost (or host you use), it might be empty in PSR7 but Symfony might be requiring it.

$req = $req->withUri($req->getUri()->withHost('localhost'));

@Richard87
Copy link
Author

Okay, after a lot of stupidity, Symfony is setting the cookie in the symfony response:

{
    "url": "\/login_check",
    "headers": [
        "sf_redirect:{\"token\":\"b20886\",\"route\":\"login_check\",\"method\":\"POST\",\"controller\":\"n\\\/a\",\"status_code\":302,\"status_text\":\"Found\"}",
        "Hello:World!"
    ]
}

The PSR7 Response headers:

{
    "url": "\/login_check",
    "headers": {
        "cache-control": [
            "max-age=0, must-revalidate, private"
        ],
        "date": [
            "Fri, 22 Jun 2018 13:49:34 GMT"
        ],
        "location": [
            "\/dashboard\/"
        ],
        "content-type": [
            "text\/html; charset=UTF-8"
        ],
        "x-debug-token": [
            "dd6430"
        ],
        "x-debug-token-link": [
            "http:\/\/localhost:8000\/_profiler\/dd6430"
        ],
        "set-cookie": [
            "sf_redirect=%7B%22token%22%3A%22dd6430%22%2C%22route%22%3A%22login_check%22%2C%22method%22%3A%22POST%22%2C%22controller%22%3A%22n%5C%2Fa%22%2C%22status_code%22%3A302%2C%22status_text%22%3A%22Found%22%7D; path=\/; httponly"
        ],
        "Set-Cookie": [
            "sf_redirect=%7B%22token%22%3A%22dd6430%22%2C%22route%22%3A%22login_check%22%2C%22method%22%3A%22POST%22%2C%22controller%22%3A%22n%5C%2Fa%22%2C%22status_code%22%3A302%2C%22status_text%22%3A%22Found%22%7D; path=\/; httponly"
        ]
    }
}

But somehow the auth-cookie/session id is not set...
Google Chrome also see the cookie: sf_redirect=%7B%22token%22%3A%22ed1ed6%22%2C%22route%22%3A%22login_check%22%2C%22method%22%3A%22POST%22%2C%22controller%22%3A%22n%5C%2Fa%22%2C%22status_code%22%3A302%2C%22status_text%22%3A%22Found%22%7D; path=/; httponly

@Richard87
Copy link
Author

Adding the Uri didn't work:

$kernel = new \App\Kernel("dev", true);
$httpFoundationFactory = new HttpFoundationFactory();
$cacheDir = $kernel->getCacheDir();
while ($req = $psr7->acceptRequest()) {
    try {
        $req = $req->withUri($req->getUri()->withHost('localhost'));
        $request = $httpFoundationFactory->createRequest($req);
        $response = $kernel->handle($request);
        
        $psr7factory = new DiactorosFactory();
        $psr7response = $psr7factory->createResponse($response);

        $cookies = $psr7response->getHeaders();
        file_put_contents(__DIR__ . "/headers.json",json_encode([
                'url' => $request->getPathInfo(),
                'headers' => $cookies,
            ],JSON_PRETTY_PRINT)."\n", FILE_APPEND);
        
        $psr7->respond($psr7response);

        $kernel->terminate($request, $response);
        $kernel->reboot($cacheDir);
    } catch (\Throwable $e) {
        $worker->error((string)$e);
    }
}

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

So one cookie is set and another don't? Do you see cookie headers in chrome debug panel on a response from your login?

@Richard87
Copy link
Author

Yup

It's insanely weird... The "Debug toolbar" cookies, and the custom cookies I set to test is stored and sent, BUT not auth cookies...

@Richard87
Copy link
Author

It seems the session storage doesn't work...

@Richard87
Copy link
Author

I'm using redis backend for session storage.. .does that have any implications with Roadrunner?

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Not at all, only http layer is different.

@Richard87
Copy link
Author

Strange, session does seems to work-ish, but it's weird:

{"id":"7noncegfojm7slhu31pucoko0b","test":"2018-06-22T14:38:05+00:00","name":"eportal_auth"}
{"id":"pno6dppgmk36sb673rprt9b6ig","test":"2018-06-22T14:38:06+00:00","name":"eportal_auth"}
{"id":"78clifqv3ov8ve5t9pvvrc1jlu","test":"2018-06-22T14:38:06+00:00","name":"eportal_auth"}
{"id":"1obeqdstigeqbhagoui8rjid76","test":"2018-06-22T14:38:07+00:00","name":"eportal_auth"}
{"id":"7noncegfojm7slhu31pucoko0b","test":"2018-06-22T14:38:05+00:00","name":"eportal_auth"}
{"id":"pno6dppgmk36sb673rprt9b6ig","test":"2018-06-22T14:38:06+00:00","name":"eportal_auth"}
{"id":"78clifqv3ov8ve5t9pvvrc1jlu","test":"2018-06-22T14:38:06+00:00","name":"eportal_auth"}
{"id":"1obeqdstigeqbhagoui8rjid76","test":"2018-06-22T14:38:07+00:00","name":"eportal_auth"}
{"id":"7noncegfojm7slhu31pucoko0b","test":"2018-06-22T14:38:05+00:00","name":"eportal_auth"}
{"id":"pno6dppgmk36sb673rprt9b6ig","test":"2018-06-22T14:38:06+00:00","name":"eportal_auth"}

I saved a item in session:

  $session = $kernel->getContainer()->get("session");
        if (!$session->has("test"))
            $session->set("test", date("c"));

        file_put_contents(__DIR__ . "/headers.json",json_encode([
                'id' => $session->getId(),
                'test' => $session->get("test"),
                'name' => $session->getName(),
            ])."\n", FILE_APPEND);

The ID is changing constantly, and therefor reading slighly different times, anyhow, the session id never reaches the browser :/

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

I think it's related to cookies not being emitted by Symfony, is there any sort of Symfony option to disable them? Maybe it requires any specific setting?

@Richard87
Copy link
Author

I don't think so, it works perfectly everywhere else...

{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:54:50+00:00","uri":"\/login_check"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:54:50+00:00","uri":"\/dashboard\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:54:51+00:00","uri":"\/"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:54:51+00:00","uri":"\/_wdt\/949254"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:54:55+00:00","uri":"\/login_check"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:54:55+00:00","uri":"\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:54:56+00:00","uri":"\/_wdt\/3b2bf4"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:54:58+00:00","uri":"\/"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:54:58+00:00","uri":"\/_wdt\/018964"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:57:38+00:00","uri":"\/login_check"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:57:38+00:00","uri":"\/"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:57:38+00:00","uri":"\/_wdt\/796c97"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:57:48+00:00","uri":"\/login_check"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:57:48+00:00","uri":"\/dashboard\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:57:48+00:00","uri":"\/"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:57:48+00:00","uri":"\/_wdt\/05835e"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:58:04+00:00","uri":"\/login_check"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:58:04+00:00","uri":"\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:58:04+00:00","uri":"\/_wdt\/c418cb"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:59:14+00:00","uri":"\/"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:59:14+00:00","uri":"\/_wdt\/6e9522"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T14:59:32+00:00","uri":"\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T14:59:33+00:00","uri":"\/_wdt\/31da3a"}
{"id":"idemsd1mihrpf13e5j4gi7eq14","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T15:00:22+00:00","uri":"\/"}
{"id":"movsub0sitiab507i9plg936ju","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T15:00:23+00:00","uri":"\/_wdt\/d4bc9e"}
{"id":"8mrbbtunenbrodp752iipfgrra","test":"2018-06-22T14:54:50+00:00","now":"2018-06-22T15:00:35+00:00","uri":"\/"}
{"id":"qoalctg5bvae67jvq5n8f53rgj","test":"2018-06-22T14:54:51+00:00","now":"2018-06-22T15:00:35+00:00","uri":"\/_wdt\/84c22d"}

The strange this is it seems the ID's are recycled, and the session storage works. It feels like something the load balancer is doing? Is there some logic looking at cookies in there?

(Test is the time php first saw that session_id)

@Richard87
Copy link
Author

In our production env / live, I deleted all cookies, and went to the dashboard

Symfony immidiatly creates a new Cookie, and uses the "Set-cookie" header, on all sequent request, Chrome uses that cookie, and symfony never sends a Set-cookie again, not even when logging in (even with auth denied, it keeps the same cookie id).

So, when I run up docker-compose, everything works immidiatly, if I stop docker-php, and run the symfony built in dev-server, it reacts exactly the same way as the production env.

I can also see all cookies in Chrome dev-tools etc (1. set cookie on the first request, and then using that cookie on all subsequent requests).

When using roadrunner, the browser never sees the cookie, even though somehow the same id's are recycled?

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Can you try to dump the $response->getHeaders() somewhere? Are they being set in response?

@Richard87
Copy link
Author

Yeah, I don't have any clues what's happening...

It doesn't seem like symfony returns any headers, but everytime roadrunner crashes (without any description to why), I have to reboot the machine to be able to get it up and running again, so troubleshooting is pretty slow...

Also, is there any way of enabling xdebug in the workers?

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

It doesn't seem like symfony returns any headers, but everytime roadrunner crashes (without any description to why), I have to reboot the machine to be able to get it up and running again, so troubleshooting is pretty slow...

What OS are you using?

Also, is there any way of enabling xdebug in the workers?

Yes, i will write an instruction next week how to configure it properly.

@Richard87
Copy link
Author

I'm on Linux (Fedora 28)

@wolfy-j
Copy link
Contributor

wolfy-j commented Jun 22, 2018

Is it possible that error within this lines?

if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
    Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}
if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
    Request::setTrustedHosts(explode(',', $trustedHosts));
}

Do you have any sort of IP filtering which might affect session creation or anything like that? Do you set this values using ENV? RR runs using php-cli mode and it might not nesessary provide same values as nginx.

@Alex-Bond
Copy link
Contributor

@grachevko how do you check if there data in session? Because i can send cookie all the time if it not present, but the idea in native sessions is that php-fpm adds cookies only if you have data in the session. If session empty it will not add anything.

@grachevko
Copy link

@Alex-Bond i don't check data in session. I see on session id, then send cookie if client session_id != server session_id.

@Alex-Bond
Copy link
Contributor

@grachevko technically its the same that i described earlier. The only better solution is to figure out how to check if there any data in session before sending cookies.

@grachevko
Copy link

@Alex-Bond session creates and generate id only on write data. If ids is different that session was writed. What edge case you want to fix?

@Alex-Bond
Copy link
Contributor

Alex-Bond commented Feb 6, 2019

@Alex-Bond session creates and generate id only on write data. If ids is different that session was writed. What edge case you want to fix?

Your method required to inject listener to SF? I tried that way without injecting and after few requests system stops returning me session data.

Russian:
Проблема в том что я не хочу слать кукисов котогда сессия пустая. $this->_symfonyRequest->getSession()->all() возаращает иногда пустоту даже если данные в сессии есть. Я не знаю почему, но мне не удается добится вменяемой проверки на содержание сесиии.

@grachevko
Copy link

@Alex-Bond yes my listener is a part of sf and not related to rr directrly.

Russian:
Если сессии не было и во время запроса не произошло записи в неё, то и ID сессии не генерируется. В этом случае мой листенер не ставит куку.
Сессия может стартануть если кто-то попытается из неё читать без проверки что сессия isStarted(), такого поведения нужно избегать, если не хочешь ставить куку когда на стороне сервера в сессии пусто.

@Alex-Bond
Copy link
Contributor

@Alex-Bond yes my listener is a part of sf and not related to rr directrly.

Russian:
Если сессии не было и во время запроса не произошло записи в неё, то и ID сессии не генерируется. В этом случае мой листенер не ставит куку.
Сессия может стартануть если кто-то попытается из неё читать без проверки что сессия isStarted(), такого поведения нужно избегать, если не хочешь ставить куку когда на стороне сервера в сессии пусто.

У меня всегда генерится айди :( И самое крутое что в какой-то момент перестает отдавать данные из сессии вообще

@speller
Copy link

speller commented Feb 16, 2019

This is my version of the Symfony worker which handles sessions almost correctly:

<?php
use Kernel\AppKernel;
use Spiral\Goridge\StreamRelay;
use Spiral\RoadRunner\PSR7Client;
use Spiral\RoadRunner\Worker;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
use Symfony\Component\Debug\Debug;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;

require '../vendor/autoload.php';

require_once __DIR__ . '/load-env.php';

if ($debug) {
    umask(0000);

    Debug::enable();
}

if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) {
    Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
}

if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) {
    Request::setTrustedHosts(explode(',', $trustedHosts));
}

$kernel = new AppKernel($env, $debug);
$relay = new StreamRelay(STDIN, STDOUT);
$psr7 = new PSR7Client(new Worker($relay));
$httpFoundationFactory = new HttpFoundationFactory();
$diactorosFactory = new DiactorosFactory();

while ($req = $psr7->acceptRequest()) {
    try {
        $request = $httpFoundationFactory->createRequest($req);
        // Get the actual session ID from request.
        $sessionId = (string)$request->cookies->get(session_name());
        unset($_SESSION);
        // Set new session id for PHP or forget previous request session id.
        session_id($sessionId);
        $response = $kernel->handle($request);
        if (session_id() !== $sessionId) {
            // Set session cookie if session id was changed
            $response->headers->setCookie(
                Cookie::create(
                    session_name(),
                    session_id()
                )
            );
        }
        $psr7->respond($diactorosFactory->createResponse($response));
        $kernel->terminate($request, $response);
        $kernel->reboot(null);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    }
}

The only problem here is that the cookie output don't use cookie parameters like domain, path etc.

@honarkhah
Copy link

honarkhah commented Oct 30, 2019

Still this issue is there, also after php7.2 we are not allowed to change session_id like session_id($sessionId);
Anyone had same issue with laravel or other framework?
Is there any update?

@wolfy-j
Copy link
Contributor

wolfy-j commented Oct 30, 2019

Not sure if it will help, but this is the way how we work with sessions under roadrunner: https://github.com/spiral/session/blob/master/src/Session.php

It works with native sessions and operates on production for a couple of years so far (the handler is not file-based though).

@Baldinof
Copy link
Contributor

Hi, I wrote a symfony bundle that works with sessions: https://github.com/baldinof/roadrunner-bundle

It also has a Flex recipe for easy installation.

Hope it can help!

@Radiergummi
Copy link

...to chime in, I wrapped the magnificent bundle by @Baldinof in a Docker image: https://github.com/Radiergummi/roadrunner-symfony-skeleton

May be helpful too :)

@rustatian rustatian added help-heeded-medium Call for participation: Experience needed to fix: Medium / intermediate F-insufficent details Need more details W - waiting on author and removed help wanted F-need-verification labels Feb 15, 2020
@rustatian rustatian added this to the unplanned milestone Feb 15, 2020
@rustatian rustatian removed the F-insufficent details Need more details label Feb 15, 2020
@wolfy-j
Copy link
Contributor

wolfy-j commented Feb 16, 2020

I would appreciate if someone can add this information to https://github.com/spiral/roadrunner-docs/blob/master/integration/symfony.md

I hope we can finally close this ticket!

@rustatian rustatian added the A-docs Area: documentation label Feb 16, 2020
@Baldinof
Copy link
Contributor

Baldinof commented Feb 16, 2020

👍 I will write the PR.

@wolfy-j
Copy link
Contributor

wolfy-j commented Feb 24, 2020

And the story is over. Let me know if this ticket should be reopened!

@wolfy-j wolfy-j closed this as completed Feb 24, 2020
@wolfy-j
Copy link
Contributor

wolfy-j commented Feb 24, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-docs Area: documentation help-heeded-medium Call for participation: Experience needed to fix: Medium / intermediate
Projects
No open projects
Archived in project
Development

No branches or pull requests