Closed Ahzam-Lathiya closed 2 years ago
Do not use php session, it's blocking and it can not work in Swoole. Maybe something like https://github.com/hyperf/session can help you. A similar issue: https://github.com/swoole/swoole-src/issues/4197
I've used the ContextManager class sample and I am trying to print context ID and the collection of context id, I'm getting nothing. Getting the same context ID on different requests.
Also this is how I am using swoole with my application in index.php
use Swoole\Http\Server as HttpServer;
use Swoole\Coroutine as Co;
use Swoole\Http\Request;
use Swoole\Http\Response;
//enable Hooks
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
$server = new HttpServer('127.0.0.1', 8000);
$server->on('start', function ($server) {
echo "Server started at http://127.0.0.1:8000\n";
});
$server->on('request', function (Request $request, Response $response){
$app = new Application($request, $response);
$app->routes['GET']['/'] = [SiteController::class, 'home'];
$app->routes['GET']['/home'] = [SiteController::class, 'home'];
$app->routes['GET']['/contact'] = [SiteController::class, 'contact'];
$app->routes['POST']['/contact'] = [SiteController::class, 'contact'];
$app->routes['GET']['/about'] = [SiteController::class, 'about'];
$app->routes['GET']['/stuck'] = [SiteController::class, 'stuck'];
$app->routes['GET']['/coroutine'] = [SiteController::class, 'coroutineID'];
$app->routes['GET']['/contexts'] = [SiteController::class, 'contexts'];
$app->run($request, $response);
});
$server->start();
In the application the request according to the 'request_uri' and 'request_method' is served with the corresponding controller and the method. In the controller I'm just printing the coroutine ID and am getting the same coroutine ID for different windows/browsers.
use Swoole\Http\Response;
use Swoole\Http\Request;
use Swoole\Coroutine as Co;
class ContextManager
{
// Set is used to save a new value under the context
public function set(string $key, mixed $value)
{
// Get the context object of the current coroutine
$context = Co::getContext();
// Long way of setting a new context value
$context[$key] = $value;
//$content->key = $value;
// Short method of setting a new context value, same as above code...
//Co::getContext()[$key] = $value;
}
// Navigate the coroutine tree and search for the requested key
public function get(string $key, mixed $default = null): mixed
{
// Get the current coroutine ID
$cid = Co::getCid();
do
{
/*
* Get the context object using the current coroutine
* ID and check if our key exists, looping through the
* coroutine tree if we are deep inside sub coroutines.
*/
if(isset(Co::getContext($cid)[$key]))
{
return Co::getContext($cid)[$key];
}
// We may be inside a child coroutine, let's check the parent ID for a context
$cid = Co::getPcid($cid);
} while ($cid !== -1 && $cid !== false);
// The requested context variable and value could not be found
return $default ?? throw new InvalidArgumentException(
"Could not find `{$key}` in current coroutine context."
);
}
public function getCoID()
{
return Co::getCid();
}
public function getAllContexts()
{
return Co::list();
}
}
I'm calling the getAllContexts(), getCoID() method in the controller methods. For the first method I'm getting nothing and for the second I'm getting '1' on different windows/browsers.
How can I set unique Coroutines on different windows, so that I can start implementing some sort of session storage in the ContextManager??
@twose Perhaps I'm getting the same coroutine ID because there is only one coroutine generated instead of different coroutines generated for different windows/browsers.
Try to set worker_num
to 1 on the Server to debug this problem, because your requests may be dispatched to different worker processes, and cid always starts from 1.
@twose You're right about that the cid always starts from 1 and increments on each request. How can I get some sort of unique id that keeps track which window/client initiated this request. I'm trying to build a session manager, but can't store a unique key because each request increments the cid. This is what is returned when I echo Co::getAllContexts() :
{"0":1}
//next request
{"0": 2}
// next request
{"0": 3}
You should save session data to redis or files, so that can be used across processes
@matyhtf In order to save data in redis, I need some sort of unique key, if I set my redis session data on basis of my coroutine ID, then it would be a disaster because that would change on every request. I need some sort of unique ID, all of my sessions should be distinct. Why can't I get/regenerate the session ID without the session functions ??
Generate a token (anything you like, such as a random string), bind the token to the user in DB, and send the token to the client by set cookie. Then the client needs to access the server with the cookie, now you can get its token from the cookie, then use the token to get the user from DB. That's how session libraries work, is that what you're asking? I am not sure...
@twose Yes, that is what I asked, I'll look into it. Thanks a ton.
Hello, So I've built an MVC project from scratch. I wanted to integrate this library for asynchronous requests. After integrating I'm having issues logging in users and keeping them logged in.
Please answer these questions before submitting your issue. Thanks!
Below is the sessionManager class which is initiated inside my application class. So what happens is on each request a session object is initialized and that object checks given the session id if there is a user stored in the $_SESSION global. It retrieves the user object from that global given 'user' key. This is how my project worked before using swoole.
After swoole I replaced $_SESSION with php-redis and I use the redis object to set , get and delete key values in the redis-server. I've checked my php-redis, because it works fine outside of this swoole project.
What did you expect to see? I was expecting the session_id to stay consistent given that session_start() checks if there is a session already, it then uses that very same id to continue between pages.
What did you see instead? I am seeing different session ids generated on each request. I can't login users with this functionality.
I've also tried without the session_start() function in the constructor, in that case the session is stored and a user can login and logout just ok. But, there is only one session id no other session id generated to differentiate between sessions. Only one user can be logged in at a time.
php --ri swoole
)? swooleuname -a
&php -v
&gcc -v
) ? uname:php version:
gcc -v :
Anyone who can tell how to properly implement sessions in this framework. Thanks in advance.