Swoole-src: headers sent when ob start enabled

Created on 23 Jul 2018  ·  10Comments  ·  Source: swoole/swoole-src

1. the demo code below

$http = new swoole_http_server("0.0.0.0", 9501);
$http->on('request', function ($request, $response) {
    $headers_sent = 'false';
    if (headers_sent()) {
        $headers_sent = 'true';
    }

    ob_start();
    echo 'headers sent: ';
    $result = ob_get_contents();
    ob_end_clean();

    $response->end($result . $headers_sent);
});
$http->start();

2. the issue:

open the browser with address http://127.0.0.1:9501
browser output:
headers sent: false

then refresh the page, the output will always is:
headers sent: true

it means headers already sent. for example session can't start:
session_start(): Cannot send session cookie - headers already sent

it seems ob_start() caused the headers_sent return true, when I remove ob_start,
headers_sent return false (that is right)

is it an issue ? what can I do for session_start with ob_start ?

3. php --ri swoole

swoole
swoole support => enabled
Version => 4.0.3
Author => Swoole Group[email: [email protected]]
coroutine => enabled
epoll => enabled
eventfd => enabled
timerfd => enabled
signalfd => enabled
spinlock => enabled
rwlock => enabled
async http/websocket client => enabled
pcre => enabled
zlib => enabled
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled

Directive => Local Value => Master Value
swoole.aio_thread_num => 2 => 2
swoole.display_errors => On => On
swoole.use_namespace => On => On
swoole.use_shortname => On => On
swoole.fast_serialize => Off => Off
swoole.unixsock_buffer_size => 8388608 => 8388608

question

All 10 comments

You can't use headers_sent, it's not PHP-FPM.
You should use swoole_http_request and swoole_http_response

function swoole_http_response->header(string $key, string $value, bool $ucwords = true);

yes I see. but I want to use the php builtin session_start(), and with ob_start(). session_start will check the headers sent.
I can found that the swoole-framework also supported to use the builtin session_start

@xrjxs
swoole-framework is not the framework by swoole, it's just named swoole, you can't use traditional functions such as session_*, headers in swoole.

@twose I tested session_* can use in the swoole and works prefect. but not good with ob_start.

if ($_GET['seesion_cookie']) {
  session_id($_GET['session_cookie']);
  session_start();
   // also can do this below if session_id not working
   //$fileName = session_save_path() . "/sess_$sessionId";
   //$content = file_get_contents($fileName);
   //session_decode($content);
} else {
  if (session_status() != PHP_SESSION_ACTIVE) {
    session_start();
    session_regenerate_id();
    swoole_http_response->cookie( ... add session cookie here );
  }
}

@xrjxs
Yes you can do these but session_* use PHP file functions, it's synchronous blocking, and when it operates session file, all the server would be blocked.
you can use swoft-session, and you can only use ob_* with swoole ver >= 4.0.2, we just solve the global output controller problem.

@twose, @xrjxs,
The library upscalesoftware/swoole-session implements compatibility of PHP sessions with Swoole.

@sshymko
You make some mistakes, session_* functions is blocked (expect you use Swoole\Runtime::enableCoroutine), and you use global var $SESSION but you have not separated it by coroutine's uid (context processing), this will cause disaster when high concurrency, when a coroutine yield and switch to the other coroutine, the other coroutine will change the global vars, when the previous one resume, it will get the wrong global values.

@twose,
Thanks for the code review and the explanation!
I need to test this, but I think session_start() blocks execution until session_end_write() is called. All the code between session_start() and session_end_write() is synchronous regardless of whether it uses co-routines or not. If I'm wrong then disabling co-routines is a requirement.

@sshymko swoft-cloud/swoft-session Reference for you, or maybe you could just use it.

@huangzhhui,
Yes, upscalesoftware/swoole-session references the Swoft sessions in the README docs ;)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

godtail picture godtail  ·  4Comments

jerryli1 picture jerryli1  ·  4Comments

jobs-git picture jobs-git  ·  3Comments

nick-zh picture nick-zh  ·  3Comments

andreybolonin picture andreybolonin  ·  4Comments