cakephp: Sessions: session_write_close() and redirect() - data not saved on php-fpm/nginx

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • CakePHP Version: 3.7.0

  • Platform and Target: php-fpm 7.1.26-1+ubuntu16.04.1+deb.sury.org+1, nginx 1.10.3

  • Using database sessions - no specials, just plain vanilla. session.lazy_write Off in fpm config.

What you did

We were doing final testing of our app after major upgrade and noticed that some code does not work as it should. The code is highly dependent on session variables as they hold the state. The script updates the state in the session just before redirecting - and then we noticed, that the variable that is written before the redirect is not written to the session itself. It does succeed after ca. 8-10 attempts.

What happened

I am not sure how much of a problem it is - but it’s not something that is wildly discussed other places. I also have a feeling this could somehow be related to #11162.

I can reproduce this behavior on my php-fpm setup every time. I cannot reproduce it when running on cakephp built-in server.

The following snippet shows the problem (controller action):

public function bazinga()
    {
        $this->autoRender = false; 
        $session = $this->request->getSession();                 

        if($this->request->getQuery('next') !== null) {                                  
            $sval =  time(); 
            $session->write('Bazinga.yes',$sval);                   
           // GLUE
            return $this->redirect(['controller' => 'Bazinga', 'action' => 'bazinga', '?' => ['sval' => $sval]]);            
        }

        echo "<hr>";
        echo $session->read('Bazinga.yes'); 

    }

If you access the url as /bazinga/bazinga?next it should print the timestamp recorded at the time of the redirect. But it does not. If you manage to save the timestamp - you will notice it is not changing on subsequent requests where ?next is in the URL.

Snippet above will work EVERY time if you add the following after // GLUE and before the return statement:

// GLUE
session_write_close(); 
return $this->redirect(['controller' => 'Bazinga', 'action' => 'bazinga', '?' => ['sval' => $sval]]);  

Then it works flawlessly as intended.

Session data is written automatically on destroy - and if I terminate the script with an exit; before the return - then data is also saved correctly in the database.

What you expected to happen

Where does it come from. It “used to work” w/o problems on older PHP releases/Cake version. I would expect it just worked as intended - i.e. when I do $session->write() I would like to have that data stored in the session.

How is the session_write_close() administered internally by cakephp? Isn’t it an idea to add it into the Controller::redirect() - and check whether session is started etc. and then explicitly close it?

Are there better alternatives that could solve this problem for majority of “possible” cases?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 18 (17 by maintainers)

Most upvoted comments

Very interesting. We could probably add a session_write_close call here that should solve the issue.