TL;DR update: Whether closing an EventSource from the client or closing the client entirely, php continues to execute on the backend and fails to report the correct value for connection_aborted()
. Why might this be?
I have been all over Google and Stack Overflow looking for answers to this, but none of the suggested fixes resolve the issue: I have a simple page testing the functionality of server-sent events using JavaScript and php. Everything was working well until I realized that server script execution did not stop when a client navigated to another page or refreshed itself. This appears to be a mon problem and the suggestions given in other questions have borne no fruit for me.
StackOverflow questions I've already investigated
PHP Event Source keeps executing (the ments on the accepted answer here almost led to something and then they pulled out to "continue this discussion in chat" and that link is apparently broken)
PHP Server Sent Events Connection won't close?
How do I put this on Real-Time? I already put (async: True) but it doesnt work
PHP connection_aborted() not working correctly
PHP doesn't detect connection abort at all
Linked articles & other material I've already investigated
/
I have stripped the code of everything that I thought could be a possible culprit and I'm still having the issue. I am especially surprised that connection_aborted
continues to report false
after the explicit EventSource.close()
call in the client or simply closing the client before the 10 second server loop has finished. Here is my exact code, after stripping out everything but the server-sent event stuff:
sse_tests.js
document.addEventListener('DOMContentLoaded', () => {
// Set up EventSource for receiving server-sent events.
const testEventSource = new EventSource('sse_tests.php');
testEventSource.addEventListener('test', (e) => {
const data = JSON.parse(e.data);
console.log(`count: ${data.count}`);
if (data.count >= 5) {
testEventSource.close();
}
});
});
sse_tests.php
<?php
// Set the event stream header(s).
header("Cache-Control: no-cache");
header("Content-Type: text/event-stream");
// XXX Override automatic detection of client abortion; we'll do it ourselves.
// (This was suggested in another answer, and I have the same issue with or without it)
ignore_user_abort(true);
// Initialize an arbitrary count parameter to investigate client munication.
$count = 1;
while ($count <= 10) {
$eventData = json_encode(array(
"count" => $count,
));
echo "event: test\n";
echo "data: ${eventData}";
echo "\n\n";
ob_flush();
flush();
$aborted = connection_aborted();
error_log("count: ${count}, connection_aborted: ${aborted}");
if ($aborted) {
break;
}
$count++;
sleep(1);
}
The client successfully opens the connection, tracks it for 5 emissions of the test
event and then stops seeing any further emissions of the test
event, but the server continues to execute for the full count of 10, even after the testEventSource.close()
call or a closing of the browser window before the full count of 10, as evidenced by the server log contents here:
count: 1, connection_aborted: 0
count: 2, connection_aborted: 0
count: 3, connection_aborted: 0
count: 4, connection_aborted: 0
count: 5, connection_aborted: 0
count: 6, connection_aborted: 0
count: 7, connection_aborted: 0
count: 8, connection_aborted: 0
count: 9, connection_aborted: 0
count: 10, connection_aborted: 0
I'm on shared hosting with php 7.2 and minimal tweaks to server configuration. Let me know if that could be the source of strife, and I'll try to investigate more of the default configurations and share whatever else is needed.
TL;DR update: Whether closing an EventSource from the client or closing the client entirely, php continues to execute on the backend and fails to report the correct value for connection_aborted()
. Why might this be?
I have been all over Google and Stack Overflow looking for answers to this, but none of the suggested fixes resolve the issue: I have a simple page testing the functionality of server-sent events using JavaScript and php. Everything was working well until I realized that server script execution did not stop when a client navigated to another page or refreshed itself. This appears to be a mon problem and the suggestions given in other questions have borne no fruit for me.
StackOverflow questions I've already investigated
PHP Event Source keeps executing (the ments on the accepted answer here almost led to something and then they pulled out to "continue this discussion in chat" and that link is apparently broken)
PHP Server Sent Events Connection won't close?
How do I put this on Real-Time? I already put (async: True) but it doesnt work
PHP connection_aborted() not working correctly
PHP doesn't detect connection abort at all
Linked articles & other material I've already investigated
https://www.html5rocks./en/tutorials/eventsource/basics/
https://developer.mozilla/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
I have stripped the code of everything that I thought could be a possible culprit and I'm still having the issue. I am especially surprised that connection_aborted
continues to report false
after the explicit EventSource.close()
call in the client or simply closing the client before the 10 second server loop has finished. Here is my exact code, after stripping out everything but the server-sent event stuff:
sse_tests.js
document.addEventListener('DOMContentLoaded', () => {
// Set up EventSource for receiving server-sent events.
const testEventSource = new EventSource('sse_tests.php');
testEventSource.addEventListener('test', (e) => {
const data = JSON.parse(e.data);
console.log(`count: ${data.count}`);
if (data.count >= 5) {
testEventSource.close();
}
});
});
sse_tests.php
<?php
// Set the event stream header(s).
header("Cache-Control: no-cache");
header("Content-Type: text/event-stream");
// XXX Override automatic detection of client abortion; we'll do it ourselves.
// (This was suggested in another answer, and I have the same issue with or without it)
ignore_user_abort(true);
// Initialize an arbitrary count parameter to investigate client munication.
$count = 1;
while ($count <= 10) {
$eventData = json_encode(array(
"count" => $count,
));
echo "event: test\n";
echo "data: ${eventData}";
echo "\n\n";
ob_flush();
flush();
$aborted = connection_aborted();
error_log("count: ${count}, connection_aborted: ${aborted}");
if ($aborted) {
break;
}
$count++;
sleep(1);
}
The client successfully opens the connection, tracks it for 5 emissions of the test
event and then stops seeing any further emissions of the test
event, but the server continues to execute for the full count of 10, even after the testEventSource.close()
call or a closing of the browser window before the full count of 10, as evidenced by the server log contents here:
count: 1, connection_aborted: 0
count: 2, connection_aborted: 0
count: 3, connection_aborted: 0
count: 4, connection_aborted: 0
count: 5, connection_aborted: 0
count: 6, connection_aborted: 0
count: 7, connection_aborted: 0
count: 8, connection_aborted: 0
count: 9, connection_aborted: 0
count: 10, connection_aborted: 0
I'm on shared hosting with php 7.2 and minimal tweaks to server configuration. Let me know if that could be the source of strife, and I'll try to investigate more of the default configurations and share whatever else is needed.
Share Improve this question edited Apr 21, 2020 at 12:17 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Apr 17, 2020 at 14:29 SheffDoinWorkSheffDoinWork 7932 gold badges9 silver badges20 bronze badges 15-
What is the value of
connection_status()
? – miknik Commented Apr 21, 2020 at 21:40 - @miknik The status is 0 (NORMAL) – SheffDoinWork Commented Apr 21, 2020 at 21:42
-
in your php.ini do you have these two lines?
output_buffering = 0 implicit_flush = 1
– miknik Commented Apr 21, 2020 at 22:00 - 1 Sounds like you have some output buffering going on somewhere. I just copied your code to my server and it works perfectly. – miknik Commented Apr 22, 2020 at 0:11
- 1 Correct, and console log on the web page updates with each count at the expected interval. – miknik Commented Apr 22, 2020 at 1:48
2 Answers
Reset to default 2 +50Based on the updated information, I believe this is definitely wrong:
ignore_user_abort(true);
This should be:
ignore_user_abort(false);
... so that the disconnect is not ignored. What's happening after that is something of a mystery. MDN reports that the connection is persistent, so it could be a bug in the browser that does not close the connection. It could be a problem with a load balancer or reverse proxy, if those are present. It could be a problem in the web server. Or it could be a problem in the PHP configuration.
In the chat it looks like the test server was most likely nginx with PHP running under FastCGI. Are you using Apache with mod_php instead? If so, does it still happen when you run PHP as a CGI? That should help isolate the issue further.
I would also use connection_status() just so you can be more certain about the connection state. https://www.php/manual/en/features.connection-handling.php
Well. The problem is likely happening because you are using an intermediate server (e.g., proxy). So when you send a close
event from the client i.e., testEventSource.close();
, the connection between the client and the proxy must be closed and the problem you are likely to have is the proxy is keeping the connection with the server, hence, that's why you have the connection open from the server side.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745337226a4623162.html
评论列表(0条)