Giter Site home page Giter Site logo

Comments (108)

dunglas avatar dunglas commented on May 4, 2024 7

Creating a HttpFoundation driver would anyway be a good idea, because the PSR-7 bridge adds an important overhead.

As Symfony, Laravel, Drupal and phpBB use HttpFoundation, it would be a good first step to support all these projects.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024 4

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);
    }
}

from roadrunner.

dunglas avatar dunglas commented on May 4, 2024 4

I don’t think that it’s currently implemented in Symfony. The interfaces and all the infrastructure exist, but we need an implementation.
Any help on this topic will be very welcome!

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024 3

Looks like this work correctrly, i keep testing

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

        $sessionId = '';
        if ($request->cookies->has(\session_name())) {
            $sessionId = $request->cookies->get(\session_name());
            \session_id($sessionId);
            $kernel->getContainer()->get('session')->setId($sessionId);
        }

        $response = $kernel->handle($request);

        if (
            $request->hasSession()
            && [] !== $request->getSession()->all()
            && !\in_array($request->getSession()->getId(), ['', $sessionId], true)
        ) {
            $cookie_options = $kernel->getContainer()->getParameter('session.storage.options');
            $response->headers->setCookie(
                new \Symfony\Component\HttpFoundation\Cookie(
                    \session_name(),
                    \session_id(),
                    $cookie_options['cookie_lifetime'] ?? 0,
                    $cookie_options['cookie_path'] ?? '/',
                    $cookie_options['cookie_domain'] ?? '',
                    ($cookie_options['cookie_secure'] ?? 'auto') === 'auto' ? $request->isSecure() : (bool) ($cookie_options['cookie_secure'] ?? 'auto'),
                    $cookie_options['cookie_httponly'] ?? true,
                    false,
                    $cookie_options['cookie_samesite'] ?? null
                )
            );
        }

        $psr7->respond($diactorosFactory->createResponse($response));
        $kernel->terminate($request, $response);
        $kernel->reboot($kernel->getCacheDir());
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string) $e);
    } finally {
        if (PHP_SESSION_ACTIVE === \session_status()) {
            \session_write_close();

            \session_id('');
            \session_unset();
            unset($_SESSION);
        }

        if ($request->hasSession()) {
            $request->getSession()->setId('');
        }
    }
}

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024 2

Maybe a Symfony Flex Recipe could install a RoadRunnerBundle whenever RoadRunner was installed ... what do you think @wolfy-j ?

I have no issues with that :) I'm fine creating a repository for that if anyone wants to participate. Thought I would like to avoid coupling to the specific framework in RoadRunner repository (that's why we go with PSR7).

BTW, it's not hard to implement custom session handling mechanism AND keep native php session management enabled (via _SESSION), the only required thing is proper cookie handler (I've attached a link to our implementation above).

If someone can handle the creation of proper bridge I can expose underlying worker without PSR7 so we can later connect Symfony HttpKernel directly to RR without PSR7 (+performance).

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024 2

Hi!

EDIT

Didn't see your comment @wslaghekke , works good :)

I tested it and it worked niceley!
Check out the Repo here: https://github.com/Richard87/roadrunner-test-session

<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;

class DefaultController
{
    /** @Route("/") */
    public function indexAction(SessionInterface $session){
        $x = $session->get("x",0);
        $session->set("x", ++$x);

        return new Response($x);
    }
}

I needed to modify psr-worker.php slighly, I think composer(?) was confused since roadrunner also includeded the symfony dependencies...:

require_once 'vendor/autoload.php';
include_once 'vendor/symfony/psr-http-message-bridge/Factory/DiactorosFactory.php';
include_once 'vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php';

But it works perfect :)

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024 2

I found who make duplication symfony/psr-http-message-bridge#58

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024 1

I think we identified one of the potential issues with locking down pipes, we will release this patch today.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024 1

Zend Diactoros does not manage sessions at all (only data-carrying), since Symfony control session internally it must read/write session cookie. I assume the issue can be with some security or "trusted proxy" mechanism which either does not allow to set or to get cookie value to/from PSR7.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024 1

@1ma https://github.com/spiral/roadrunner/wiki/Debugging

from roadrunner.

shyim avatar shyim commented on May 4, 2024 1

I had the same problem, i just simple changed the binary to php-cgi, switched to sockets and used headers_list() after the handle to get the cookie and added them to the psr7 response

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024 1

Please put it into separate ticket.

from roadrunner.

wslaghekke avatar wslaghekke commented on May 4, 2024 1

I've gotten sessions working by adding some code to worker.php as follows:

<?php
ini_set('display_errors', 'stderr');

use App\Kernel;
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\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\Request;

require 'vendor/autoload.php';

// The check is to ensure we don't use .env in production
if (!isset($_SERVER['APP_ENV']) && !isset($_ENV['APP_ENV'])) {
    if (!class_exists(Dotenv::class)) {
        throw new \RuntimeException(
            'APP_ENV environment variable is not defined. You need to define environment variables for configuration or add "symfony/dotenv" as a Composer dependency to load variables from a .env file.'
        );
    }
    (new Dotenv())->load(__DIR__.'/.env');
}

$env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? 'dev';
$debug = (bool) ($_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? ('prod' !== $env));

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 Kernel($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);
        if ($request->cookies->has(session_name())) {
            session_id($request->cookies->get(session_name()));
        }

        $response = $kernel->handle($request);

        $cookie_options = $kernel->getContainer()->getParameter('session.storage.options');
        $response->headers->setCookie(
            new \Symfony\Component\HttpFoundation\Cookie(
                session_name(),
                session_id(),
                $cookie_options['cookie_lifetime'] ?? 0,
                $cookie_options['cookie_path'] ?? '/',
                $cookie_options['cookie_domain'] ?? '',
                ($cookie_options['cookie_secure'] ?? 'auto') === 'auto' ? $request->isSecure(
                ) : (bool)($cookie_options['cookie_secure'] ?? 'auto'),
                $cookie_options['cookie_httponly'] ?? true,
                false,
                $cookie_options['cookie_samesite'] ?? null
            )
        );

        $psr7->respond($diactorosFactory->createResponse($response));
        $kernel->terminate($request, $response);
        $kernel->reboot(null);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    } finally {
        if(PHP_SESSION_ACTIVE === session_status()) {
            session_write_close();
        }
        session_id('');
        session_unset();
        unset($_SESSION);
    }
}

from roadrunner.

Alex-Bond avatar Alex-Bond commented on May 4, 2024 1

So, a little info about my research and final result:
The problem of Symfony sessions is in simple - SF relies on native sessions to create cookies for session id when you writing something to it. And from this point, i was thinking that i can check driver tyle (native session handler in SF) and if it uses native sessions check if there some data in session and create a cookie if there none.
I was wrong. There are 2 problems that i faced while trying to create deep checks in SF:

  1. Driver object is written in protected parameter of Session object, so i cant access if from outside and as result cant check type of it.
  2. SF ending and closing sessions earlier than RR receiving response object and i didn't manage to get any session data from SF after receiving Response object.

My final decision at this time is to send session cookie all the time even if there no session data exists. If i do that it seems like Symfony works fine with sessions.

If you have some suggestions on how to make it works better please create PR or issue to https://github.com/UPDG/roadrunner-symfony

Thank you!

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Maybe it have some issues shutting down cleanly?

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

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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!)

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Have you tried to debug using instructions attached earlier?

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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"
        ]
    }
}

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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'));

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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);
    }
}

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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...

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Not at all, only http layer is different.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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 :/

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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?

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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)

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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?

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

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?

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

I'm on Linux (Fedora 28)

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

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.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Hi!

No, I'm not sure what does actually do! (I have put file_put_contents in strategic places, sometimes it crashes the roadrunner, but I don't now why).

I'll remove them and see what happens :)

There are no ip-filters or anything, it should be simple and straight forward :(

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Try adding ini_set('display_errors', 'stderr'); to your script, this part is missing in README but we have in tests and at our production. This might explain why you can't see any errors.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

I tried with "xdebug_break()", but no erros are sent with display_errors on.

Id did modify Worker.php:

    /**
     * Respond to the server with result of task execution and execution context.
     *
     * Example:
     * $worker->respond((string)$response->getBody(), json_encode($response->getHeaders()));
     *
     * @param string|null $payload
     * @param string|null $header
     */
    public function send(string $payload = null, string $header = null)
    {
        if (is_null($header)) {
            $this->relay->send($header, Relay::PAYLOAD_CONTROL | Relay::PAYLOAD_NONE);
        } else {

            file_put_contents("/home/richard/Projects/eportal/headers.json", $header."\n",FILE_APPEND);
            $this->relay->send($header, Relay::PAYLOAD_CONTROL | Relay::PAYLOAD_RAW);
        }

        $this->relay->send($payload, Relay::PAYLOAD_RAW);
    }

But no cookies are set related to session id at all (only the cookie setting the sf_redirect is set) :(

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

I'm currently preparing an update which will allow your to see the content of STDERR in realtime in debug mode, this might help, see #21

This is def some integration issue with Symfony. Do you see any cookies in Original Symfony response?

$psr7response = $psr7factory->createResponse($response);

Maybe the psr7 mapper does not work correctly.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Use error_log with ini_set('display_errors', 'stderr'); for an easier debug.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Hi, no, currently I think there is something weird going on in symfony, it never sets any auth cookies when using road runner :/

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Hi!

Thanks, just trying 1.0.3 now, and there is some awesome error reporting ;)

But I still can't restart RoadRunner after a php error.

^[
^CDEBU[0641] [rpc]: stopped                               
ERRO[0641] worker.23968 signal: interrupt 
ERRO[0641] worker.5693 signal: interrupt 
ERRO[0641] worker.5704 signal: interrupt 
ERRO[0641] worker.5697 signal: interrupt 

^C
^Z
[1]  + 5682 suspended  ./rr serve -vvv -d

~/Projects/eportal on  feature/road-runner ➜ kill 5682

~/Projects/eportal on  feature/road-runner ➜ ./rr serve -vvv -d         
DEBU[0000] [rpc]: started                               
DEBU[0000] [http]: started                              
DEBU[0000] [static]: started                            
^Z
[2]  + 24405 suspended  ./rr serve -vvv -d

~/Projects/eportal on  feature/road-runner ➜ bg
[2]  - 24405 continued  ./rr serve -vvv -d

~/Projects/eportal on  feature/road-runner ➜ ./rr http:workers 
^C
^C
^Z
[3]  + 24492 suspended  ./rr http:workers

~/Projects/eportal on  feature/road-runner ➜ bg
[3]  - 24492 continued  ./rr http:workers

~/Projects/eportal on  feature/road-runner ➜ curl localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

~/Projects/eportal on  feature/road-runner ➜ curl 127.0.0.1:8000
curl: (7) Failed to connect to 127.0.0.1 port 8000: Connection refused

~/Projects/eportal on  feature/road-runner ➜ kill -9 24405
Error: unexpected EOF                                                                                                                                                                                              
[2]    24405 killed     ./rr serve -vvv -d
[3]  - 24492 exit 1     ./rr http:workers

~/Projects/eportal on  feature/road-runner ➜ ./rr serve -vvv -d &
[2] 24557
DEBU[0000] [rpc]: started                                                                                                                                                                                          
DEBU[0000] [http]: started                              
DEBU[0000] [static]: started                            

~/Projects/eportal on  feature/road-runner ➜ curl 127.0.0.1:8000 
curl: (7) Failed to connect to 127.0.0.1 port 8000: Connection refused

~/Projects/eportal on  feature/road-runner ➜ ./rr http:workers   
^Z
[3]  + 24597 suspended  ./rr http:workers

~/Projects/eportal on  feature/road-runner ➜ bg
[3]  - 24597 continued  ./rr http:workers

~/Projects/eportal on  feature/road-runner ➜ kill 24557
DEBU[0015] [rpc]: stopped                                                                                                                                                                                          
DEBU[0015] [http]: stopped                              

~/Projects/eportal on  feature/road-runner ➜ 

(I'm still trying to get Cookies to work, but it goes slightly slower when I have to reboot everytime... )

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

I set up a new repository to test https://github.com/Richard87/roadrunner-test

I have only installed symfony/security-bundle, symfony/psr-http-message-bridge and spiral/roadrunner to make test it out...

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

The problem is that the session_id is not stored in the symfony Response object, it's handled seperatly by PHP.

Therefor DiactorosFactory never includes the session id / set Cookie...
https://github.com/symfony/http-foundation/blob/master/Session/Storage/NativeSessionStorage.php#L142

session_start() sets the Set-cookie with the correct properties depending on the active handler that implements \SessionHandlerInterface.

To fix/hack it we need to fetch the Session Storage from the Symfony kernel and build our own cookie, it's included, but I still have some problems...

First off all, all cookies are duplicated(!):

POST http://localhost:8007/login_check

HTTP/1.1 302 Found
Cache-Control: max-age=0, must-revalidate, private
Content-Type: text/html; charset=UTF-8
Date: Mon, 25 Jun 2018 15:29:10 GMT
Location: /dashboard/
Set-Cookie: sf_redirect=%7B%22token%22%3A%22706c85%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: eportal_auth=slfj100pcgchcb69h7n6abdrgo; path=/; httponly
Set-Cookie: sf_redirect=%7B%22token%22%3A%22706c85%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: eportal_auth=slfj100pcgchcb69h7n6abdrgo; path=/; httponly
X-Debug-Token: 706c85
X-Debug-Token-Link: http://localhost:8007/_profiler/706c85
Content-Length: 288

My current code:

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

        $session = $request->getSession();
        if ($session) {
            $name = $session->getName();
            $sessionId = $session->getId();

            if (!$request->cookies->has($name)) {
                $cookie = new Cookie($name, $sessionId);
                $response->headers->setCookie($cookie);
            }
        }

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

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

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Try 1.0.4, it should help with busy sockets and potential locks on resources.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Thanks :)

I got the session to work, but it's not pretty :/

kernel = new \App\Kernel("dev", true);
$kernel->boot();
$cacheDir = $kernel->getCacheDir();
while ($req = $psr7->acceptRequest()) {
    try {
        $httpFoundationFactory = new HttpFoundationFactory();
        $request = $httpFoundationFactory->createRequest($req);
        
        // If session is missing from cookies, generate a new Id
        $sessionId = $request->cookies->get(session_name(), session_create_id());
        session_id($sessionId);

        $response = $kernel->handle($request);
        $kernel->terminate($request, $response);

        $session = $request->getSession();
        if ($session) {
            if (!$request->cookies->has(session_name())) {
                // TODO: build real cookie with proper
                // TODO: domain,path,lifetime,secure,httpOnly etc
                $cookie = new Cookie(session_name(), $sessionId);
                $response->headers->setCookie($cookie);
            }
            $session->save();
        }

        $psr7factory = new DiactorosFactory();
        $psr7response = $psr7factory->createResponse($response);
        $psr7->respond($psr7response);
        $kernel->shutdown();
    } catch (\Throwable $e) {
        $worker->error((string)$e);
        $worker->stop();
    }
}

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

We are using session middleware which fallbacks to default PHP session mechanism with a custom cookie, this might explain why we do not have the same issue. Native PHP sessions do not work with long-running scripts, you must to start and stop them manually. Are you sure there is no Symfony bundle to manage sessions on framework level?

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

There probably is, but I haven't have time to look into it (and get it to work!)

from roadrunner.

Pomyk avatar Pomyk commented on May 4, 2024

To make sessions work in a silex app (using symfony components):

in the request loop:

$session_id = $req->cookies->get('session_cookie_name');
if (!empty($session_id)) {
     session_id($session_id);
}
$resp = $app->handle($req);
$app['session.storage']->save();

For session storage use
Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Hi!

In Symfony 4 we don't have access to the Session storage service, also we need to set the session id in the cookie if it's missing. How does Silex handle that?

from roadrunner.

Pomyk avatar Pomyk commented on May 4, 2024

Actually it's not working 100% for me either... back to the drawing board.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

I assume $session->save() (either it's Silex or Symfony) only saves the session to the designated session storage.

But the session cookie is never set on the Symfony request, I assume it's the same on Silex?

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

I'm closing this request due to inactivity.

from roadrunner.

mnavarrocarter avatar mnavarrocarter commented on May 4, 2024

@wolfy-j I would like to to consider reopening this and I'm willing to provide more feedback on the issue, since something similar is happening with my application as well.

AFAIK, Symfony 4 does not use php native session solutions as pointed out here and here.

Mi issue is a bit different though. I configured 4 workers to my web app, and when I authenticate with one of them successfully, then another one grabs the redirect request, and tries to access the protected page, but unauthenticated.

I know that this is due to the fact that a different worker handles the redirect, because if I keep authenticating, eventually I kinda hit a worker that is authenticated and I'm able to enter. And because if I run the app with just one worker, it authenticates and works fine. Any idea of what could I be missing?

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

I would recommend asking advice from Symfony users, we use the almost identical mechanism of auto-managing sessions via middleware and it works perfectly. Is there any issue with request mapping between Symfony Request and PSR7?

from roadrunner.

mnavarrocarter avatar mnavarrocarter commented on May 4, 2024

I'll do a little bit of research. Symfony does not use PSR7 Requests by default. They developed some sort of factory bridge to be able to work with PSR 7. There may be something missing there. Or maybe Zend Diactoros uses native session functions.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

@dunglas would you mind providing any advice what might be the case? From PSR7 and RR standpoint we are 100% confident that it works properly cos, well, it works on production for over 6 months now and we have this tests:

https://github.com/spiral/roadrunner/blob/master/tests/http/cookie.php
https://github.com/spiral/roadrunner/blob/master/service/http/handler_test.go#L170

from roadrunner.

dunglas avatar dunglas commented on May 4, 2024

I'll try to give it a look asap. Do you have a minimal reproducer?
The PSR-7 to HttpFoundation bridge does support cookies. However sessions and cookies are a totally different thing in Symfony.

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Hi! my research concluded with Symfony not creating a Session Cookie on the Response object, but leaves it to PHP to set the relevant cookies (and just configures PHP's session handling according to the relevant symfony config files)

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php#L149

Maybe it's possible to write a custom "decorator" that catches php's set-cookie header, and adds it to the Response object somehow? :)

edit Alternatively creating a HttpFoundation driver in RoadRunner that knows about this limitation and catches the set-cookie header itself and ads it to the Response object...

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

edit Alternatively creating a HttpFoundation driver in RoadRunner that knows about this limitation and catches the set-cookie header itself and ads it to the Response object...

I don't think this is possible, php write headers directly to STDOUT and it ignores active buffers. The only viable option is to disable default cookies and manage sid on app end: https://github.com/spiral/session/blob/master/src/SessionFactory.php#L59

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

Yeah, if I remember correctly, RoadRunner executes the php scripts as CLI(?), and then header() doesn't do anything.

So the only solution I see is intercept Symfony's session handler somehow.

from roadrunner.

1ma avatar 1ma commented on May 4, 2024

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

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

Please, do 😅

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Yeah, if I remember correctly, RoadRunner executes the php scripts as CLI(?), and then header() doesn't do anything.

So the only solution I see is intercept Symfony's session handler somehow.

I'm pretty sure Symfony can do it out of the box, but I not aware how to properly configure it. :(

from roadrunner.

Richard87 avatar Richard87 commented on May 4, 2024

@dunglas Is that a feature you think Symfony wants in the core, or should it be a part of RoadRunner or a new library, maybe in a RoadRunnerBundle to connect it all?

I have a feeling any legacy projects might take a hit if we disconnect symfony from php's own session handling?

Maybe a Symfony Flex Recipe could install a RoadRunnerBundle whenever RoadRunner was installed ... what do you think @wolfy-j ?

from roadrunner.

ruudk avatar ruudk commented on May 4, 2024

@shyim Smart, this should be added to the wiki

from roadrunner.

NiceWG avatar NiceWG commented on May 4, 2024

Do not understand whet needed to do with this situation. Where I do wrong?

"C:\roadrunner>rr serve -v -d
DEBU[0003] [rpc]: started
DEBU[0003] [http]: started
ERRO[0003] [http]: unable to connect to worker: unexpected response, header is missing: exit status 1
DEBU[0003] [rpc]: stopped"

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Try to execute command described in rr.yaml file manually and see what happens. Most likely you are not forwarding errs to stderr and RR cannot capture it. Try to run php worker.php.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Added to Wiki: https://github.com/spiral/roadrunner/wiki/PHP-Workers

from roadrunner.

pimshtein avatar pimshtein commented on May 4, 2024

Hi. Can you help?
I have a code.
Golang:

srv := roadrunner.NewServer(
		&roadrunner.ServerConfig{
			Command: "php test.php hbc-worker",
			Relay:   "unix:///tmp/hbc.sock",
			RelayTimeout: time.Second * 10,
			Pool: &roadrunner.Config{
				NumWorkers:      1,
				AllocateTimeout: time.Second * 30,
				DestroyTimeout:  time.Second * 30,
			},
		})
	defer srv.Stop()

	if err := srv.Start(); nil != err {
		log.Fatal(err)
	}

	res, err := srv.Exec(&roadrunner.Payload{Body: []byte("hello")})

Php:
$rr = new Worker(new SocketRelay("/tmp/hbc.sock", null, SocketRelay::SOCK_UNIX));

When I run the code on go, I get an error "unable to connect to worker: relay timeout: signal: killed" because this event never occurs:

case rl := <-f.relayChan(*w.Pid):
			timer.Stop()
			f.cleanChan(*w.Pid)
			return rl, nil

Where I do wrong?

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

But the error is that worker has never connected to socket server, so it was marked as dead. Make sure that PHP script does not stuck anywhere or try pipes.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Also, try to start worker manually and see what happens. If it does not help please post your php code so I can’t take a look.

from roadrunner.

pimshtein avatar pimshtein commented on May 4, 2024

The PHP script was always waiting because xdebug was running. For this reason, php was unable to connect to the socket. The problem is solved. Thanks for help!

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

@wslaghekke manual session control should work! If someone can verify this approach I would update Wiki page.

I would also recommend to use finally part of try catch block to close the session in case of app error.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

@wslaghekke if someone can verify the approach I can update the wiki.

from roadrunner.

wslaghekke avatar wslaghekke commented on May 4, 2024

@wolfy-j what would be neccesary to verify the approach? do you want me to provide an example repo? or are you waiting for someone else to test this?

I've also updated my comment to do the session cleanup in a finally block

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Attaching sample repo will help with that, I would like someone else to verify it as well.

This ticket has been reopened multiple times and I want to make sure we have a solid fix.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

@wslaghekke are symfony create new session on first request?
Your snippet doesn't work for me, session won't starting.

from roadrunner.

wslaghekke avatar wslaghekke commented on May 4, 2024

@grachevko It thought i could check the session_status to see if symfony used the session (and so if we need the session cookie at all) but it seems that doesnt work, i've updated my code snippet to not use that check anymore, and always send the session cookie.

Could you test it again?

I've also created an example repository with a simple counter in the session if testing a simple application is desired: https://github.com/wslaghekke/roadrunner-sessions

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

@wslaghekke i have no session cookie on first request. Symfony need to initialize session to store csrf token for login form and then set session cookie in response.
But this doesn't happen, cookie header not exist in response object from symfony.
If your project running on rr correctly initialize session maybe problem on my side.

from roadrunner.

wslaghekke avatar wslaghekke commented on May 4, 2024

@grachevko Do you have the repo or an example repo i can use to reproduce the issue?
Then i could try to find out what is going wrong.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

@wslaghekke i find my mistake, new cookie is set. But now i find new bug.
If delete cookie, worker will return previous handled. I guess this is because session service in symfony is shared and it not resetted between requests.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

My last snippet working today on production all day. Works great.

One thing, rr duplicate cookies, i don't know why.
image

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Try to dump Response to the STDERR and see if there are 2 cookie headers being send to rr.
https://github.com/spiral/roadrunner/wiki/Debugging most likely Symfony is duplicating them.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Should I convert this ticket into Wiki or there is still outstanding questions ?

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

It will be premature because above snippets throws error in some cases which I am testing now.
Moreover calling Kernel::reboot() reduce benefits from RR as it slow down execution about 4 times in my benchmark.
Removing reboot produce new errors. Keep working.

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

#96

from roadrunner.

wolfy-j avatar wolfy-j commented on May 4, 2024

Please pay attention to #110 which provides native integration with Symfony.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

@Alex-Bond this is my SessionListener with whom everything works.
I don't understand your problem, can you explain?

from roadrunner.

Alex-Bond avatar Alex-Bond commented on May 4, 2024

@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.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

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

from roadrunner.

Alex-Bond avatar Alex-Bond commented on May 4, 2024

@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.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

@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?

from roadrunner.

Alex-Bond avatar Alex-Bond commented on May 4, 2024

@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() возаращает иногда пустоту даже если данные в сессии есть. Я не знаю почему, но мне не удается добится вменяемой проверки на содержание сесиии.

from roadrunner.

grachevko avatar grachevko commented on May 4, 2024

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

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

from roadrunner.

Alex-Bond avatar Alex-Bond commented on May 4, 2024

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

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

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

from roadrunner.

speller avatar speller commented on May 4, 2024

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.

from roadrunner.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.