Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Error by using Response::redirect before Session::set
  • Hello FuelPHP-Community, I use the 'db'-Session for the saving the user data and got an error in FuelPHP 1.2 when I use Response::redirect('xyz'): Fuel\Core\FuelException [ Error ]: The session data stored by the application in the cookie exceeds 4Kb. Select a different session storage driver. --> COREPATH/classes/session/driver.php @ line 431 The fueldid is not set. If I write Session::set('welcome', 'Welcome to XYZ') before Response::redirect('xyz'), the fueldid is set and the error does not occur. Is it a bug or a feature?
  • I use the following configuration in app/config/session.php as well as in core/config/session.php (to be sure that it will be used): return array(
    /**
    * global configuration
    */ // set it to false to prevent the static session from auto-initializing, know that it might make your session
    // expire sooner because it's not updated when it's not used. note that auto-initializing always loads the default driver
    'auto_initialize' => true, // if no session type is requested, use the default
    'driver' => 'db', // check for an IP address match after loading the cookie (optional, default = false)
    'match_ip' => false, // check for a user agent match after loading the cookie (optional, default = true)
    'match_ua' => false, // cookie domain (optional, default = '')
    'cookie_domain' => '', // cookie path (optional, default = '/')
    'cookie_path' => '/', // cookie http_only flag (optional, default = use the cookie class default)
    'cookie_http_only' => null, // if true, the session expires when the browser is closed (optional, default = false)
    'expire_on_close' => false, // session expiration time, <= 0 means 2 years! (optional, default = 2 hours)
    'expiration_time' => 7200, // session ID rotation time (optional, default = 300)
    'rotation_time' => 7200, // default ID for flash variables (optional, default = 'flash')
    'flash_id' => 'flash', // if false, expire flash values only after it's used (optional, default = true)
    'flash_auto_expire' => true, // for requests that don't support cookies (i.e. flash), use this POST variable to pass the cookie to the session driver
    'post_cookie_name' => '', /**
    * specific driver configurations. to override a global setting, just add it to the driver config with a different value
    */ // special configuration settings for cookie based sessions
    'cookie' => array(
    'cookie_name' => 'fuelcid', // name of the session cookie for cookie based sessions
    ), // specific configuration settings for file based sessions
    'file' => array(
    'cookie_name' => 'fuelfid', // name of the session cookie for file based sessions
    'path' => '/tmp', // path where the session files should be stored
    'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
    ), // specific configuration settings for memcached based sessions
    'memcached' => array(
    'cookie_name' => 'fuelmid', // name of the session cookie for memcached based sessions
    'servers' => array( // array of servers and portnumbers that run the memcached service
    array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100)
    ),
    ), // specific configuration settings for database based sessions
    'db' => array(
    'cookie_name' => 'fueldid', // name of the session cookie for database based sessions
    'database' => 'session', // name of the database name (as configured in config/db.php)
    'table' => 'sessions', // name of the sessions table
    'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
    ), // specific configuration settings for redis based sessions
    'redis' => array(
    'cookie_name' => 'fuelrid', // name of the session cookie for redis based sessions
    'database' => 'default' // name of the redis database to use (as configured in config/db.php)
    )
    );
  • Hello, now I've found a little time to look closer to the problem. In the new version 1.3 of fuelphp it is solved. In previous versions of fuelphp the function create in core/classes/session/db.php inserted the value of the 'payload' key before the command "$this->_set_cookie" so that payloads values over 4KB throws in the function _set_cookie in core/classes/session/driver.php the FuelException('The session data stored by the application in the cookie exceeds 4Kb. Select a different session storage driver.').
  • I tried to autoload the session via /app/config.php --> always_load--> classes and in the Controller is the line $session_user = Session::get('user'); before the redirect so that the session class must be loaded, but the error occurs again.
  • I'm baffled. I've installed a new 1.2/master environment, created a 'redirect' controller with your code in it, and added 'session' to always load. I can't reproduce your problem, no matter what I do. I also tried 1.2-RC1 (just in case you have installed that), but no difference. Can you zip your entire app folder, and email it to me at wanwizard<at>fuelphp.com?
  • Thank you Harro for your offer to have a look on my code. It is a commercial project, so it will take a while until I extract a small authorized version.
  • Hi Kai, Did you managed to get the thing solved? I'm getting the same error though i'm using stock v1.2. It's the same with v1.2.1
  • Do you have some code for me to reproduce it? Because I tried and I can't...
  • i'll send you out the whole apps. btw, I notice it happens if i change the input type to select or radio. Where should I send the code Harro?
  • it seems like, it happen when I change from Form::input to Form::radio or Form::Select and when change back to Form::input it will retain the error.
  • lokman4844 wrote on Friday 29th of June 2012:
    i'll send you out the whole apps. btw, I notice it happens if i change the input type to select or radio. Where should I send the code Harro?
    You can send it to wanwizard<at>fuelphp.com, and explain what exactly I have to do to reproduce it.
  • Thanks for sending me the code. I'll reply here so others might benefit from it. The message has nothing to do with redirects. Your application uses a cookie to store all session data (which is the default, and you haven't configured anything else). The maximum size of a cookie payload is 4Kb, this is a browser limit (and probably limited by the HTTP header line length). When submitting the contacts form, you store all validation objects (so not the errors but the objects themselfs) into the session. Which after serializing and encrypting makes the payload 79823 bytes, clearly more then the maximum of 4Kb. So the error message is absolutely correct. Either find a more efficient means of storing the messages in the session (or don't store them at all but pass them directly to the view as a variable), or choose a different session storage mechanism that doesn't have the 4Kb limit.
  • Harro Verton wrote on Saturday 30th of June 2012:
    Thanks for sending me the code. I'll reply here so others might benefit from it. The message has nothing to do with redirects. Your application uses a cookie to store all session data (which is the default, and you haven't configured anything else). The maximum size of a cookie payload is 4Kb, this is a browser limit (and probably limited by the HTTP header line length). When submitting the contacts form, you store all validation objects (so not the errors but the objects themselfs) into the session. Which after serializing and encrypting makes the payload 79823 bytes, clearly more then the maximum of 4Kb. So the error message is absolutely correct. Either find a more efficient means of storing the messages in the session (or don't store them at all but pass them directly to the view as a variable), or choose a different session storage mechanism that doesn't have the 4Kb limit.

    Hi Harro, Thanks for the prompt reply. The error does sound like that but I'm not sure how to respond to it as all setting is default. When you mention find a more efficient means of storing the messages, are you referring to the error or the variables? Appreciate if you could shed some lights on what are other methods that can be used to store the message or other storage mechanism.
  • The default template stores the validation objects in the session I see. Which is not a problem, providing you use session storage that can handle that amount of data. A cookie can't. You shouldn't use a cookie anyway, it's very limited in size (as you already noticed), and storing user data client side (encrypted or not) is not a good idea. So if you want to continue using the standard oil template, switch session storage driver. FuelPHP supports the following session drivers: 'cookie', 'db', 'memcached', 'redis' and 'file'. If you want to stick to cookies, you have to abandon the idea of storing the errors in the session. Instead, just pass the validation object directory to the view. So
    // instead of doing
    Session::set_flash('error', $val->error());
    
    // do
    $this->template->set('val', $val);
    
    Then in the template view
    // replace
    <?php if (Session::get_flash('error')): ?>
     <div class="alert-message error">
      <p>
      <?php echo implode('</p><p>', e((array) Session::get_flash('error'))); ?>
      </p>
     </div>
    <?php endif; ?>
    
    // by
    <?php if (isset($val)): ?>
     <div class="alert-message error">
      <?php foreach($val->error() as $e): ?>
        echo $e->get_message(false, '<p>', '</p>');
      <?php endforeach; ?>
     </div>
    <?php endif; ?>
    
    If you want this for everything you generate, copy the views from the oil package to app/views (maintain the same folder structure) and modify them there. Next time you generate something your custom views will be used.
  • Hi, I've got the same problem.
    I've tried doing as you've suggested Harro, my view is like you've written and here is the controller: public function action_signup()
    {
    // create the view
    $view = View::forge( 'layout' );
    $valid = Validation::forge(); $valid->add( 'firstname', 'First Name' )->add_rule( 'required' )
    ->add_rule( 'min_length', 2 );
    $valid->add( 'lastname', 'Last Name' )->add_rule( 'required' )
    ->add_rule( 'min_length', 2 );
    $valid->add( 'email', 'Email Address' )->add_rule( 'required' )
    ->add_rule( 'valid_email' );
    $valid->add( 'confirmemail', 'Email Confirmation' )->add_rule( 'required' )
    ->add_rule( 'match_field', 'email' );
    $valid->add( 'username', 'Username' )->add_rule( 'required' )
    ->add_rule( 'min_length', 3)
    ->add_rule( 'max_length', 15 );
    $valid->add( 'password', 'Password' )->add_rule( 'required' )
    ->add_rule( 'min_length', 7 )
    ->add_rule( 'max_length', 12 );
    $valid->add( 'confirmpassword', 'Password Confirmation' )->add_rule( 'required' )
    ->add_rule( 'match_field', 'password' ); if( Input::method() == 'POST' && $valid->run() )
    {
    Response::redirect( 'http://google.co.uk' );
    }
    else
    {
    $view->set( 'valid', $valid );
    }
    // assign global variables so all views have access to them
    $view->set_global( 'title', 'Create an Account' ); // assign views as variables
    $view->head = View::forge( 'head' );
    $view->header = View::forge( 'header' );
    $view->content = View::forge( 'login/signup' );
    $view->footer = View::forge( 'footer' ); // return the view object to the Request
    return $view;
    } When the form submits it recalls the same controller so that the validation can be displayed on the same page as the form.
    When there are errors I'm getting the following message:
    RuntimeException [ Error ]: Object class "Fuel\Core\Validation" could not be converted to string or sanitized as ArrayAccess. Whitelist it in security.whitelisted_classes in app/config/config.php to allow it to be passed unchecked. Any ideas why it's not working?
  • As the message says, the object can't be sanitized. Pass it to the view raw:
    $view->set( 'valid', $valid, false );
    
    don't forget that this passes fieldnames and values (as they can be part of the error message) to the view unescaped, so use the e() function to escape them when you echo them.
  • Thanks Harro!
    Finally it works! as you mentioned $view->set( 'valid', $valid, false ); and i later found out which rule have a problem. Thanks!
  • Thanks for the answer Harro, works fine now.
    Thanks for starting the thread Lokman4844.
  • no need to thank me xonorageous, its kai_haase started it but Harro the superb one answering to our question even on the weekend :) Thanks Harro!
  • sorry that it took some time ... i tried to reproduce the error with as little coding as possible. I found out that it is not an error of the response::redirect. It seems that it is not possible to use the first Session::set with a high volume of data. I use db config for the session and the before function in a Controller_Template Here my testcode: public function before()
    {
    parent::before(); // if you remove the '//' and clear the browser cache the error not occurs
    // Session::set('welcome', 'welcome to my test'); // check login data
    if(isset($_POST) && isset($_POST))
    {
    // ...
    $this->logged_in = true;
    // replace the string with a much longer string
    $string = 'use here a string with 3000 characters to test the data for an object';
    Session::set('text', $string);
    }
    }
  • Are you sure you have your session config set to db? I've just tried
    public function action_index()
    {
     $string = str_repeat('0123456789', 3000);
     Session::set('text', $string);
    
     return 'done';
    }
    
    which stores a 30.000 byte string, without problems.
  • Yes, i have set session config to db in app/config/session.php and (to be sure that db will be used) in core/config/session.php (see below). Have you tried to use Session::set with the long string in the 'before' function as the first call of the session class and cleared the cache and cookies of your browser? The error only occurs if there is no cookie resp. there is no session. My session config: return array(
    /**
    * global configuration
    */ // set it to false to prevent the static session from auto-initializing, know that it might make your session
    // expire sooner because it's not updated when it's not used. note that auto-initializing always loads the default driver
    'auto_initialize' => true, // if no session type is requested, use the default
    'driver' => 'db', // check for an IP address match after loading the cookie (optional, default = false)
    'match_ip' => false, // check for a user agent match after loading the cookie (optional, default = true)
    'match_ua' => false, // cookie domain (optional, default = '')
    'cookie_domain' => '', // cookie path (optional, default = '/')
    'cookie_path' => '/', // cookie http_only flag (optional, default = use the cookie class default)
    'cookie_http_only' => null, // if true, the session expires when the browser is closed (optional, default = false)
    'expire_on_close' => false, // session expiration time, <= 0 means 2 years! (optional, default = 2 hours)
    'expiration_time' => 7200, // session ID rotation time (optional, default = 300)
    'rotation_time' => 7200, // default ID for flash variables (optional, default = 'flash')
    'flash_id' => 'flash', // if false, expire flash values only after it's used (optional, default = true)
    'flash_auto_expire' => true, // for requests that don't support cookies (i.e. flash), use this POST variable to pass the cookie to the session driver
    'post_cookie_name' => '', /**
    * specific driver configurations. to override a global setting, just add it to the driver config with a different value
    */ // special configuration settings for cookie based sessions
    'cookie' => array(
    'cookie_name' => 'fuelcid', // name of the session cookie for cookie based sessions
    ), // specific configuration settings for file based sessions
    'file' => array(
    'cookie_name' => 'fuelfid', // name of the session cookie for file based sessions
    'path' => '/tmp', // path where the session files should be stored
    'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
    ), // specific configuration settings for memcached based sessions
    'memcached' => array(
    'cookie_name' => 'fuelmid', // name of the session cookie for memcached based sessions
    'servers' => array( // array of servers and portnumbers that run the memcached service
    array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100)
    ),
    ), // specific configuration settings for database based sessions
    'db' => array(
    'cookie_name' => 'fueldid', // name of the session cookie for database based sessions
    'database' => 'session', // name of the database name (as configured in config/db.php)
    'table' => 'sessions', // name of the sessions table
    'gc_probability' => 5 // probability % (between 0 and 100) for garbage collection
    ), // specific configuration settings for redis based sessions
    'redis' => array(
    'cookie_name' => 'fuelrid', // name of the session cookie for redis based sessions
    'database' => 'default' // name of the redis database to use (as configured in config/db.php)
    )
    );
  • I've never seen this issue. How can I reproduce this?
  • I used a Controller (extends Controller_Template) with the before function: public function before($data = null)
    {
    parent::before();
    // ...
    // Session::set('welcome', 'Welcome to XYZ');
    // ...
    Response::redirect('redirect_uri');
    }
  • And you've got the Session class 'always loaded'?
  • Hi,
    I'm using version 1.4. Facing the same problem. Tried the above method but couldn't solve my problem :(.
    Can anyone please help ?

    Thanks.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion