Jump to content
gebeer

Connect to PW without starting a session

Recommended Posts

Hello all,

I am using part of a PW install as a backend for a RESTful API.

Everytime a client consumes the API, a session is started. The RESTful approach is sessionless per definition and I would like to avoid sessions, if possible, for performance reasons.

When I look at the open sessions while only one client is getting or putting data through my REST API, I can see that there are quite a few (over 50) sessions open from that client.

The project is at a testing stage right now and I'm afraid that once 50 or 100 clients are connected, the sessions will put a big load on the server.

Is it advisable at all to try and avoid sessions?

How would I go about killing sessions or, even better, connect to my API endpoints without starting a session in the first place? 

  • Like 1

Share this post


Link to post
Share on other sites

The session is started by the wire/core/session.php, which currently seems to be a mandatory part of the core. Things like determining the current user and further down the road the template access management rely on a session being present. 

Share this post


Link to post
Share on other sites

Thanks for the answer.

I see that there is a config setting "$config->sessionExpireSeconds" which defaults to 86400 seconds.

Would it make any difference to the server load to reduce the session time?

Or does nayone have an idea how to deal with the situation?

Share this post


Link to post
Share on other sites

I'm not sure about the performance considerations of short vs long sessions, but I think it would be nice if the core would allow sessionless usage at least for unauthenticated requests. Shouldn't be to hard to declare everyone "guest", but there may be considerations regarding the $session api variable.

Share this post


Link to post
Share on other sites

Yeah, would be great if we could decide on a template basis whether to use sessions or not.

Share this post


Link to post
Share on other sites

maybe you could delete sessions using a cron.

every x minutes delete sessions longer than y seconds.

Share this post


Link to post
Share on other sites

Maybe you can use Module: Session Handler Database,

Don't know if it is a much better performance, but could be, as it don't need to touch filesystem.

You find it under modules -> core -> "Session". There you can activate it.

In this regard, it may also be useful to use this both settings for PHP in the site/config.php

@ini_set("session.gc_probability", 1);
@ini_set("session.gc_divisor", 100);

It has to do with the session garbage collector. Maybe you can tweak those settings. But I don't know, you have to research on your own for that. :)

Share this post


Link to post
Share on other sites

Thank you all for your suggestions.

@horst

I'm already storing sessions in the DB. Will have a look into the ini settings.

Meanwhile I found and interesting article which talks about using "session_write_close();". I will do some more research and post my findings here.

  • Like 3

Share this post


Link to post
Share on other sites

Just wanted to report my findings.

session_name($config->sessionName);
session_write_close();

does not have the desired effect. Sessions remain open.

session_name($config->sessionName);
session_write_close();
session_destroy();

throws a Warning: "Warning: session_destroy(): Trying to destroy uninitialized session"

What I think happens, is that "session_name($config->sessionName);" does not capture the original PW session.

If I do

$_SESSION = array();
session_destroy();

the Sessions get destroyed and are not recorded in the DB anymore.

I s there a way how I can get the PW session other than with $_SESSION?

EDIT: looking at var_dump($session), it is all protected properties.

  • Like 1

Share this post


Link to post
Share on other sites

I haven't tried this - but, it may be possible to solve this by creating two new session handler modules. A 'dummy' session handler for use with your API, and a clone of the Database handler for normal web requests.

Your initialisation code for each would detect if it's being loaded via the REST interface or traditional HTTP, and only register the hook into session when appropriate for it to do so.

In your dummy handler, all the storage methods would use an internal array/WireData object, and the other one would work exactly like the existing database one.

Share this post


Link to post
Share on other sites

There's no way to hook anything in regards to the session starting. This all happens in processwire's bootstrap part, before even the earliest hooks would run. But with Ryan having a processwire javascript api on the roadmap it may be time to discuss if pw 3.0 shouldn't support authentication without session.

  • Like 2

Share this post


Link to post
Share on other sites

Thank you all for your input.

@LostKobrakai

Would be great if this could be implemented into 3.0 :)

Share this post


Link to post
Share on other sites

This is what I was thinking of:
 

<?php

// Code for SessionHandler abstract class for reference
abstract class WireSessionHandler extends WireData implements Module {

	/**
	 * Initialize the save handler
	 *
	 */
	public function __construct() {
		$this->addHookBefore('Session::init', $this, 'attach'); 
		register_shutdown_function('session_write_close'); 
	}
}

class SessionHandlerDB extends WireSessionHandler implements Module, ConfigurableModule {

	public function __construct() {
		if ( ! isRestApi()) {
			parent::__construct();
		}
	}
}


class SessionHandlerDummy extends WireSessionHandler implements Module, ConfigurableModule {

	public function __construct() {
		if (isRestApi()) {
			parent::__construct();
		}
	}
}

If that doesn't work, there's an attach() function which could be overwritten/extended instead.

Share this post


Link to post
Share on other sites
5 hours ago, tiefenbacher_bluetomato said:

anything news about sessionles requests?

I don't think anything has changed since.

Share this post


Link to post
Share on other sites
On 9/11/2015 at 3:20 PM, gebeer said:

Hello all,

I am using part of a PW install as a backend for a RESTful API.

Everytime a client consumes the API, a session is started. The RESTful approach is sessionless per definition and I would like to avoid sessions, if possible, for performance reasons.

When I look at the open sessions while only one client is getting or putting data through my REST API, I can see that there are quite a few (over 50) sessions open from that client.

The project is at a testing stage right now and I'm afraid that once 50 or 100 clients are connected, the sessions will put a big load on the server.

Is it advisable at all to try and avoid sessions?

How would I go about killing sessions or, even better, connect to my API endpoints without starting a session in the first place?

Hi @gebeer

Just stumbled across this (I know my reply is a little late,) but it is totally possible to prevent your rest API endpoints from starting sessions by using the $config->sessionAllow; variable. If you define it to be a function that returns bool true or false, then it will be evaluated and the return value determines if the Session class constructor is allowed to start a new session. There's an example of it in the default wire/config.php file at line 245. Reproduced here...

$config->sessionAllow = function($session) {
    // if there is a session cookie, a session is likely already in use so keep it going
    if($session->hasCookie()) return true;

    // if URL is an admin URL, allow session
    if(strpos($_SERVER['REQUEST_URI'], $session->config->urls->admin) === 0) return true;

    // otherwise disallow session
    return false;
};

You just need to rewrite the function so it returns false for your API endpoint path. Make that change and add it to your site/config.php file, and I think that anything hitting your API endpoint directly will not have a session created for the connection.

Hope that helps!

  • Like 9
  • Thanks 1

Share this post


Link to post
Share on other sites

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By fliwire
      Hi, after redirect to payment page processwire session lost because of samesite cookies changed default to "lax".

      https://web.dev/samesite-cookies-explained/

      tried to hook session::init but not works ?
      $wire->addHookBefore("Session::init", function (HookEvent $event) { ini_set('session.cookie_samesite', 'None'); session_set_cookie_params(['samesite' => 'None']); });

      set by htaccess works
       
      <ifmodule mod_headers.c> Header always edit Set-Cookie ^(.*)$ $1;SameSite=None;Secure </ifmodule>  
    • By derelektrischemoench
      Hi guys,
      I'm facing a somewhat strange issue here which I can't quite wrap my head around. 
      I have a PW site in development which runs on three machines simultaneously, one staging server which is accessible as a preview instance for my customer, my PC and my laptop. 
      I have three completely identical settings on each of the three machines (same apache version, same php version, same codebase, same database); however on my PC I am unable to log into the backend. I get no error message or anything, when I try to login; i just get redirected to the login  page. I have already enabled database driven sessions (I enabled them on my laptop, then I dumped the database and copied it to my pc); I have cleared the cache directory; I cleared the sessions in the database; I cleared my browser caches, I tried different browsers, all to no avail; I am unable to login when using my pc, the instances all have the same .htaccess.
      Is there something I'm missing here or does anyone have a clue as to what my issue here might be? I'm using processwire 3.0.123
      Thanks for any input, greetings
      derelektrischemoench
       
      //edit: I've noticed something interesting; despite the directories of my web folders being the same layout; when I open the admin page i get a 404 on the processwire/ resource in the networks panel of chrome; on my laptop I get a  200.... I guess this is where my problem is; but why?
       
       
    • By derelektrischemoench
      Hi guys,
      I'm facing a somewhat strange issue here which I can't quite wrap my head around. 
      I have a PW site in development which runs on three machines simultaneously, one staging server which is accessible as a preview instance for my customer, my PC and my laptop. 
      I have three completely identical settings on each of the three machines (same apache version, same php version, same codebase, same database); however on my PC I am unable to log into the backend. I get no error message or anything, when I try to login; i just get redirected to the login  page. I have already enabled database driven sessions (I enabled them on my laptop, then I dumped the database and copied it to my pc); I have cleared the cache directory; I cleared the sessions in the database; I cleared my browser caches, I tried different browsers, all to no avail; I am unable to login when using my pc, the instances all have the same .htaccess.
      Is there something I'm missing here or does anyone have a clue as to what my issue here might be? I'm using processwire 3.0.123
      Thanks for any input, greetings
      derelektrischemoench
       
       
    • By Peter Knight
      How do you guys handle large session tables when sessions are being recorded to the database?
      I notice one of my sites has a session table of over 14MB 
      Am I missing a way in the Admin or a module to auto-remove any sessions older than X days?
      Thanks
       
    • By helmut2509
      In my PW-Application there is currently no session timeout.
      I want to set the user session to 60 minutes which means that after 60 minutes of inactivity the user will be redirected to the homepage.
      so I added the following entry to my config.php:
      $config->sessionExpireSeconds = 120; (120 seconds is just for testing).
      But after five minutes of inactivity I am still logged in, there is no redirection.
      Is there anything wrong or did I miss something?
      In php.ini I have the entry:
      session.cookie_lifetime = 3600
×
×
  • Create New...