Jump to content

Connect to PW without starting a session


gebeer
 Share

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
Link to comment
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?

Link to comment
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.

Link to comment
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. :)

Link to comment
Share on other sites

  • 1 month later...
  • 2 months later...

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
Link to comment
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.

Link to comment
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
Link to comment
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.

Link to comment
Share on other sites

  • 2 years later...
  • 3 months later...
  • 5 months later...
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 11
  • Thanks 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...