Laravel SSE start sending the events after long time - javascript

I am integrating the SSE with laravel 5.7 on a server in php 7.4 (prod&local) but locally I receive the events without problem, unfortunately the client can wait up to 10 minutes to start receiving the events. And especially on the server side according to my logs, it starts sending the events as soon as the connection is opened, I wonder what could be blocking (or buffering) the results for sending them to after some time what can crash my server in prod.
Controller
public function index()
{
return response()->stream(function () {
try{
while(true){
Log::info("in".now());
echo "data: " . now() . "\n\n";
ob_flush();
flush();
Log::info("out".now());
sleep(3);
}
}catch(\Exception $e){
Log::error($e->getMessage());
}
if (connection_aborted()) {break;}
}, 200, [
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive'
]);
}
Javascript
<script>
window.onload= function(){
console.log('loaded')
var source = new EventSource('{{route("myroute",['transaction_id'=>$payment->trans->id])}}');
source.addEventListener("message", function(event) {
const trans = event.data;
console.log(Date(),trans)
});
source.onerror = (e)=>{
console.log(e)
}
</script>

Related

Why XmlHttpRequest wait until complete PHP response (proc_open) even with flush?

I 'm trying to execute commands (wp cli) with xhr.
My problem is when i call my file deploy.php with the javascript.
Without JS call the script works, the flush is immediate.
When i call deploy.php in a XmlHttpRequest, the response wait until the end of the php execution.
I try different commands (grep / wp cli / find) but the result is the same.
I work on WSL Debian + Chrome.
// PHP
public function liveExecuteCommand($cmd, $ajax = false)
{
ob_start();
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "error-output.txt", "a")
);
$output = '';
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
while ($s = fread($pipes[1], 8192)) {
$output .= $s;
print $s;
$this->doFlush();
}
fclose($pipes[1]);
$return_value = proc_close($process);
//echo "La commande a retourné $return_value\n";
}
if ($ajax == false) {
return $output;
}
}
$obj->liveExecuteCommand($cmd, true);
die();
// JS
function getLiveStream() {
var ajax = new XMLHttpRequest();
var url = 'https://www.monsite.local/deploy.php';
ajax.open('GET', url, true);
ajax.onprogress = function() {
document.getElementById("xhr_cmd_result").innerHTML = ajax.responseText;
console.log('onprogress');
}
ajax.onload = function() {
console.log('onload');
}
ajax.onreadystatechange = function() {
document.getElementById("xhr_cmd_result").innerHTML = ajax.responseText;
console.log('statechange');
}
ajax.send();
}
window.addEventListener('DOMContentLoaded', (event_loaded) => {
document.getElementById("xhr_cmd").onclick = getLiveStream;
});
In the Google chrome console, the result display all status directly (after 1 min), like the php result.
statechange
onprogress
statechange
onprogress
statechange
onprogress
statechange
onload
I would like have a console.log every time that the flush is called.
No problem when i execute the php file in the browser, the problem is certainly in the javascript.
How do I solve the problem?
Let me explain you in simple words.
Javascript's XMLHttpRequest(AJAX) call will request to server. It will only waits for response from server(final output from your php page), irrespective to internal process of server.

JS Event Listener check on PHP session infinitely

I want my page to consistently check if the user session is still active.
if using event listener. My concern is that php file execution time is limited. is there way to set php execution to infinite? or is there a better way of doing this?
JS:
$(document).ready(function() {
var loginSource = new EventSource("/structure/ajax/check_login_session.php");
loginSource.addEventListener("login-verification", function(e) {
var response = JSON.parse(e.data);
if (data.login_failed) {
login_fail_redirect();
}
});
})
php
function send_response() {
if (empty($_SESSION['user_info']) || empty($_SESSION['user_info']['active'])) {
$response = array("status" => "failed", "login_failed" => 1);
} else {
$response = array("status" => "success", "login_failed" => 0);
}
echo "event: login-verification\n";
echo 'data: '.json_encode($response);
echo "\n\n";
flush();
}
while (true) {
send_response();
sleep(2);
}
Use a javascript setInterval instead. It will send timed requests to the backend to check if the session is active or not.
$(document).ready(function() {
setInterval(function {
var loginSource = new EventSource("/structure/ajax/check_login_session.php");
loginSource.addEventListener("login-verification", function(e) {
var response = JSON.parse(e.data);
if (data.login_failed) {
login_fail_redirect();
}
});
},1000); //time in ms
})
Then replace this code from your backend:
while (true) {
send_response();
sleep(2);
}
to
send_response();

How to implement WebSocket to communicate with a server that has SSL enabled?

I am trying to implement WebSocket communication between a client "web browser" and a Apache 2.4/PHP 5.6 server that is running on Windows 2008 R2.
My application is assume to be running on this URL "HTTPS"
https://myApllication.example.com
I am not sure if there is something I need to install on the server before this works or not.
My code so far looks like this
$(function(){
if(!("WebSocket" in window)){
console.log('your browser does not support WebSocket');
} else {
connect();
$('#disconnect').click(function(){
socket.close();
});
}
function connect(){
var socket;
var host = "ws://myApplication.example.com:8000/dev/icws/poll2.php";
try{
var socket = new WebSocket(host, {
protocolVersion: 13,
origin: 'https://www.example.com'
});
message('Socket Status: '+socket.readyState);
socket.onopen = function(){
message('Socket Status: '+socket.readyState+' (open)');
}
socket.onmessage = function(msg){
message('Received: ' + msg.data);
}
socket.onclose = function(){
message('Socket Status: '+ socket.readyState + ' (Closed)');
}
} catch(exception){
message(exception);
}
} //End connect()
function message(msg){
console.log(msg);
}//End message()
});
This code will give me this error in the console.
DOMException [SecurityError: "The operation is insecure."
code: 18
nsresult: 0x80530012
Here is how my poll2.php script looks like
<?php
header("Content-Type: text/event-stream" . PHP_EOL);
header("Cache-Control: no-cache" . PHP_EOL);
echo "data: {mykey: 'myvalue', eventName: 'eventName'}" . PHP_EOL . PHP_EOL;
?>
** Edited**
After changing the host from
var host = "ws://myApplication.example.com:8000/dev/icws/poll2.php";
to
var host = "wss://myApplication.example.com:8000/dev/icws/poll2.php";
I no longer get the security error but I get this in the console.
Socket Status: 0 (ready)
Socket Status: 3 (Closed)
Firefox can't establish a connection to the server at wss://myApplication.example.com:8000/dev/icws/poll2.php
What could be causing the connection not to be made?
Do I have to open the port 8000 on the server?

retriving user information through Paypal Javascript login button

i have integrated paypal login button (javascript button) and when i am clicking on it its getting to the paypal site for authentication.
following is my code for paypal button
<span id="paypal"></span>
<script src="https://www.paypalobjects.com/js/external/api.js"></script>
<script>
var url = document.URL;
paypal.use( ["login"], function(login) {
login.render ({
"appid": "***",
"authend": "sandbox",
"scopes": "profile email address phone https://uri.paypal.com/services/paypalattributes",
"containerid": "paypal",
"locale": "en-us",
"returnurl": "http://stereotribes.dev/login"
});
});
</script>
after successful authentication its redirecting me to my server url again.
now my question is how to receive user information after authentication done.
i have searched around paypal site but i am not getting the clear idea to retrieve user informatoin.
can anybody help me in this?
Thanks in advance
Take a look at Instant Payment Notification (IPN). It will POST transaction data to a listener script you have configured on your server immediately when transactions happen, so you can automate tasks like updating your database, sending email notifications, etc. in real-time.
If you need data available on your return URL you can use Payment Data Transfer (PDT), which is very similar to IPN. The only thing about that is if people don't make it back to your return URL for some reason then that code will never run, so it's not recommended that you do any database updates, email notifications, or anything like that from your return URL.
Again, IPN will be triggered regardless of whether they make it back, so you can rest assured that code will run as expected.
After wasting 1 day i came up with the following code(solution), hope it may save someone's time ...
in my return url ("http://stereotribes.dev/login") i have written following code ...
if($_REQUEST['code']) {
$model->getPaypalEmail($_REQUEST['code']);
}
$_REQUEST['code'] (token) will be send by paypal and same code we have send back via curl to confirm identity...
public function getPaypalEmail($code){
if($code){
$strGetCodePaypalLoginDetails = $code;
if ($strGetCodePaypalLoginDetails != '') {
// Change this curl_init url according to your environment.
$ch = curl_init("https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice");
$flag_result = 1;
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => 'client_id=********&client_secret=*****&grant_type=authorization_code&code=' . $strGetCodePaypalLoginDetails,
CURLOPT_RETURNTRANSFER => 1
)
);
$arrResponse = curl_exec($ch);
if ($arrResponse === false) {
$arrResponseToken = 'Curl error: ' . curl_error($ch);
$flag_result = 0;
} else {
//Operation completed without any errors
$arrResponse = json_decode($arrResponse);
$strAccess_Token = $arrResponse->{'access_token'};
// Change this curl_init url according to your environment.
$chToken = curl_init("https://api.sandbox.paypal.com/v1/identity/openidconnect/userinfo/?schema=openid&access_token=" . $strAccess_Token);
curl_setopt_array($chToken, array(
CURLOPT_RETURNTRANSFER => 1
)
);
$arrResponseToken = curl_exec($chToken);
if ($arrResponseToken === false) {
$arrResponseToken = 'Curl error: ' . curl_error($chToken);
$flag_result = 0;
}
}
}
$arrResponseToken = json_decode($arrResponseToken, true);
print_r($arrResponseToken); //here you will get info from paypal
}
}

PHP Comet cause page reload slow

Hi I am tring to implement the comet with PHP and jquery. The comet is started on every page load. However it cause loading of any page in the website become very slow like 10 seconds, it seem to be waiting for the previous request to the server to die() at the if($elapse > 10)
But if a ajax connection connection is aborted, isn't the PHP should stop executing furher ? Any idea why reloading page become slow ?
function getPendingCheckin()
{
ignore_user_abort(false);
$iCreatedDate = $this->input->post("iLastCreateDate");
$aCheckin = [];
$prev = time();
while(! $aCheckin )
{
$aCheckin = $this->getData();
if($aCheckin || connection_aborted() == 1)
{
break;
}
else
{
sleep(1);
$elapse = time() - $prev;
if($elapse > 10)
{
die();
}
}
}
header('Content-type: application/json');
echo json_encode($aCheckin);
}
Javascript
$(window).ready(function(){
var iLastCreateDate = $('#iLastCreateDate').val();
function startGetPendingCheckin()
{
$.ajax({
type: "POST",
url: "/kc/comet/getPendingCheckin",
data: 'iLastCreateDate=' + iLastCreateDate,
error : function(msg)
{
//alert("Error get pending checkin");
},
success :function(o)
{
if(o)
{
//process data
}
startGetPendingCheckin();
}
});
}
startGetPendingCheckin();
})
No, php execution is not (always) aborted. I noticed that on heavy scripts runned on local machine.
You may fail to run 2 parallel request to php scripts due to not closed session. Usually it is auto-closed after termination of the script. With default behavior (sessions in lockable files, no manual closing) it is not possitble to have 2 simultaneous requests from the same user — the latter would be blocked by the former and will wait for its termination.
You may close session as long as you checked everything about user authorization.

Categories

Resources