So I’m having an issue getting Server Side Events working with PHP. I’ve tried various different tutorials online that utilise an infinite while loop but all of my attempts end up in a 500 error after a couple of minutes, instead of the data being sent.
For my application I need the script to keep running in an infinite loop as I’m getting updates from a hardware device via TCP sockets, and for the device to send me updates I have to keep the socket connection open.
My setup is as follows:
PHP Version 7.3.33
Windows Server 2022 with IIS 10 (Also tried on Windows Server 2016 with IIS 10)
output_buffering and zlib.output_compression are both set to "Off"
responseBufferLimit is set to 0 in the FastCGI Handler settings for PHP.
The basic test code I’m currently using is as follows:
sse.php
<?PHP
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true) {
$now = date('r');
echo "data: The time is : {$now}nn";
@ob_flush();
flush();
sleep(2);
}
?>
test.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
</head>
<body>
<script>
var source = new EventSource("sse.php");
source.onopen = function(e) {
console.log("The connection to your server has been opened");
}
source.onmessage = function(e) {
console.log ("message: " + e.data);
}
source.onerror = function(e) {
console.log("The server connection has been closed due to some errors");
}
</script>
</body>
</html>
This should (in theory) send a data string to the client with the current time every 2 seconds, but instead is 500 erroring. I must add it is only when a while loop is implemented. If I remove the while loop then it works with the client reconnecting every 3 seconds (which won’t work for my application).
The PHP logs only show the following errors which don’t appear to be linked to my issue, unless anyone can suggest otherwise:
[17-Nov-2022 21:26:28 UTC] PHP Warning: Module ‘mysqli’ already loaded in Unknown on line 0
[17-Nov-2022 21:26:28 UTC] PHP Warning: Module ‘mbstring’ already loaded in Unknown on line 0
[17-Nov-2022 21:26:28 UTC] PHP Deprecated: Directive ‘track_errors’ is deprecated in Unknown on line 0
I’ve searched for days for a solution with nothing working so far. Does anyone have any suggestions on potential settings that need altering with the IIS/PHP setup to get this to work?
Some tutorials have suggested making these config changes:
php.ini > output_buffering and zlib.output_compression set to "Off"
responseBufferLimit is set to 0 in the FastCGI Handler settings for PHP.
But neither of these have had any effect on the script.
2
Answers
So after a lot of trial and error I have figured out the issue. If anyone else has a similar issue here are the steps I took.
It would appear PHP is referenced 2 times in my IIS installation (the second time just as Fast-CGI which is how I missed it the first time round, so I had to add the "responseBufferLimit = 0" to both handlers. This enabled the infinite loop to work without a 500 error.
On the Server configuration page within IIS there are some options for FastCGISettings. Within there is a setting for the "Request Timeout". By default this is set to 90 seconds. I've set this to 600 seconds (or 10 minutes) and now I get a constant stream of data for 10 minutes before the script times out and starts again. You can only choose a value between 10 and 2592000 seconds, but 10 minutes should be plenty for my application.
Big thanks to everyone who offered suggestions!
The HTTP 500 error is server error. It is usually caused by using infinite loop that exceeds PHP’s memory limit or exceeds timeout limit in PHP. It may cause 500 error and will not be written to logs.
You can increase memory limit via PHP. This sets the maximum amount of memory in bytes that a script is allowed to allocate. For more information about “memory_limit” you can refer to this.